Pattern
Tabs
Sections of a record or a page, as buttons that switch in place or links that navigate, with count pills.
Copy it from /
Button tabs with counts and an indicator
Switch a section in place. The row is a tablist: each tab has role tab and the current one aria-selected, with no aria-current since nothing navigates, and Left, Right, Home, and End move between tabs. Give it an `id` from `useId` and spread `tabPanelProps(id, tab)` on the element that shows the selected section, which the selected tab’s aria-controls names. A count shows in a pill, zero included, and the flag marks flagged answers.
- Route
- /
dashboard/ accounts/ :acctId/ sites/ :siteId/ submitted-forms/ :kind?review=:id - Screenshot
- docs/
agents/ ui-patterns/ drawer-tabs-footer-1440.png
<Tabs
id={tabsId}
items={[
{
key: 'overview',
label: 'Overview',
},
{
key: 'answers',
label: 'Answers',
count: 117,
indicator: 'flag',
},
{
key: 'contracts',
label: 'Contracts',
count: 0,
},
{
key: 'notes',
label: 'Notes',
count: 5,
},
{
key: 'history',
label: 'History',
count: 23,
},
]}
selected={tab}
onSelect={setTab2}
/>
<div
{...tabPanelProps(tabsId, tab)}
>
{/* the selected section */}
</div>Link tabs
Navigate. The tab whose path matches the page exactly is current, whatever the search string, so a link can keep the list’s filters. Here they switch between the gallery’s own pages; the snippet shows the paths the Animals layout builds.
- Route
- /
dashboard/ accounts/ :acctId/ sites/ :siteId/ animal-list/ :group
<Tabs
items={[
{
key: 'active',
label: 'Active',
count: 37,
to: `${siteBaseUrl}/active`,
},
{
key: 'action-required',
label: 'Action Required',
count: 701,
to: `${siteBaseUrl}/action-required`,
},
{
key: 'completed',
label: 'Completed',
count: 330,
to: `${siteBaseUrl}/completed`,
},
]}
/>An overflowing row
The row never wraps or becomes a dropdown. It scrolls sideways, keeps the current tab in view clear of the fade, and fades at a clipped edge. When this page opens, Sponsors is current; each other tab opens its own gallery page, where that tab is current.
- Route
- /
dashboard/ accounts/ :acctId/ sites/ :siteId/ animals/ :group/ :id/ edit
<Tabs
items={[
{
key: 'edit',
label: 'Edit Animal',
to: `${siteBaseUrl}/edit`,
},
{
key: 'medical',
label: 'Medical',
to: `${siteBaseUrl}/medical`,
},
{
key: 'notes',
label: 'Notes',
to: `${siteBaseUrl}/notes`,
},
{
key: 'submissions',
label: 'Applications',
count: 4,
to: `${siteBaseUrl}/submissions`,
},
{
key: 'contracts',
label: 'Contracts',
count: 2,
to: `${siteBaseUrl}/contracts`,
},
{
key: 'history',
label: 'History',
to: `${siteBaseUrl}/history`,
},
{
key: 'sponsors',
label: 'Sponsors',
count: 3,
to: `${siteBaseUrl}/sponsors`,
},
]}
/>