# TabsScrollArea
**đź“– Live documentation:** https://cds.coinbase.com/components/navigation/TabsScrollArea/
Horizontal scroll container for tab rows on web, with chevron controls, edge gradients, and automatic scroll-into-view for the active tab.
## Import
```tsx
import { TabsScrollArea } from '@coinbase/cds-web/tabs'
```
## Examples
TabsScrollArea is the recommended wrapper when a [Tabs](/components/navigation/Tabs/) row may overflow horizontally. Pass a **function child** that receives `onActiveTabElementChange` and spread that onto **`Tabs`** (along with shared accessibility props) so the scroll region can measure tab positions and scroll the active tab into view.
### Basics
Pair **`TabsScrollArea`** with **`Tabs`**, **`DefaultTab`**, and **`DefaultTabsActiveIndicator`**. Set **`width`** / **`maxWidth`** on **`TabsScrollArea`** so the row overflows on smaller viewports; chevron controls and edge gradients appear when there is offscreen content.
```jsx live
function Example() {
const tabs = [
{ id: 't1', label: 'Overview' },
{ id: 't2', label: 'Markets' },
{ id: 't3', label: 'Trade' },
{ id: 't4', label: 'Earn' },
{ id: 't5', label: 'Learn' },
{ id: 't6', label: 'More' },
];
const [activeTab, setActiveTab] = useState(tabs[0]);
return (
{({ onActiveTabElementChange }) => (
)}
);
}
```
### Overflow indicator
On web, the default **`TabsScrollAreaOverflowIndicator`** combines a fade gradient with chevron controls.
#### Custom `OverflowIndicatorComponent`
Provide your own component that matches **`TabsScrollAreaOverflowIndicatorProps`**: **`direction`** (`'left'` \| `'right'`), **`show`**, **`onClick`**, plus optional **`styles`** / **`classNames`** slots. **`TabsScrollArea`** passes **`accessibilityLabel`** for the side control—forward it to a button or **`IconButton`** when you build a custom control.
```jsx live
function Example() {
const tabs = [
{ id: 't1', label: 'Overview' },
{ id: 't2', label: 'Markets' },
{ id: 't3', label: 'Trade' },
{ id: 't4', label: 'Earn' },
{ id: 't5', label: 'Learn' },
{ id: 't6', label: 'More' },
];
const [activeTab, setActiveTab] = useState(tabs[0]);
const CustomOverflowIndicator = useCallback(
({ accessibilityLabel, direction, show, onClick, style, className }) => {
if (!show) {
return null;
}
return (
);
},
[],
);
return (
{({ onActiveTabElementChange }) => (
)}
);
}
```
### Styling
Use **`styles`** / **`classNames`** to target the root, scroll container, and overflow controls (`overflowIndicator`, `overflowIndicatorButton`, `overflowIndicatorButtonContainer`, `overflowIndicatorGradient`, and related slots on web).
### Accessibility
Set **`accessibilityLabel`** on **`TabsScrollArea`** for the scrollable tab list region. On web, customize **`previousArrowAccessibilityLabel`** and **`nextArrowAccessibilityLabel`** for the default overflow controls. Ensure **`Tabs`** also has a meaningful **`accessibilityLabel`** for the tablist, as in the [Tabs](/components/navigation/Tabs/) examples.
## Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `children` | `(props: TabsScrollAreaRenderProps) => ReactNode` | Yes | `-` | Render function that receives onActiveTabElementChange (wire to Tabs as onActiveTabElementChange). |
| `OverflowIndicatorComponent` | `FC` | No | `-` | Component rendered at each end when content overflows (left / right). Defaults to {@link TabsScrollAreaOverflowIndicator}. Props must extend {@link TabsScrollAreaOverflowIndicatorProps}. |
| `alignContent` | `ResponsiveProp` | No | `-` | - |
| `alignItems` | `ResponsiveProp` | No | `-` | - |
| `alignSelf` | `ResponsiveProp` | No | `-` | - |
| `aspectRatio` | `ResponsiveProp` | No | `-` | - |
| `autoScrollOffset` | `number` | No | `50` | Horizontal offset when auto-scrolling to the active tab (e.g. so the active tab is not under a paddle). |
| `background` | `ResponsiveProp` | 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 | `-` | - |
| `className` | `string` | No | `-` | Merged with the root HStack. |
| `classNames` | `{ root?: string; scrollContainer?: 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 | `-` | Passed to the {@link TabsScrollAreaOverflowIndicator} to render compact sub-components (IconButton compact). |
| `dangerouslySetBackground` | `string` | No | `-` | - |
| `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 | `-` | - |
| `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 | `-` | - |
| `right` | `ResponsiveProp>` | No | `-` | - |
| `rowGap` | `ResponsiveProp` | No | `-` | - |
| `style` | `CSSProperties` | No | `-` | Merged with the root HStack. |
| `styles` | `{ root?: CSSProperties; scrollContainer?: 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 | `-` | - |
| `zIndex` | `ResponsiveProp` | No | `-` | - |
## Styles
| Selector | Static class name | Description |
| --- | --- | --- |
| `root` | `-` | Root layout element |
| `scrollContainer` | `-` | Horizontal scroll region wrapping Tabs |
| `overflowIndicator` | `-` | Applied to each overflow indicators root (style / className on the rendered component) |
| `overflowIndicatorButton` | `-` | - |
| `overflowIndicatorButtonContainer` | `-` | - |
| `overflowIndicatorGradient` | `-` | - |