Navigation
Which component to use for moving between places, switching views, or narrowing what a list shows. Find the job, take the component, and read the “not when” before you commit: it names the thing people reach for by mistake, and what to use instead.
At a glance
| Job | Use | Not when | Instead | Because |
|---|---|---|---|---|
| Show where this page sits in a hierarchy, with a way back up | Breadcrumbs | You need the list of places someone can go | Sidebar | Breadcrumbs show the path here, not the other places. |
| The path is a sequence of steps in a process | Stepper | A stepper shows position in a sequence; breadcrumbs show position in a hierarchy. | ||
| You are stepping through items of a set in place | PagerChip | The pager chip says "4 of 19" and moves to the next one without leaving. | ||
| Let someone type to find and run any command or go anywhere, from anywhere | CommandPalette | Someone is choosing a value for a field by typing | Combobox | A combobox fills a field in a form; a palette runs a command and closes. |
| There are a few actions on one thing | Menu | A menu button opens beside its trigger and does not take the page over. | ||
| A frequent action wants one key of its own on one screen — J for next, E for done | Shortcuts | A single-key shortcut acts at once and has to be possible to turn off; the palette is a search opened by a chord. | ||
| The person is browsing places rather than searching | Sidebar | The rail shows every place at once; a palette shows only what matches. | ||
| Let a narrow column of long names be read by scrolling, one at a time | Dock | The list is the app's places | Sidebar | A rail of places has short names and marks the current page. |
| There is room for each row to show its name and a line of provenance | Item | An item list shows every row in full; a dock only grows the one in focus. | ||
| The column can simply be made wider by the reader | Split | A resizable pane gives width persistently instead of momentarily. | ||
| Show an attribute of a row, and narrow the list to it when pressed | Facet | The value is a status — done, failed, at risk | Tag | A tag reports a state in a reserved tone; a facet is a neutral name and value. |
| The dimension is not on the rows, or the reader needs every value listed | Filter | A filter lists the values of a dimension in a menu above the list. | ||
| Narrow a list by one dimension, beside the other dimensions | Filter | The dimension is already printed on every row | Facet | The attribute on the row can be the control; there is no filter panel to go and find. |
| The choice is between two or three views of the same thing | Segmented | Views are all present and equal; a filter removes rows. | ||
| The choice swaps the panel of content | Tabs | Tabs swap panels; a filter narrows one list and can combine with others. | ||
| The person is entering a value on a form, not narrowing a list | Select | A filter has an "any" state and acts at once; a form field holds a value until submit. | ||
| Open and close the navigation on a narrow screen | Hamburger | The button opens a list of actions, not navigation | Menu | A menu button opens a menu of actions with its own keyboard contract. |
| The screen is wide enough to show the links | Nav | Navigation that fits should be visible, not behind a button. | ||
| Put the product's name and its top-level places across the top of every page | Nav | There are more places than fit across the top, or they fall into groups | Sidebar | A rail holds a long, grouped list of places down the side. |
| The options swap panels inside one page | Tabs | Tabs are panels in one place; nav items are places with their own URLs. | ||
| The reader needs to see where this page sits in a hierarchy | Breadcrumbs | Breadcrumbs show the path to here; the nav shows where you can go. | ||
| The header has to collapse on a phone | Hamburger | The hamburger is the button that opens the links in a drawer on a narrow screen. | ||
| Step through a set one item at a time without leaving the place you are in | PagerChip | Jumping to any page of a long list | Pagination | Pagination draws the page numbers; the chip only steps to the neighbour. |
| Under a table, saying which rows are on show | TablePager | The table pager carries the range and the pages for a table. | ||
| The person is moving through steps of a task | Stepper | A stepper says which steps are done; a pager chip has no notion of done. | ||
| Move between numbered pages of a long set | Pagination | Paging rows of a table | TablePager | The table pager adds "Showing 26–50 of 61", renders nothing for one page, and is wired to usePagedTable. |
| Stepping through a set one item at a time without leaving a pane | PagerChip | "4 of 19" with previous and next is one control; a page list is many. | ||
| Showing position in a sequence of steps the person is working through | Stepper | Steps have state — done, current, failed; pages do not. | ||
| Pick one of two or three views of the same thing | Segmented | Each option shows a different panel of content | Tabs | A segmented control is a radiogroup, not a tablist; it changes how one thing is shown, not which thing. |
| The options narrow a list, or there may be more than three values | Filter | A filter is a dimension with a value; spelled out as a strip it grows across the page and hides which dimensions exist. | ||
| Each choice needs a description or a figure under it | RadioCards | A radio card carries a title, a note and a figure, and the whole card is the hit target. | ||
| There are more than a handful of options to pick from | Select | A long run of segments stops reading as one control; a select holds the list behind one field. | ||
| List every place in an app down the side, grouped, with the current one marked | Sidebar | The options are panels of one page | Tabs | Tabs swap panels in place; a sidebar moves between pages. |
| The items are a nested hierarchy the reader opens and closes — folders, a taxonomy | Tree | A tree has the keyboard contract for expand and collapse at any depth; the rail is one level of places. | ||
| The column is a long list of records or documents, not places | Dock | A dock lets every name be read at the focus point in a narrow column; a sidebar truncates them. | ||
| The column is a document's own headings | Contents | Contents tracks where you are in the document as you scroll. | ||
| Swap between panels of different content in one place | Tabs | The options are views of the same content — a range, a grouping, list or grid | Segmented | A segmented control is a radiogroup that changes how one thing is shown; a tablist promises a different panel per tab. |
| The options narrow a list by a dimension — status, owner, type | Filter | A filter is a dimension with a value and sits beside other dimensions; tabs cannot combine. | ||
| The options are pages with their own URLs in an app | Sidebar | Places are navigation and take aria-current="page"; tabs are panels inside one page. | ||
| The sections should be readable one after another, several open at once | Accordion | An accordion keeps every section in reading order; tabs hide all but one. | ||
| Browse a nested hierarchy, opening and closing branches | Tree | The hierarchy is the app's places, one level deep | Sidebar | A rail of places is links with aria-current, not a tree. |
| The sections are content to read, opened and closed in place | Accordion | An accordion discloses content panels; a tree selects nodes in a hierarchy. | ||
| The structure is layers that cover one another — needs to tests, plan to milestones | LayeredGraph | Coverage between layers is a graph, not a hierarchy. |
Breadcrumbs
Show where this page sits in a hierarchy, with a way back up.
Use when
- A page several levels down — a work item inside a project inside a client — where going up a level is common.
- The last crumb is the current page, rendered as text with
aria-current="page"; separators are added for you.
Not when
- You need the list of places someone can go →
Sidebar. Breadcrumbs show the path here, not the other places. - The path is a sequence of steps in a process →
Stepper. A stepper shows position in a sequence; breadcrumbs show position in a hierarchy. - You are stepping through items of a set in place →
PagerChip. The pager chip says "4 of 19" and moves to the next one without leaving.
CommandPalette
Let someone type to find and run any command or go anywhere, from anywhere.
Use when
- An app with many places and actions, where a keyboard user wants ⌘K / Ctrl+K and a search (
useCommandPalettebinds it). - It takes the page over as a modal: focus stays in the search, arrows move the highlight, Enter runs.
Not when
- Someone is choosing a value for a field by typing →
Combobox. A combobox fills a field in a form; a palette runs a command and closes. - There are a few actions on one thing →
Menu. A menu button opens beside its trigger and does not take the page over. - A frequent action wants one key of its own on one screen — J for next, E for done →
Shortcuts. A single-key shortcut acts at once and has to be possible to turn off; the palette is a search opened by a chord. - The person is browsing places rather than searching →
Sidebar. The rail shows every place at once; a palette shows only what matches.
Dock
Let a narrow column of long names be read by scrolling, one at a time.
Use when
- A long list of records in a narrow column, where every name would otherwise be truncated: the one at the focus point grows to be legible.
- Reading must not open anything —
onSelectfires on a click and on Enter, never on scroll or focus.
Not when
- The list is the app's places →
Sidebar. A rail of places has short names and marks the current page. - There is room for each row to show its name and a line of provenance →
Item. An item list shows every row in full; a dock only grows the one in focus. - The column can simply be made wider by the reader →
Split. A resizable pane gives width persistently instead of momentarily.
Facet
Show an attribute of a row, and narrow the list to it when pressed.
Use when
- A row carries a recorded fact — "Owner · Dana", "Against · ISO 27001" — that a reader may want to filter by.
- Showing an attribute plainly: without
onClickit renders as a span, so a row does not change shape when the dimension becomes filterable. - A missing value: an empty one renders nothing; pass
mutedwith the absence in words when you know why.
Filter
Narrow a list by one dimension, beside the other dimensions.
Use when
- A table or list can be narrowed by Type, Status or Owner; put one
Filterper dimension in aFiltersrow. - The trigger reads as the dimension until it holds a value, so a row of them says what can be narrowed.
- Several values of one dimension at once ("gaps and conflicts") — pass
multiple; values are OR-ed.
Not when
- The dimension is already printed on every row →
Facet. The attribute on the row can be the control; there is no filter panel to go and find. - The choice is between two or three views of the same thing →
Segmented. Views are all present and equal; a filter removes rows. - The choice swaps the panel of content →
Tabs. Tabs swap panels; a filter narrows one list and can combine with others. - The person is entering a value on a form, not narrowing a list →
Select. A filter has an "any" state and acts at once; a form field holds a value until submit.
Hamburger
Open and close the navigation on a narrow screen.
Use when
- The header's links do not fit on a phone; this button opens them, usually in a
Drawer. - One button whose bars morph to an X, driven by
openand announced througharia-expanded;labelis required.
PagerChip
Step through a set one item at a time without leaving the place you are in.
Use when
- The head of a side pane that walks a set in order — sources, open findings, attachments:
‹ S4 of 19 ›. - In a
Drawerheader, so the way to the next item never scrolls away.
Not when
- Jumping to any page of a long list →
Pagination. Pagination draws the page numbers; the chip only steps to the neighbour. - Under a table, saying which rows are on show →
TablePager. The table pager carries the range and the pages for a table. - The person is moving through steps of a task →
Stepper. A stepper says which steps are done; a pager chip has no notion of done.
Pagination
Move between numbered pages of a long set.
Use when
- Search results, a gallery or a feed served a page at a time, where the page number is a place.
- Building your own pager:
PaginationItemtakesaria-current="page";PaginationGapis the elided run.
Not when
- Paging rows of a table →
TablePager. The table pager adds "Showing 26–50 of 61", renders nothing for one page, and is wired tousePagedTable. - Stepping through a set one item at a time without leaving a pane →
PagerChip. "4 of 19" with previous and next is one control; a page list is many. - Showing position in a sequence of steps the person is working through →
Stepper. Steps have state — done, current, failed; pages do not.
Segmented
Pick one of two or three views of the same thing.
Use when
- Two or three mutually exclusive views of one set — Week / Month / Quarter, List / Grid.
- Seeing the alternatives side by side is the point, and the strip is only as wide as the choices.
- A short either/or answer in a form, named with
labelso the group reads as a question.
Not when
- Each option shows a different panel of content →
Tabs. A segmented control is a radiogroup, not a tablist; it changes how one thing is shown, not which thing. - The options narrow a list, or there may be more than three values →
Filter. A filter is a dimension with a value; spelled out as a strip it grows across the page and hides which dimensions exist. - Each choice needs a description or a figure under it →
RadioCards. A radio card carries a title, a note and a figure, and the whole card is the hit target. - There are more than a handful of options to pick from →
Select. A long run of segments stops reading as one control; a select holds the list behind one field.
Sidebar
List every place in an app down the side, grouped, with the current one marked.
Use when
- An app with more places than fit in a header, in groups under mono headings (
SidebarGroup). - Groups that come from data use
SidebarSection, which can fold its items away when the rail is long. - A place that cannot hold anything yet stays a link, quieter, with why in its
title— not disabled, not hidden.
Not when
- The options are panels of one page →
Tabs. Tabs swap panels in place; a sidebar moves between pages. - The items are a nested hierarchy the reader opens and closes — folders, a taxonomy →
Tree. A tree has the keyboard contract for expand and collapse at any depth; the rail is one level of places. - The column is a long list of records or documents, not places →
Dock. A dock lets every name be read at the focus point in a narrow column; a sidebar truncates them. - The column is a document's own headings →
Contents. Contents tracks where you are in the document as you scroll.
Tabs
Swap between panels of different content in one place.
Use when
- Each option shows a different panel — Overview, Activity, Settings — and only one is on screen at a time.
- The panels are siblings of equal weight and the reader moves between them without leaving the page.
Not when
- The options are views of the same content — a range, a grouping, list or grid →
Segmented. A segmented control is a radiogroup that changes how one thing is shown; a tablist promises a different panel per tab. - The options narrow a list by a dimension — status, owner, type →
Filter. A filter is a dimension with a value and sits beside other dimensions; tabs cannot combine. - The options are pages with their own URLs in an app →
Sidebar. Places are navigation and takearia-current="page"; tabs are panels inside one page. - The sections should be readable one after another, several open at once →
Accordion. An accordion keeps every section in reading order; tabs hide all but one.
Tree
Browse a nested hierarchy, opening and closing branches.
Use when
- Folders, a taxonomy, a nested set of requirements — any depth, with a count or size at the end of each row.
- The whole tree is one Tab stop: Up/Down move through visible rows, Right expands then descends, Left collapses then rises.
Not when
- The hierarchy is the app's places, one level deep →
Sidebar. A rail of places is links witharia-current, not a tree. - The sections are content to read, opened and closed in place →
Accordion. An accordion discloses content panels; a tree selects nodes in a hierarchy. - The structure is layers that cover one another — needs to tests, plan to milestones →
LayeredGraph. Coverage between layers is a graph, not a hierarchy.
Other guides: Screens · Overlays · Status and feedback · Data · Input · Reading · Agents and live work
Generated from the when.ts beside each component — the same data the Claude Code plugin reads.