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
  • Accessibility
  • Figma Course tabs 3842:32295
  • packages/ui/src/components/TabStrip

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.

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.

bash
pnpm add @nuton/ui @nuton/tokens @remixicon/react
tsx
import '@nuton/tokens/tokens.css'
import '@nuton/ui/styles.css'

Usage

tsx
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 onAdd to 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

Open tabBg/Weak-50 and aria-selected.
Being writtenA small spinner and a hidden “still being written”. Live only (C94).

Composition examples

Under the top bar of the lesson page, above the TableOfContents. See Learner → Lesson in the product review.

API reference

Props

Tab strip props
PropTypeDefaultDescription
tabsTabStripTab[]—The courses: { id, title, format?, status? }.
activeIdstring—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.
labelsPartial<TabStripLabels>—Strings: add, generating.
aria-labelstring—Names the tab list. Always set it.

Accessibility

Keyboard

KeyBehaviour
TabMoves into the strip on the open tab, then on to the plus button.
ArrowRight / ArrowLeftMoves focus between tabs (reversed in right-to-left).
Home / EndFirst and last tab.
Enter / SpaceOpens 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)

Do and don't

DoShow it when there are two or more courses It is a way to move between them.
Don'tShow a strip of one A single tab is noise.