Design System
Components

Picker

Fixed 106×72 option tiles — value, caption and an optional status strip; a selected tile inverts and shows a check.

Figma description · pickerOpen in Figma ↗

A compact selectable tile displaying a value, a description label, and an optional status badge — used for choosing between discrete options in a constrained layout.

Use for: Horizontal picker rows where the user selects one value from a set of discrete options — such as a data amount, a duration, or a quantity — where each option needs a value and a unit or description label.

Not for: General navigation or filtering — use chips or filter-pill instead. Not for free-form input — use a text field instead.

Choosing: Use color-scheme=default on light and sunken surfaces. Use color-scheme=inverse on glass, midnight, or dark surfaces — the tile renders with a white glass fill and inverse text tokens. Toggle badges to show or hide the status badge at the bottom of the tile. Set state=selected to highlight the active option. Set state=disabled to prevent interaction and reduce visual prominence.

Rules: Width is fixed at 106px, height at 72px — do not resize. Padding is 20px top, 8px left and right. The status badge is 16px tall and spans the full tile width — do not change its dimensions. Edit the value and description label via text properties on the instance. Do not place pickers outside a horizontal picker row — they are always grouped with sibling pickers representing alternative options.

Props
import SwiftUI
import EandTokens

// V1.2 picker tile: fixed 106×72, r16, centred. Value title/sm over a body/xs caption
// (20pt top, 8pt sides). Selected swaps the fill to midnight-raised with inverse ink
// and adds a 20pt check-circle at 6,6 from the top-end. Optional neutral sm badge strip.
struct PickerOption: View {
  let value: String; let caption: String; let selected: Bool
  var body: some View {
    VStack(spacing: 0) {
      Text(value).font(.system(size: EandTypography.titleSm.size, weight: EandTypography.titleSm.weight))
      Text(caption).font(.system(size: EandTypography.bodyXs.size))
        .foregroundColor(selected ? EandColor.textDefaultInverse : EandColor.textDefaultSubtle)
      Spacer(minLength: 0)
    }
    .foregroundColor(selected ? EandColor.textDefaultInverse : EandColor.textDefaultDefault)
    .padding(.top, EandSpacing.xl).padding(.horizontal, EandSpacing.sm)
    .frame(width: 106, height: EandScale.scale72)
    .background(selected ? EandColor.surfaceRaisedMidnight : EandColor.surfaceSunkenDefault)
    .overlay(alignment: .topTrailing) {
      if selected {
        Image(systemName: "checkmark.circle.fill").font(.system(size: EandIcon.lg))
          .foregroundColor(EandColor.surfaceBaseInverse)
          .frame(width: EandIcon.xl, height: EandIcon.xl).padding(6)
      }
    }
    .clipShape(RoundedRectangle(cornerRadius: EandRadius.radius6))
  }
}

When to use

  • Use to choose one value from a small set shown side by side, such as top-up amounts. Picker manages the selection; PickerOption is the standalone tile for custom layouts.
  • Don't use for a long list — use an Input of type="dropdown". For options that combine, use Checkbox; to switch views, Tabs.

Anatomy

  • Value — title/sm, centred. Caption — body/xs beneath it, such as a unit.
  • Badge — a string or number renders the neutral sm status Badge as a strip along the bottom of the tile. Any other node renders as given. Hidden while disabled.
  • Selected — the fill and ink swap, and a check circle appears at the top end. On default and light the tile turns midnight with white text; on inverse and glass it turns white.
  • Disabled — disabled ink, no badge. A disabled tile never shows as selected.

The surface names predate V1.2 and map to Figma's surfaces as follows:

surfaceFigma surfaceTile fill
defaultsunkensurface/sunken/default
lightdefaultsurface/canvas/default
inversemidnightsurface/raised/midnight
glassglasssurface/glass/white/lg

Props

PropTypeDefaultDescription
optionsPickerOptionData[]—
defaultValue?number—
onChange?((index: number) => void)—
surface?'default' | 'inverse' | 'light' | 'glass'default
value?number—Selected index (controlled).
PropTypeDefaultDescription
badge?ReactNode—Status badge along the bottom of the tile (Figma badges). A string or number renders the published neutral sm status badge across the tile; any other node renders as given. Hidden while disabled.
caption?ReactNode—Secondary line under the value (body/xs) — e.g. a unit.
disabled?boolean—
onClick?(() => void)—
selected?boolean—
surface?'default' | 'inverse' | 'light' | 'glass'default
value?ReactNode—Primary text (title/sm, centred).

Design

Figma source: picker — etisalat Consumer App DSL V1.2

  • A fixed 106×72 tile (scale/72), border-radius/6 (16), content centred with 20px top and 8px side padding.
  • Selected, default scheme: surface/raised/midnight with text/default/inverse. Inverse scheme: surface/raised/default with text/default/default and subtle.
  • The check is check-circle-filled, 20px in a 24px box, 6px from the top and end edges.
  • Badge strip: a 2px inset and corner radii 6/6/28/28, so the strip follows the tile's curve. The bottom 28 has no token.
  • Glass: surface/glass/white/lg behind a 20px backdrop blur.

On this page