Tab strip
TabStrip is the row of courses a learner made together, one tab for each uploaded material, with a plus to add another. Use it above a lesson when more than one course belongs to the same set of materials.
Beta until design confirms the narrow-screen behaviour, which Figma does not draw (C94).
Preview
Three courses made from three files, the second one open, with the add button.
<TabStrip
aria-label="Courses made from your materials"
tabs={tabs}
activeId="ppt"
onSelect={open}
onAdd={addCourse}
/>Installation
Availability
@nuton/ui and @nuton/tokens are private workspace packages and aren't published yet (D4, D12). Inside the Nuton monorepo, add them as workspace dependencies.
pnpm add @nuton/ui @nuton/tokens @remixicon/reactnpm install @nuton/ui @nuton/tokens @remixicon/reactyarn add @nuton/ui @nuton/tokens @remixicon/reactimport '@nuton/tokens/tokens.css'
import '@nuton/ui/styles.css'Usage
import { TabStrip } from '@nuton/ui'
const tabs = [
{ id: 'pdf', title: 'The Design of Everyday Things', format: 'pdf' },
{ id: 'ppt', title: 'Introduction to Design Principles', format: 'ppt' },
]
<TabStrip aria-label="Courses made from your materials" tabs={tabs} activeId={current} onSelect={setCurrent} />- Show it only when more than one course was made from the learner's materials; with a single course, leave it out (live does the same).
- Each tab is one uploaded material, with its format icon and a title cut with an ellipsis at 216px.
- Always give the strip an
aria-label. - Pass
onAddto show the plus button at the end. - A course still being written shows a small spinner (
status: 'generating').
Variants and sizes
One size: a 48px row.
Sizes
Row 48 tall with 24px side padding and a hairline under it. Each tab is 32 tall, at most 216 wide, with a 24px format icon; dividers are 24 tall.
States and interactions
aria-selected.Composition examples
Under the top bar of the lesson page, above the TableOfContents. See Learner → Lesson in the product review.
API reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
tabs | TabStripTab[] | — | The courses: { id, title, format?, status? }. |
activeId | string | — | The course open now. |
onSelect | (id: string) => void | — | Called when a tab is chosen. |
onAdd | () => void | — | Shows the plus button at the end and calls this. |
labels | Partial<TabStripLabels> | — | Strings: add, generating. |
aria-label | string | — | Names the tab list. Always set it. |
Accessibility
Keyboard
| Key | Behaviour |
|---|---|
| Tab | Moves into the strip on the open tab, then on to the plus button. |
| ArrowRight / ArrowLeft | Moves focus between tabs (reversed in right-to-left). |
| Home / End | First and last tab. |
| Enter / Space | Opens the focused course. |
Screen readers
A tab list named by your label; the open tab is selected; the format icon is decorative and the dividers are hidden.
Focus
Roving: the open tab is the one tab stop, and arrows move focus without opening a course until Enter or Space.
Contrast and colour
Sub-600 text on white and Strong-950 on the open tab are above 4.5:1. The open tab is marked by its band and aria-selected, not by colour alone.
Touch and pointer
Tabs are 32px tall and the plus button is 36px; the strip scrolls sideways when the tabs do not fit.
You must: give the strip an accessible name and keep each course title unique.
Figma mapping
Frame 1321319362 (3842:32295) in the lesson frames: tabs up to 216px with a File Format icon, Content Dividers between, and a 36px plus button. Live: CourseTabs.
Guidelines and related components
Use Tab strip for
- Courses made together from several uploaded materials
Don't use Tab strip for
- Switching views inside a page (use Tabs)
- A single course (leave it out)