# SidebarItem **📖 Live documentation:** https://cds.coinbase.com/components/navigation/SidebarItem/ A navigation item component designed to work within a Sidebar. ## Import ```tsx import { SidebarItem } from '@coinbase/cds-web/navigation/SidebarItem' ``` ## Examples ### Basics SidebarItem requires an `icon` and `title`. Place it inside a Sidebar component which provides context for collapsed state and variant styling. ```jsx live function BasicSidebarItem() { const [active, setActive] = useState(false); return ( }> setActive(!active)} title="Home" tooltipContent="Home" /> ); } ``` ### Active State Use the `active` prop to indicate the currently selected navigation item. The active state changes the text and icon color to provide visual feedback. ```jsx live function ActiveState() { const [activeIndex, setActiveIndex] = useState(0); const items = [ { title: 'Home', icon: 'home' }, { title: 'Assets', icon: 'chartPie' }, { title: 'Trade', icon: 'trading' }, { title: 'Settings', icon: 'cog' }, ]; return ( }> {items.map((item, index) => ( setActiveIndex(index)} title={item.title} tooltipContent={item.title} /> ))} ); } ``` ### Collapsed State When the parent Sidebar is collapsed, SidebarItem automatically hides the title text and shows only the icon. Use `tooltipContent` to display a tooltip on hover, which is essential for usability since the title is hidden. ```jsx live function CollapsedState() { const [collapsed, setCollapsed] = useState(true); const [activeIndex, setActiveIndex] = useState(0); const items = [ { title: 'Home', icon: 'home' }, { title: 'Assets', icon: 'chartPie' }, { title: 'Trade', icon: 'trading' }, ]; return ( } renderEnd={() => ( setCollapsed(!collapsed)} /> )} > {items.map((item, index) => ( setActiveIndex(index)} title={item.title} tooltipContent={item.title} /> ))} ); } ``` ### Styling #### Border Radius The default border radius is `1000` (pill shape) for the default sidebar variant. You can customize it with the `borderRadius` prop. ```jsx live function CustomBorderRadius() { return ( }> ); } ``` ### Custom Component Use the `Component` prop to render a completely custom layout while still benefiting from SidebarItem's state management. Your custom component receives `icon`, `title`, `color`, `active`, and `isCollapsed` props. ```jsx live function CustomComponent() { const [activeIndex, setActiveIndex] = useState(0); const items = [ { title: 'Dashboard', icon: 'home', badge: 3 }, { title: 'Messages', icon: 'speechBubble', badge: 12 }, { title: 'Analytics', icon: 'chartBar', badge: 0 }, ]; const CustomSidebarContent = ({ icon, title, color, active, isCollapsed }) => ( {!isCollapsed && ( {title} {items.find((i) => i.title === title)?.badge > 0 && ( {items.find((i) => i.title === title)?.badge} )} )} ); return ( }> {items.map((item, index) => ( setActiveIndex(index)} title={item.title} tooltipContent={item.title} /> ))} ); } ``` ### Accessibility SidebarItem automatically sets `accessibilityLabel` to the `title` value and uses `aria-current="page"` when active. When collapsed, the accessibility label is applied to the Pressable to ensure screen readers announce the item correctly. Provide a custom `accessibilityLabel` for more descriptive screen reader announcements. ```jsx live function Accessibility() { const [activeIndex, setActiveIndex] = useState(0); const items = [ { title: 'Home', icon: 'home', label: 'Navigate to home page' }, { title: 'Assets', icon: 'chartPie', label: 'View your asset portfolio' }, { title: 'Trade', icon: 'trading', label: 'Open trading interface' }, ]; return ( }> {items.map((item, index) => ( setActiveIndex(index)} title={item.title} tooltipContent={item.title} /> ))} ); } ``` ## Props | Prop | Type | Required | Default | Description | | --- | --- | --- | --- | --- | | `icon` | `IconName` | Yes | `undefined` | The Navigation Icon this item represents | | `Component` | `ElementType` | No | `-` | Optional presentational component to render for the SidebarItem. By default, the SidebarItem will render as a row with an Icon and Headline Text element The component must implement the CustomSidebarItemProps props interface | | `active` | `boolean` | No | `false` | Use the active prop to identify the current page | | `alignContent` | `ResponsiveProp
` | No | `-` | - | | `alignItems` | `ResponsiveProp
` | No | `-` | - | | `alignSelf` | `ResponsiveProp
` | No | `-` | - | | `as` | `button` | No | `-` | The underlying element or component the polymorphic component will render. Changing as also changes the inherited native props (e.g. href for as=a) and the expected ref type. | | `aspectRatio` | `ResponsiveProp` | No | `-` | - | | `blendStyles` | `InteractableBlendStyles` | No | `-` | - | | `block` | `boolean` | No | `-` | Set element to block and expand to 100% width. | | `borderBottomLeftRadius` | `ResponsiveProp` | No | `-` | - | | `borderBottomRightRadius` | `ResponsiveProp` | No | `-` | - | | `borderBottomWidth` | `ResponsiveProp` | No | `-` | - | | `borderColor` | `Color` | No | `-` | Border color of the element. | | `borderEndWidth` | `ResponsiveProp` | No | `-` | - | | `borderRadius` | `ResponsiveProp` | No | `-` | - | | `borderStartWidth` | `ResponsiveProp` | No | `-` | - | | `borderTopLeftRadius` | `ResponsiveProp` | No | `-` | - | | `borderTopRightRadius` | `ResponsiveProp` | No | `-` | - | | `borderTopWidth` | `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 | `-` | - | | `collapsed` | `boolean` | No | `false` | Use collapsed to show only the logo | | `color` | `ResponsiveProp` | No | `-` | - | | `columnGap` | `ResponsiveProp` | No | `-` | - | | `dangerouslySetBackground` | `string` | No | `-` | - | | `disablePortal` | `boolean` | No | `false` | - | | `disabled` | `boolean` | No | `-` | Is the element currently disabled. | | `display` | `ResponsiveProp` | No | `-` | - | | `elevation` | `ResponsiveProp` | No | `-` | - | | `flexBasis` | `ResponsiveProp>` | No | `-` | - | | `flexDirection` | `ResponsiveProp` | No | `-` | - | | `flexGrow` | `ResponsiveProp` | No | `-` | - | | `flexShrink` | `ResponsiveProp` | No | `-` | - | | `flexWrap` | `ResponsiveProp` | No | `-` | - | | `focusable` | `boolean` | 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 | `-` | - | | `key` | `Key \| null` | No | `-` | - | | `left` | `ResponsiveProp>` | No | `-` | - | | `lineHeight` | `ResponsiveProp` | No | `-` | - | | `loading` | `boolean` | No | `-` | Is the element currenty loading. When set to true, will disable element from press and keyboard events | | `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 | `-` | - | | `noScaleOnPress` | `boolean` | No | `-` | Dont scale element on press. | | `onChange` | `FormEventHandler` | 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 | `-` | - | | `pressed` | `boolean` | No | `-` | Is the element being pressed. Primarily a mobile feature, but can be used on the web. | | `ref` | `((instance: HTMLButtonElement \| null) => void) \| RefObject \| null` | No | `-` | - | | `right` | `ResponsiveProp>` | No | `-` | - | | `rowGap` | `ResponsiveProp` | No | `-` | - | | `style` | `CSSProperties` | 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 | `-` | - | | `title` | `string` | No | `undefined` | The title of the page this item represents | | `tooltipContent` | `ReactNode` | No | `-` | Label or content to display when Sidebar is collapsed and sidebar more menu is hovered | | `top` | `ResponsiveProp>` | No | `-` | - | | `transform` | `ResponsiveProp` | No | `-` | - | | `transparentWhilePressed` | `boolean` | No | `-` | Mark the background and border as transparent even while element is interacted with (elevation underlay issue). Must be used in conjunction with the pressed prop | | `type` | `button \| reset \| submit` | No | `-` | - | | `userSelect` | `ResponsiveProp` | No | `-` | - | | `value` | `string \| number \| readonly string[]` | No | `-` | - | | `visibility` | `ResponsiveProp` | No | `-` | - | | `zIndex` | `ResponsiveProp` | No | `-` | - |