Props
Usage guidelines
- To break up a large collection of content into logical, digestible views.
- To switch between different, yet related views, such as Updates and Messages.
- When any UI or content above the Tabs is altered upon selection. Use Link instead.
- To break up content that is not related to each other or is not on the same hierarchical level.
Best practices
Place Tabs directly above the target content.
Use Tabs as a way to filter content. Consider using SegmentedControl in this use-case.
Keep Tab labels concise, ideally one to two words.
Truncate labels in Tabs. If there is not enough horizontal space, allow the Tabs to scroll horizontally.
Order Tabs by relevance — the first tab should be the most logical starting view. Ideally, sequence Tabs by association — tabs with similar content should be adjacent to each other.
Disable or hide Tabs if a Tab's content is empty. There should always be at least 2 Tabs. We don't support applying a disabled state for the Tab as it can cause usability and accessibility issues.
Accessibility
Tabs are intended for page-level navigation between multiple URLs. Each tab must have an individual title that precisely describes the tab content. Provide a short, descriptive label for screen-readers using accessibilityLabel
. It is helpful for users of assistive technologies so they have the necessary information to navigate the content efficiently.
Keyboard
Tab key navigates the tabs.
Enter/return key activates a tab (i.e., it navigates to the link href
).
Screen Reader
The tab/link must announce a state of "current" if the href
matches the current window URL.
Localization
Be sure to localize text
and accessibilityLabel
.
The Tab's title should be 3 words or less: long enough to be understood by users but short enough to prevent text wrapping. Aim for a single word when possible.
Variants
Wrapping
Truncate the Button text. In rare instances where Buttons must remain on one line, truncate the text on the secondary Button before truncating on the primary Button.
import { useState } from 'react'; import { Flex, Tabs, Label, Text, Switch, Box } from 'gestalt'; export default function Example() { const [activeIndex, setActiveIndex] = useState(0); const [wrap, setWrap] = useState(false); return ( <Flex height="100%" width="100%" alignItems="center" justifyContent="center" > <Flex alignItems="start" direction="column" gap={{ column: 4, row: 0 }}> <Flex gap={{ row: 4, column: 0 }}> <Label htmlFor="wrap"> <Text>Wrap</Text> </Label> <Switch id="wrap" onChange={() => setWrap(!wrap)} switched={wrap} /> </Flex> <Box borderStyle="sm" maxWidth={500} overflow="auto" padding={1}> <Tabs activeTabIndex={activeIndex} onChange={({ activeTabIndex, event }) => { event.preventDefault(); setActiveIndex(activeTabIndex); }} tabs={[ { href: 'https://pinterest.com', text: 'Boards for You' }, { href: 'https://pinterest.com', text: 'Pins for You' }, { href: 'https://pinterest.com', text: 'Following' }, { href: 'https://pinterest.com', text: 'People to Follow' }, ]} wrap={wrap} /> </Box> </Flex> </Flex> ); }
Indicator
Use the indicator
field on individual tabs to indicate notifications. You can either show a red dot or a number — numbers greater than 99 will be shown as "99+".
import { useState } from 'react'; import { Flex, Tabs } from 'gestalt'; export default function Example() { const [activeIndex, setActiveIndex] = useState(0); return ( <Flex height="100%" width="100%" alignItems="center" justifyContent="center" > <Tabs activeTabIndex={activeIndex} onChange={({ activeTabIndex, event }) => { event.preventDefault(); setActiveIndex(activeTabIndex); }} tabs={[ { href: 'https://pinterest.com', text: 'Boards for You' }, { href: 'https://pinterest.com', text: 'Pins for You', indicator: 'dot', }, { href: 'https://pinterest.com', text: 'Following', indicator: 3 }, { href: 'https://pinterest.com', text: 'People to Follow', indicator: 112, }, ]} wrap /> </Flex> ); }
Background color
import { useState } from 'react'; import { Flex, Tabs, Label, Text, Switch, Box } from 'gestalt'; export default function Example() { const [activeIndex, setActiveIndex] = useState(0); const [isTransparent, setIsTransparent] = useState(false); return ( <Flex gap={4} direction="column" height="100%" width="100%" alignItems="center" justifyContent="center" > <Flex gap={{ row: 4, column: 0 }}> <Label htmlFor="color"> <Text>Transparent background</Text> </Label> <Switch id="color" onChange={() => setIsTransparent((value) => !value)} switched={isTransparent} /> </Flex> <Box borderStyle="sm" color="secondary" paddingX={3} paddingY={1}> <Tabs activeTabIndex={activeIndex} bgColor={isTransparent ? 'transparent' : 'default'} onChange={({ activeTabIndex, event }) => { event.preventDefault(); setActiveIndex(activeTabIndex); }} tabs={[ { href: 'https://pinterest.com', text: 'Boards for You' }, { href: 'https://pinterest.com', text: 'Pins for You' }, { href: 'https://pinterest.com', text: 'Following' }, { href: 'https://pinterest.com', text: 'People to Follow' }, ]} wrap /> </Box> </Flex> ); }
Component quality checklist
Quality item | Status | Status description |
---|---|---|
Figma Library | Ready | Component is available in Figma across all platforms. |
Responsive Web | Ready | Component is available in code for web and mobile web. |
iOS | Component is not currently available in code for iOS. | |
Android | Planned | Component is slotted to be built for Android. |
Related
Link
Link is used to navigate to different areas of the product or to external sites. Link is the preferred component in cases where you want to direct the user to unrelated content.
SegmentedControl
SegmentedControl is used to switch between views within a small area of content, such as a Popover. SegmentedControl is preferred when changing state or selection within a view.