Initial commit
This commit is contained in:
284
skills/skill/references/chrome-140-features.md
Normal file
284
skills/skill/references/chrome-140-features.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Chrome 140+ Features (September 2025+)
|
||||
|
||||
New Chrome Extension APIs introduced in Chrome 140 and later versions.
|
||||
|
||||
## Chrome 140 (September 2025)
|
||||
|
||||
### sidePanel.getLayout()
|
||||
|
||||
Determines the position of the side panel (left or right) in the browser window.
|
||||
|
||||
**Official Documentation:** https://developer.chrome.com/docs/extensions/reference/api/sidePanel#method-getLayout
|
||||
|
||||
#### API Signature
|
||||
|
||||
```typescript
|
||||
chrome.sidePanel.getLayout(): Promise<{
|
||||
side: 'left' | 'right';
|
||||
}>
|
||||
```
|
||||
|
||||
#### Basic Usage
|
||||
|
||||
```typescript
|
||||
// Get current side panel layout
|
||||
const layout = await chrome.sidePanel.getLayout();
|
||||
console.log('Side panel is positioned on the:', layout.side);
|
||||
|
||||
if (layout.side === 'right') {
|
||||
console.log('Side panel is on the right');
|
||||
} else {
|
||||
console.log('Side panel is on the left');
|
||||
}
|
||||
```
|
||||
|
||||
#### Use Cases
|
||||
|
||||
##### 1. RTL Language Support
|
||||
|
||||
```typescript
|
||||
export default defineContentScript({
|
||||
matches: ['*://*'],
|
||||
async main() {
|
||||
const layout = await chrome.sidePanel.getLayout();
|
||||
const documentDir = document.documentElement.dir;
|
||||
|
||||
// Adjust UI based on panel side and text direction
|
||||
if (layout.side === 'right' && documentDir === 'rtl') {
|
||||
// Apply RTL-optimized positioning
|
||||
applyRTLStyles();
|
||||
}
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
##### 2. Dynamic Content Positioning
|
||||
|
||||
```typescript
|
||||
// Popup component
|
||||
function App() {
|
||||
const [panelSide, setPanelSide] = useState<'left' | 'right'>('left');
|
||||
|
||||
useEffect(() => {
|
||||
chrome.sidePanel.getLayout().then(({ side }) => {
|
||||
setPanelSide(side);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`panel-${panelSide}`}>
|
||||
<p>Panel is positioned on the {panelSide}</p>
|
||||
{/* Adjust UI layout based on panel side */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
##### 3. Optimal Notification Placement
|
||||
|
||||
```typescript
|
||||
// Background script
|
||||
browser.alarms.onAlarm.addListener(async (alarm) => {
|
||||
const layout = await chrome.sidePanel.getLayout();
|
||||
|
||||
// Position notifications away from side panel
|
||||
const notificationPosition = layout.side === 'right'
|
||||
? 'bottom-left'
|
||||
: 'bottom-right';
|
||||
|
||||
await chrome.notifications.create({
|
||||
type: 'basic',
|
||||
title: 'Reminder',
|
||||
message: 'Task is due',
|
||||
iconUrl: '/icon/128.png',
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
#### Browser Compatibility
|
||||
|
||||
- **Chrome:** 140+ (September 2025)
|
||||
- **Firefox:** Not yet supported
|
||||
- **Edge:** 140+ (follows Chromium)
|
||||
- **Safari:** Not applicable (no side panel API)
|
||||
|
||||
#### Feature Detection
|
||||
|
||||
Always check if the API is available:
|
||||
|
||||
```typescript
|
||||
async function getSidePanelSide(): Promise<'left' | 'right' | null> {
|
||||
if (chrome.sidePanel?.getLayout) {
|
||||
try {
|
||||
const layout = await chrome.sidePanel.getLayout();
|
||||
return layout.side;
|
||||
} catch (error) {
|
||||
console.error('Failed to get side panel layout:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null; // API not available
|
||||
}
|
||||
```
|
||||
|
||||
#### Integration with WXT
|
||||
|
||||
```typescript
|
||||
// entrypoints/sidepanel/main.tsx
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
function SidePanel() {
|
||||
const [side, setSide] = useState<'left' | 'right'>('left');
|
||||
|
||||
useEffect(() => {
|
||||
// Get initial side
|
||||
chrome.sidePanel.getLayout().then(({ side }) => {
|
||||
setSide(side);
|
||||
});
|
||||
|
||||
// Note: Chrome doesn't fire events when user changes panel side
|
||||
// You may need to periodically check or reload when panel is opened
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={`sidepanel-container side-${side}`}>
|
||||
<header className={side === 'right' ? 'rtl' : 'ltr'}>
|
||||
<h1>Side Panel Content</h1>
|
||||
</header>
|
||||
<main>
|
||||
<p>Current side: {side}</p>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Default Behavior
|
||||
|
||||
- **New Chrome installations (2025+):** May default to right side
|
||||
- **Upgraded Chrome installations:** Retains user's previous preference
|
||||
- **User can change:** Users can move side panel between left and right at any time
|
||||
|
||||
#### Common Patterns
|
||||
|
||||
##### Responsive Layout Adjustment
|
||||
|
||||
```typescript
|
||||
// hooks/useSidePanelPosition.ts
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export function useSidePanelSide() {
|
||||
const [side, setSide] = useState<'left' | 'right'>('left');
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (chrome.sidePanel?.getLayout) {
|
||||
chrome.sidePanel
|
||||
.getLayout()
|
||||
.then(({ side }) => {
|
||||
setSide(side);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to get side panel side:', error);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { side, isLoading };
|
||||
}
|
||||
|
||||
// Usage in component
|
||||
function MyComponent() {
|
||||
const { side, isLoading } = useSidePanelSide();
|
||||
|
||||
if (isLoading) return <LoadingSpinner />;
|
||||
|
||||
return (
|
||||
<div className={`content-${side}`}>
|
||||
{/* Content positioned based on panel location */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Styling Based on Side
|
||||
|
||||
```css
|
||||
/* CSS for panel-aware layouts */
|
||||
.content-left {
|
||||
/* Panel is on left, content flows from right */
|
||||
margin-left: 20px;
|
||||
margin-right: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.content-right {
|
||||
/* Panel is on right, content flows from left */
|
||||
margin-left: 0;
|
||||
margin-right: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* RTL support */
|
||||
[dir="rtl"] .content-left {
|
||||
direction: rtl;
|
||||
}
|
||||
```
|
||||
|
||||
## Staying Updated
|
||||
|
||||
To stay informed about new Chrome Extension features:
|
||||
|
||||
1. **Chrome Extensions What's New:** https://developer.chrome.com/docs/extensions/whats-new
|
||||
2. **Chrome Developers Blog:** https://developer.chrome.com/blog
|
||||
3. **Chrome Platform Status:** https://chromestatus.com/features
|
||||
4. **WXT Changelog:** https://github.com/wxt-dev/wxt/releases
|
||||
|
||||
## Migration Guide
|
||||
|
||||
If your extension currently assumes side panel is always on the left:
|
||||
|
||||
### Before (Assumed Left Side)
|
||||
|
||||
```typescript
|
||||
// Old code - assumes left side
|
||||
function positionContent() {
|
||||
const content = document.getElementById('content');
|
||||
content.style.marginLeft = '400px'; // Fixed left margin
|
||||
}
|
||||
```
|
||||
|
||||
### After (Side-Aware)
|
||||
|
||||
```typescript
|
||||
// New code - adapts to panel side
|
||||
async function positionContent() {
|
||||
const content = document.getElementById('content');
|
||||
|
||||
if (chrome.sidePanel?.getLayout) {
|
||||
const { side } = await chrome.sidePanel.getLayout();
|
||||
|
||||
if (side === 'right') {
|
||||
content.style.marginRight = '400px';
|
||||
content.style.marginLeft = '0';
|
||||
} else {
|
||||
content.style.marginLeft = '400px';
|
||||
content.style.marginRight = '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Related APIs
|
||||
|
||||
- **chrome.sidePanel.open()** - Open side panel programmatically
|
||||
- **chrome.sidePanel.close()** - Close side panel
|
||||
- **chrome.sidePanel.setOptions()** - Configure side panel behavior
|
||||
- **chrome.sidePanel.getOptions()** - Get current side panel configuration
|
||||
|
||||
**Full Side Panel API:** https://developer.chrome.com/docs/extensions/reference/api/sidePanel
|
||||
Reference in New Issue
Block a user