Skip to content
FrastoUI

Tabs

Status: Experimental

Tabs switches related views without navigation. The default underline variant uses one quiet baseline and a short active rule. The segmented variant adds a restrained square track and a moving square selection indicator without changing tab semantics.

Account overview content.
Invoice content.
Activity content.
Recent chat conversations.
Recent email conversations.
---
import { Tab, TabPanel, Tabs } from '@freight-px/frasto';
---
<Tabs label="Customer sections" defaultValue="overview">
<Tab slot="tab" value="overview">Overview</Tab>
<Tab slot="tab" value="invoices">Invoices</Tab>
<TabPanel slot="panel" value="overview">...</TabPanel>
<TabPanel slot="panel" value="invoices">...</TabPanel>
</Tabs>

Every tab and panel pair shares the same value. The slot attributes are required so Frasto can preserve the tab-list and panel relationships in server-rendered markup.

  • Only the active tab is in the ordinary Tab sequence.
  • Left and Right arrows move and activate the adjacent enabled tab.
  • Home and End activate the first and last enabled tab.
  • Focus moves with selection.
  • Disabled tabs are skipped.
Prop Type Default Purpose
label string required accessible tab-list name
defaultValue string first enabled tab initial selected value
variant "underline" | "segmented" "underline" visual presentation; behavior remains identical
class string — styles the root
listClass string — styles the tab list

Both require value. Tab also accepts native button attributes and disabled; TabPanel accepts native div attributes. Selection emits a bubbling frasto:tab-change event with { value } in detail.

  • IDs, aria-controls, aria-labelledby, aria-selected, and roving tabindex are wired automatically.
  • All panels remain readable if JavaScript does not initialize; enhancement hides inactive panels.
  • Long tab lists scroll horizontally rather than becoming pills or wrapping into ambiguous rows.
  • The segmented indicator follows variable tab widths and stops moving when reduced motion is requested.
  • Use ordinary links with aria-current="page" when changing routes instead of client-side views.