Tabs
48px pill tabs with an optional leading icon, in a default look and an inverse glass look for dark surfaces.
tab-pillOpen in Figma ↗A pill-shaped tab control for filtering content or switching between categories within a view.
Use for: Horizontal tab rows at the top of a content area where the user needs to switch between predefined categories or filter sets — such as plan types, content sections, or product categories.
Not for: Navigation between screens — use the navbar instead. Not for binary on/off toggles — use a switcher instead. Not for selecting items from a dropdown — use filter-pill instead.
Choosing: Use inverse=false on light surfaces. Use inverse=true on dark, midnight, or glass surfaces where standard colours would not provide sufficient contrast. Set selected=true on the active tab — the surface fills with a light red tint and the icon and label turn brand red. Only one tab-pill in a set should be selected=true at a time.
Rules: Height is fixed at 48px — do not resize. Width hugs the label; the label is single line only and never wraps. The leading icon (20px) is always present — do not remove it. Group multiple tab-pills horizontally in a scrollable row; never stack them vertically. Exactly one pill must always be selected within a set — do not leave all pills unselected. In RTL, layout mirrors automatically.
import SwiftUI import EandTokens // V1.2 tab-pill: 48 tall, min 72 wide, padding 0/16, title/xs, gap 8 between pills. // Unselected = white pill, muted ink; selected = brand-muted pill, red ink. // inverse (on brand / midnight): white 20% + blur, selected solid white. struct PillTab: View { let title: String; let active: Bool var body: some View { Text(title) .font(.system(size: EandTypography.titleXs.size, weight: EandTypography.titleXs.weight)) .foregroundColor(active ? EandColor.tabDefaultTextSelected : EandColor.tabDefaultTextDefault) .padding(.horizontal, EandSpacing.lg) .frame(minWidth: EandScale.scale72, minHeight: EandScale.scale48) .background(active ? EandColor.tabDefaultSurfaceSelected : EandColor.tabDefaultSurfaceDefault) .clipShape(Capsule()) } }
When to use
- Use to switch between sibling views at the same level. Exactly one tab is selected.
- Use
inverseon brand-red, midnight and glass surfaces, such as the tabs add-on of the TopBar. - Don't use for filters (Chip) or for steps in a flow (Stepper). PageHeader draws its own tab pills.
icons is index-aligned with tabs. A string is an icon-set name drawn at 16px; a node
renders as given. Figma always shows the icon; the code keeps it optional so text-only rows
still work. scope="local" (a midnight selected pill) exists on no V1.2 symbol and is
deprecated.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
tabs | string[] | — | |
defaultValue? | number | 0 | |
icons? | ReactNode[] | — | Leading glyph per tab, index-aligned with tabs, drawn in a 20px icon-size. A string is
an icon-set name rendered at Figma's 16px; a node renders as given. Figma's rule is that
the icon is always present; code keeps it optional so text-only rows still work. |
inverse? | boolean | — | Inverse (glass) pills for brand, midnight or glass surfaces — e.g. the TopBar tabs add-on. |
onChange? | ((index: number) => void) | — | |
scope? | 'global' | 'local' | global | Deprecated. local (midnight selected pill, bordered white unselected) exists on no V1.2
symbol — Figma publishes one look plus inverse. Kept working for existing screens;
global (the default) is the published look. |
value? | number | — |
Design
Figma source: tab-pill — etisalat Consumer App DSL V1.2
- 48px tall (
scale/48), minimum widthscale/72,spacing/lginline padding, pill. - A 20px icon box with a 16px glyph, then the
title/xslabel with 2px (spacing/2xs) side padding. - Default: unselected
tab/default/surface/default(white), selectedtab/default/surface/selectedwithtab/default/text/selected. - Inverse: unselected
tab/inverse/surface/default(white at 20%) behind a 20px backdrop blur; selectedtab/inverse/surface/selected(white) withtab/inverse/text/selected. - Pills sit
spacing/smapart in a row that scrolls sideways.