Tab Bar
Device mode tab bar with active underline indicator
Size
Material
State
<div class="tab-bar">
<button class="tab-item active">PHOTO</button>
<button class="tab-item">VIDEO</button>
<button class="tab-item">AUDIO</button>
<button class="tab-item">FILES</button>
</div> .tab-bar {
display: flex; background: var(--bg-raised);
border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
overflow: hidden; box-shadow: 0 2px 0 var(--border-deep);
}
.tab-item {
flex: 1; padding: 8px 14px; text-align: center;
font-family: var(--font-ui); font-size: 10px; font-weight: 500;
color: var(--text-muted); letter-spacing: 1px; cursor: pointer;
transition: all 0.15s; position: relative; user-select: none;
border-right: 1px solid var(--border-subtle); background: transparent;
border-top: none; border-bottom: none;
}
.tab-item:last-child { border-right: none; }
.tab-item:hover { color: var(--text-primary); }
.tab-item.active { color: var(--blue-info); background: linear-gradient(180deg, var(--glow-color), transparent); }
.tab-item.active::after {
content: ''; position: absolute; bottom: 0; left: 4px; right: 4px;
height: 2px; background: var(--blue-info); border-radius: 1px;
} API
| Class | Type | Description |
|---|---|---|
.tab-bar | Base | Primary component class |
.default | Size | Extra large variant |
.active | State | Active state |
Design Notes
Physical Analog
Reference devices: Nokia Symbian UI tabs, Sony Ericsson media player mode tabs, camera menu section tabs. Mechanism: Derived from physical tabbed dividers in filing cabinets and ring binders. Each tab represents a category. The active tab appears "in front of" the others (connected to the content below), while inactive tabs appear recessed or separated. In hardware devices, this was often a row of physical buttons with a mode indicator LED above each.
Geometry
| Property | Value |
|---|---|
| Layout | Flex row, equal-width items (flex: 1) |
| Border radius | --radius-md (8px) |
| Item padding | 8px 14px |
| Font size | 10px |
| Active indicator height | 2px |
| Bottom shadow | 2px |
CSS Recipe
Container (.tab-bar)
.tab-bar {
display: flex; background: var(--bg-raised);
border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
overflow: hidden; box-shadow: 0 2px 0 var(--border-deep);
}
Tab Item (.tab-item)
.tab-item {
flex: 1; padding: 8px 14px; text-align: center;
font-family: var(--font-ui); font-size: 10px; font-weight: 500;
color: var(--text-muted); letter-spacing: 1px; cursor: pointer;
transition: all 0.15s; position: relative; user-select: none;
border-right: 1px solid var(--border-subtle); background: transparent;
border-top: none; border-bottom: none;
}
.tab-item:last-child { border-right: none; }
Hover
.tab-item:hover { color: var(--text-primary); }
Active
.tab-item.active { color: var(--blue-info); background: linear-gradient(180deg, var(--glow-color), transparent); }
.tab-item.active::after {
content: ''; position: absolute; bottom: 0; left: 4px; right: 4px;
height: 2px; background: var(--blue-info); border-radius: 1px;
}
HTML Structure
<div class="tab-bar">
<button class="tab-item active">PHOTO</button>
<button class="tab-item">VIDEO</button>
<button class="tab-item">AUDIO</button>
<button class="tab-item">FILES</button>
</div>
Size Variants
No size variants defined. Width is typically set by parent container.
Material Variants
No material variants. Uses standard raised surface.
Theme Behavior
- Background swaps via
--bg-raisedtoken - Active indicator always uses
--blue-info - Separator borders swap via
--border-subtle - Bottom shadow adjusts via
--border-deep
Constraints
- MUST use
flex: 1on items so all tabs are equal width - MUST include 2px blue indicator bar on active tab via
::after - MUST include vertical separators between tabs (
border-right) - Only ONE tab can be
.activeat a time (radio behavior) - MUST use
overflow: hiddenon container to clip radius corners - MUST NOT use more than 5-6 tabs (becomes unreadable)
Accessibility
- Container should have
role="tablist" - Each tab should be a
<button>withrole="tab" - Active tab:
aria-selected="true" - Associated panel:
aria-controls="panel-id"androle="tabpanel"on content - Support Left/Right arrow key navigation
♿
Accessibility
- Element
- Use <nav> with aria-label
- Keyboard
- Arrow keys to navigate, Enter to select
- Focus
-
Visible focus indicator required. Use native browser focus ring or custom
:focus-visiblestyles.