Components

DhTabs

M3E underline tab strip with a sliding, resizing active indicator. Variant (primary/secondary/tertiary/error) is colour only; per-tab content (label / icon / label+icon stacked) is inferred from each item; equal-width or scrollable. Keyboard nav (arrow keys, Home/End).

Variant · primary

Default colour role. The selected label and the sliding 3px indicator pick up --color-primary; the indicator slides and resizes as selection changes.

Active: video
<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'video', label: 'Video' },
    { id: 'photos', label: 'Photos' },
    { id: 'audio', label: 'Audio' }
  ]}
  ariaLabel="Media type"
/>

Variant · secondary

<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'video', label: 'Video' },
    { id: 'photos', label: 'Photos' },
    { id: 'audio', label: 'Audio' }
  ]}
  variant="secondary"
  ariaLabel="Media type"
/>

Variant · tertiary

<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'video', label: 'Video' },
    { id: 'photos', label: 'Photos' },
    { id: 'audio', label: 'Audio' }
  ]}
  variant="tertiary"
  ariaLabel="Media type"
/>

Variant · error

<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'video', label: 'Video' },
    { id: 'photos', label: 'Photos' },
    { id: 'audio', label: 'Audio' }
  ]}
  variant="error"
  ariaLabel="Media type"
/>

Icon only

A tab with an icon and no label renders icon-only. Provide ariaLabel so the tab has an accessible name.

<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'people', icon: 'user', ariaLabel: 'People' },
    { id: 'edit', icon: 'edit', ariaLabel: 'Edit' }
  ]}
  ariaLabel="Quick actions"
/>

Label & icon

A tab that has both a label and an icon stacks them vertically at 64px.

<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'video', label: 'Video', icon: 'film' },
    { id: 'photos', label: 'Photos', icon: 'image' }
  ]}
  ariaLabel="Media type"
/>

Scrollable

Intrinsic-width tabs in a horizontally scrolling strip (90px minimum). The indicator stays aligned while scrolling.

<DhTabs
  bind:value={selected}
  tabs={[
    { id: 'summary', label: 'Summary' },
    { id: 'recordings', label: 'Recordings' },
    { id: 'transcripts', label: 'Transcripts' },
    { id: 'exports', label: 'Exports' }
  ]}
  scrollable
  ariaLabel="Workspace sections"
/>

Disabled tab

Disabled tabs are skipped by arrow-key navigation.

<DhTabs bind:value={selected} tabs={[
  { id: 'one', label: 'One' },
  { id: 'two', label: 'Two' },
  { id: 'three', label: 'Three (disabled)', disabled: true },
  { id: 'four', label: 'Four' }
]} />