Tab handbook
v1.3.2 · @snowui-design-system/components
License: Before reading component documentation, source, or npm usage instructions for the first time, read the full LICENSE. Reuse that review for the same task and version. Public API configuration and internal implementation changes have different license implications. All components use the unified runtime package; source rights remain governed by the license.
Overview
Switch among views or content panels in one area using generated items or custom Buttons, with keyboard navigation.
When to use it
Use Tab to switch panels or views in the same area. Choose the underline variant for underlined tabs. Use Segmented for compact parameter choices.
itemssupplies unique values and labels; explicitButton as="item"children replace it.bind:valuetracks the active item. A missing or unmatched value falls back visually without writing a new value; the page renders the corresponding panel.
Quick start
This example shows the recommended basic composition. See the sections below for more cases and composition limits.
API
See the base component documentation for inherited capabilities not redeclared here. This table lists only named public Props declared by this component.
Usage boundaries and details
Default built-in mode / explicit combination mode
Default built-in mode (recommended):
itemsautomatically generates<Button as="item">; item can useiconto declare icon, Tab built-in generatesIcon + Text, suitable foricon-toggle;parts.Button / parts.Icon / parts.Textconfiguration unified Props.Explicit composition: write Button children directly for icons, text, complex content, or different props per item.
Design principle
Button children: No separate TabItem exists. Place
Button as="item" value="..."directly; Button owns its size behavior.Container-owned active appearance: Tab leaves Button source unchanged and controls its active visuals through context and bridge layers.
Shared FLIP indicator: One absolutely positioned
.snowui-tab-indicatormoves and resizes between active items for pill, gray, and underline variants.Composite hover: Child Buttons disable scale-on-hover by default so adjacent items do not overlap. Tab retains its own hover and active feedback; a child or
parts.Buttoncan opt back in.
2.2 Sub-item agreement
The sub-item must be <Button as="item">, and declare it on the Button:
value="xxx"- required, item identification value (thevalueattribute of the root<button>element through Button rest-spread)Optional
disabled- disable a single itemOptional
href- Realize routing Tab through Button'shref(Button will be rendered as<a>)Optional
bare- Use Button without padding / radius / background and do not limit the content type; Tab continues to independently take over the inactive / hover / active transparency through--snowui-button-opacity-overrideon the Button root node, so it does not depend on the default emphasis level of Button bare
Variant="pill"(style 1, default)
The container has a --black-4 background, padding, and the same blur(1.25rem) (20px) backdrop blur as SearchBox. The active item has --static-white-80 and a 0 2px 4px rgba(0,0,0,0.1) shadow. Inactive Text and Icon use --black-100 at opacity: 0.4; active ones use --static-black-100 at opacity: 1. Hover raises only an inactive item’s opacity to 1.
Variant="solid"(style 2)
Container no background, no padding. Activation item: --black-4 background, no shadow. The activation item Text/Icon keeps the button default color chain; the inactivation item Text/Icon uses --black-100 × opacity: 0.4.
Variant="underline"(style 3)
The container has no background and no rounded corners. Sub-item padding 0(override Button). The bottom of the activation item is 2px horizontally underlined (the left 2px vertical line when vertical), the color is --primary; the activation item Text / Icon also uses --primary. Inactivated item Text / Icon uses --black-100 × opacity: 0.4. The sub-item spacing is larger: SM=--gap-3(12) / MD=--gap-4(16) / LG=--gap-5(20).
Variant="icon-toggle"(style 4)
The container matches the pill variant, including SearchBox’s blur(1.25rem) (20px) backdrop blur. Inactive items hide .snowui-text and show only their icon (each item must contain Icon and Text). Active items reveal icon and text; the text fade follows the Frame lifecycle bridge while Frame size motion smoothly expands width.
In generated items mode, icon-toggle uses each item label as its accessible name even while the text is hidden. With explicit children, provide aria-label on each Button. Internal graphics/text spacing belongs to Button; do not wrap each control in an extra Frame.
variant="bare"
The container has no background, padding and rounded corners, and does not display indicator; Item has no background, padding and rounded corners, and only expresses inactive, hover and activated status through opacity: 0.4 -> 1. The content can be text, single Icon or Icon + text. Item gap Reuse the size gradient of underline: SM=12px / MD=16px / LG=20px.
Dynamic effect
Item color and transparency continue to consume Frame default dynamic system. Tab root injects TAB_INDICATOR_MOTION_STYLE; share indicator displacement consumption Frame control bridge, width and height change consumption Frame size bridge, both use Tab indicator preset uniformly. The retest triggered by the visible text of icon-toggle also maintains the dynamic effect, and is no longer covered by ResizeObserver instantaneous paste.
The specific timing of Tab indicator shall be subject to TAB_INDICATOR_MOTION; TAB_INDICATOR_MOTION_STYLE injects the same preset into two sets of frame control / size bridges, prohibiting the maintenance of displacement and size values separately.
Layout model
Main layout model: inline shell layout. Tab is an inline-flex container, changing to a column when flex-direction: column.
The first child: absolute positioning
<div class="snowui-tab-indicator">, follow the activation button to transition through transform/width/heightThen there is the Button sub-item input by the user; Button
position: relative; z-index: 1to ensure that the text is above the indicator
When fill={true}, the horizontal sub-item uses flex: 1 1 0 equal width to fill the container with the available width. Usually with style="width: ..." / The width tool class is used; when the container width is not defined, it is still laid out according to the natural width of the content.
For details, please refer to LayoutProtocol.md §12.3 (source code reference: specs/maintainers/LayoutProtocol.md).
Keyboard behavior
←/→(row) or↑/↓(column): move the focus. Activate directly whenselectionFollowsFocus=true(Segmented).Home/End: Jump to the first/end, and the behavior is the same as above.Enter/Space: Triggered by Button's native click behavior, activates the current focus item.Roving tabindex: The active item has
tabindex=0and the otherstabindex=-1, so the entire Tab group occupies one position in the outer Tab sequence.
Usage examples
Tab style overlay
Read the full LICENSE first; reuse that review for the same task, version, and scope.
First use public component Props to match the desired appearance, preserving the existing look where possible. If changes are necessary, follow the style selection and override order: use your own class (including Tailwind already in the project) or an instance style. The names below are public overrides actually consumed by source; check their scope and do not modify private DOM. Choose the correct SnowUI token family. External apps need not install SnowUI website utilities.
Tab type and status
Required Props: no named required Props.
Two-way binding: bind:value.
Inheritance statement: Omit<FrameProps, "children" | "value">. The inheritance ability is subject to the public document of the base class; the fields in Omit have been excluded and cannot be used as they are according to the base class.
The following type declarations are actually referenced by public Props and come from source. A Svelte Snippet denotes a content fragment; ComponentProps denotes the Props of the corresponding component.
TabVariant
Source: components/src/components/Tab.svelte
TabSize
Source: components/src/components/Tab.svelte
TabItem
Source: components/src/components/Tab.svelte
ComponentPartsOf
Source: components/src/logic/component-parts.svelte.ts
ConfigurableComponentPartProps
Source: components/src/logic/component-parts.svelte.ts
ComponentPartControlledKey
Source: components/src/logic/component-parts.svelte.ts