# TabbedChipsAlpha
**📖 Live documentation:** https://cds.coinbase.com/components/navigation/TabbedChipsAlpha/
A chip component commonly used in filter context to refine a date source
## Import
```tsx
import { TabbedChips } from '@coinbase/cds-web/alpha/tabbed-chips/TabbedChips'
```
## Examples
### Basic usage
```jsx live
function ExampleDefault() {
const tabs = [
{ id: 'all', label: 'All' },
{ id: 'swap', label: 'Swap' },
{ id: 'collect', label: 'Collect' },
{ id: 'bridge', label: 'Bridge' },
];
const [activeTab, setActiveTab] = useState(tabs[0]);
return ;
}
```
### Compact
```jsx live
function ExampleCompactNoStart() {
const tabs = [
{ id: 'all', label: 'All' },
{ id: 'swap', label: 'Swap' },
{ id: 'collect', label: 'Collect' },
{ id: 'bridge', label: 'Bridge' },
];
const [activeTab, setActiveTab] = useState(tabs[0]);
return ;
}
```
### Many tabs (paddles)
:::tip Paddles & overflow
Paddles appear automatically when the tab list overflows.
:::
```jsx live
function ExampleWithPaddles() {
const tabs = Array.from({ length: 12 }).map((_, i) => ({
id: `tab_${i + 1}`,
label: `Tab ${i + 1}`,
}));
const [activeTab, setActiveTab] = useState(tabs[0]);
return ;
}
```
### With autoScrollOffset
:::tip Auto-scroll offset
The `autoScrollOffset` prop controls the horizontal offset when auto-scrolling the active tab into view, so it stays clear of the leading overflow control. Try selecting tabs near the edges to see the difference.
:::
```jsx live
function ExampleAutoScrollOffset() {
const tabs = Array.from({ length: 25 }).map((_, i) => ({
id: `tab_${i + 1}`,
label: `Tab ${i + 1}`,
}));
const [activeTab, setActiveTab] = useState(tabs[0]);
return (
Default offset (50px)
Custom offset (100px)
);
}
```
### With custom sized overflow controls
:::tip Overflow control styling
Target the chevron buttons with **`styles.overflowIndicatorButton`** (or **`overflowIndicator`** / **`overflowIndicatorGradient`**).
:::
```jsx live
function ExampleCustomOverflowControls() {
const tabs = Array.from({ length: 10 }).map((_, i) => ({
id: `t_${i + 1}`,
label: `Item ${i + 1}`,
}));
const [activeTab, setActiveTab] = useState(tabs[0]);
return (
);
}
```
### Long text tabs
```jsx live
function ExampleLongText() {
const tabs = [
{ id: 'a', label: 'Very long tab label that can wrap on small widths' },
{ id: 'b', label: 'Another extra long label to test overflow' },
{ id: 'c', label: 'Short' },
];
const [activeTab, setActiveTab] = useState(tabs[0]);
return ;
}
```
### Disabled tab
```jsx live
function ExampleDisabled() {
const tabs = [
{ id: 'first', label: 'First' },
{ id: 'second', label: 'Second', disabled: true },
{ id: 'third', label: 'Third' },
];
const [activeTab, setActiveTab] = useState(tabs[0]);
return ;
}
```
### With start media
:::tip Media sizing
For start media, use circular images sized 24×24 for regular chips and 16×16 for compact chips.
:::
```jsx live
function ExampleWithStart() {
const icon = { height: 24, width: 24, shape: 'circle', source: assets.eth.imageUrl };
const compactIcon = { height: 16, width: 16, shape: 'circle', source: assets.eth.imageUrl };
const tabs = [
{ id: 'all', label: 'All', start: },
{ id: 'swap', label: 'Swap', start: },
{ id: 'collect', label: 'Collect', start: },
{ id: 'bridge', label: 'Bridge', start: },
];
const compactTabs = tabs.map((tab) => ({ ...tab, start: }));
const [activeTab, setActiveTab] = useState(tabs[0]);
return (
);
}
```
### Custom TabComponent
:::tip Custom Tab behavior
When providing a custom TabComponent, use `useTabsContext()` and call `updateActiveTab(id)` to update selection state. Reflect the active state (e.g., end icon state) based on `activeTab?.id === id`.
:::
```tsx live noInline
function CustomTab({ id, label, ...props }: TabbedChipProps) {
const { activeTab, updateActiveTab } = useTabsContext();
const isActive = activeTab?.id === id;
return (
}
onClick={() => updateActiveTab(id)}
{...props}
>
{label}
);
}
const tabs = [
{ id: 'all', label: 'All' },
{ id: 'swap', label: 'Swap' },
{ id: 'collect', label: 'Collect' },
];
function Example() {
const [activeTab, setActiveTab] = useState(tabs[0]);
return (
);
}
render();
```
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `activeTab` | `TabValue \| null` | Yes | `-` | React state for the currently active tab. Setting it to null results in no active tab. |
| `onChange` | `(activeTab: TabValue \| null) => void` | Yes | `-` | Callback that is fired when the active tab changes. Use this callback to update the activeTab state. |
| `tabs` | `TabbedChipProps[]` | Yes | `-` | - |
| `TabComponent` | `FC>` | No | `-` | - |
| `TabsActiveIndicatorComponent` | `TabsActiveIndicatorComponent` | No | `-` | - |
| `alignContent` | `ResponsiveProp` | No | `-` | - |
| `alignItems` | `ResponsiveProp` | No | `-` | - |
| `alignSelf` | `ResponsiveProp` | No | `-` | - |
| `aspectRatio` | `ResponsiveProp` | No | `-` | - |
| `autoScrollOffset` | `number` | No | `50` | X position offset when auto-scrolling to active tab (to avoid active tab being covered by the overflow indicator on the left side, default: 50px) |
| `background` | `((Color \| { base?: Color; phone?: Color \| undefined; tablet?: Color \| undefined; desktop?: Color \| undefined; }) & Color) \| undefined` | No | `-` | - |
| `borderBottomLeftRadius` | `ResponsiveProp` | No | `-` | - |
| `borderBottomRightRadius` | `ResponsiveProp` | No | `-` | - |
| `borderBottomWidth` | `ResponsiveProp` | No | `-` | - |
| `borderColor` | `ResponsiveProp` | No | `-` | - |
| `borderEndWidth` | `ResponsiveProp` | No | `-` | - |
| `borderRadius` | `ResponsiveProp` | No | `-` | - |
| `borderStartWidth` | `ResponsiveProp` | No | `-` | - |
| `borderTopLeftRadius` | `ResponsiveProp` | No | `-` | - |
| `borderTopRightRadius` | `ResponsiveProp` | No | `-` | - |
| `borderTopWidth` | `ResponsiveProp` | No | `-` | - |
| `borderWidth` | `ResponsiveProp` | No | `-` | - |
| `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
| `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
| `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
| `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
| `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
| `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
| `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
| `bottom` | `ResponsiveProp>` | No | `-` | - |
| `classNames` | `{ root?: string; scrollContainer?: string \| undefined; tabs?: string \| undefined; overflowIndicator?: string \| undefined; overflowIndicatorButton?: string \| undefined; overflowIndicatorButtonContainer?: string \| undefined; overflowIndicatorGradient?: string \| undefined; } \| undefined` | No | `-` | - |
| `color` | `ResponsiveProp` | No | `-` | - |
| `columnGap` | `ResponsiveProp` | No | `-` | - |
| `compact` | `boolean` | No | `false` | Turn on to use a compact MediaChip for each tab. On web, this is also passed to {@link TabsScrollArea} as compact so the overflow chevron IconButtons use compact sizing. |
| `dangerouslySetBackground` | `string` | No | `-` | - |
| `disabled` | `boolean` | No | `-` | Disable interactions on all the tabs. |
| `display` | `ResponsiveProp` | No | `-` | - |
| `elevation` | `ResponsiveProp` | No | `-` | - |
| `flexBasis` | `ResponsiveProp>` | No | `-` | - |
| `flexDirection` | `ResponsiveProp` | No | `-` | - |
| `flexGrow` | `ResponsiveProp` | No | `-` | - |
| `flexShrink` | `ResponsiveProp` | No | `-` | - |
| `flexWrap` | `ResponsiveProp` | No | `-` | - |
| `font` | `ResponsiveProp` | No | `-` | - |
| `fontFamily` | `ResponsiveProp` | No | `-` | - |
| `fontSize` | `ResponsiveProp` | No | `-` | - |
| `fontWeight` | `ResponsiveProp` | No | `-` | - |
| `gap` | `ResponsiveProp` | No | `1` | The spacing between Tabs |
| `grid` | `ResponsiveProp` | No | `-` | - |
| `gridArea` | `ResponsiveProp` | No | `-` | - |
| `gridAutoColumns` | `ResponsiveProp>` | No | `-` | - |
| `gridAutoFlow` | `ResponsiveProp` | No | `-` | - |
| `gridAutoRows` | `ResponsiveProp>` | No | `-` | - |
| `gridColumn` | `ResponsiveProp` | No | `-` | - |
| `gridColumnEnd` | `ResponsiveProp` | No | `-` | - |
| `gridColumnStart` | `ResponsiveProp` | No | `-` | - |
| `gridRow` | `ResponsiveProp` | No | `-` | - |
| `gridRowEnd` | `ResponsiveProp` | No | `-` | - |
| `gridRowStart` | `ResponsiveProp` | No | `-` | - |
| `gridTemplate` | `ResponsiveProp` | No | `-` | - |
| `gridTemplateAreas` | `ResponsiveProp` | No | `-` | - |
| `gridTemplateColumns` | `ResponsiveProp>` | No | `-` | - |
| `gridTemplateRows` | `ResponsiveProp>` | No | `-` | - |
| `height` | `ResponsiveProp>` | No | `-` | - |
| `justifyContent` | `ResponsiveProp` | No | `-` | - |
| `left` | `ResponsiveProp>` | No | `-` | - |
| `lineHeight` | `ResponsiveProp` | No | `-` | - |
| `margin` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginBottom` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginEnd` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginStart` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginTop` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginX` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `marginY` | `ResponsiveProp<0 \| -5 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1 \| -1.5 \| -2 \| -3 \| -4 \| -6 \| -7 \| -8 \| -9>` | No | `-` | - |
| `maxHeight` | `ResponsiveProp>` | No | `-` | - |
| `maxWidth` | `ResponsiveProp>` | No | `-` | - |
| `minHeight` | `ResponsiveProp>` | No | `-` | - |
| `minWidth` | `ResponsiveProp>` | No | `-` | - |
| `nextArrowAccessibilityLabel` | `string` | No | `-` | - |
| `opacity` | `ResponsiveProp` | No | `-` | - |
| `overflow` | `ResponsiveProp` | No | `-` | - |
| `padding` | `ResponsiveProp` | No | `-` | - |
| `paddingBottom` | `ResponsiveProp` | No | `-` | - |
| `paddingEnd` | `ResponsiveProp` | No | `-` | - |
| `paddingStart` | `ResponsiveProp` | No | `-` | - |
| `paddingTop` | `ResponsiveProp` | No | `-` | - |
| `paddingX` | `ResponsiveProp` | No | `-` | - |
| `paddingY` | `ResponsiveProp` | No | `-` | - |
| `pin` | `PinningDirection` | No | `-` | Direction in which to absolutely pin the box. |
| `position` | `ResponsiveProp` | No | `-` | - |
| `previousArrowAccessibilityLabel` | `string` | No | `-` | - |
| `ref` | `ForwardedRef` | No | `-` | - |
| `right` | `ResponsiveProp>` | No | `-` | - |
| `rowGap` | `ResponsiveProp` | No | `-` | - |
| `style` | `CSSProperties` | No | `-` | - |
| `styles` | `{ root?: CSSProperties; scrollContainer?: CSSProperties \| undefined; paddle?: CSSProperties \| undefined; tabs?: CSSProperties \| undefined; overflowIndicator?: CSSProperties \| undefined; overflowIndicatorButton?: CSSProperties \| undefined; overflowIndicatorButtonContainer?: CSSProperties \| undefined; overflowIndicatorGradient?: CSSProperties \| undefined; } \| undefined` | No | `-` | - |
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
| `textAlign` | `ResponsiveProp` | No | `-` | - |
| `textDecoration` | `ResponsiveProp` | No | `-` | - |
| `textTransform` | `ResponsiveProp` | No | `-` | - |
| `top` | `ResponsiveProp>` | No | `-` | - |
| `transform` | `ResponsiveProp` | No | `-` | - |
| `userSelect` | `ResponsiveProp` | No | `-` | - |
| `visibility` | `ResponsiveProp` | No | `-` | - |
| `width` | `ResponsiveProp>` | No | `100%` | Width of the scroll region; defaults to the full width of the parent. When the tab row is wider than this container, overflow indicators appear. |
| `zIndex` | `ResponsiveProp` | No | `-` | - |
## Styles
| Selector | Static class name | Description |
| --- | --- | --- |
| `root` | `-` | Root container element |
| `scrollContainer` | `-` | Horizontal scroll region wrapping the tab row (aligned with {@link TabsScrollArea}). |
| `paddle` | `-` | - |
| `tabs` | `-` | Tabs root element |
| `overflowIndicator` | `-` | Overflow indicator root |
| `overflowIndicatorButton` | `-` | Overflow indicator icon button. |
| `overflowIndicatorButtonContainer` | `-` | Overflow indicator icon button container. |
| `overflowIndicatorGradient` | `-` | Overflow indicator gradient. |