Design System
Components

Radio

Single-choice control — a 2px ring with a filled dot, at lg (24) or sm (20), on default or inverse surfaces.

Figma description · radio-buttonOpen in Figma ↗

A circular selection control for choosing one option from a mutually exclusive set.

Use for: Form fields and settings screens where the user must select exactly one option from a group — such as choosing a plan type, a billing cycle, or a preference.

Not for: Multi-select scenarios where more than one option can be active simultaneously — use the checkbox atom instead. Not for toggling a single setting on or off — use a switcher instead.

Choosing: Use small=false (24×24px) for standard forms, settings screens, and main content. Use small=true (20×20px) for dense layouts, list items, and compact UI. Set color-scheme=default on light or neutral backgrounds. Set color-scheme=inverse on midnight or brand red surfaces. Set selected=true for the active option in the group — renders as a brand red filled dot. Set disabled=true to prevent interaction; a selected disabled radio renders at reduced opacity.

Rules: Always use radio buttons in a group of two or more options. Only one radio button in a group can be selected=true at a time — selecting one must deselect the others. Always pair with a visible label for each option. Do not use a single radio button in isolation.

Props
import SwiftUI
import EandTokens

// V1.2 radio: lg 24 / sm 20, a 2pt ring; selected adds a 16pt (sm 12) dot in the same
// colour. Off ring and selected fill are color/mark tokens.
struct RadioView: View {
  let label: String; let selected: Bool
  var body: some View {
    HStack(spacing: EandSpacing.sm) {
      Circle()
        .strokeBorder(selected ? EandColor.markDefaultSurfaceSelected : EandColor.markDefaultBorderDefault,
                      lineWidth: EandBorder.lg)
        .frame(width: EandRadio.md, height: EandRadio.md)
        .overlay {
          if selected {
            Circle().fill(EandColor.markDefaultSurfaceSelected)
              .frame(width: EandScale.scale16, height: EandScale.scale16)
          }
        }
      Text(label).font(.system(size: EandTypography.bodyMd.size))
        .foregroundColor(EandColor.textDefaultDefault)
    }
  }
}

When to use

  • Use to pick exactly one option from a short list where every option stays visible. Give the radios in a group the same name.
  • Don't use for options that combine — that is a Checkbox. For a long list, use an Input of type="dropdown"; for value tiles, a Picker.

Props

PropTypeDefaultDescription
inverse?boolean—Inverse color scheme for dark (midnight/brand) surfaces (Figma color-scheme=inverse).
label?ReactNode—
size?'lg' | 'sm'lgControl size — lg 24×24 (default) or sm 20×20 (Figma V1.1 small axis).

Design

Figma source: radio-button — etisalat Consumer App DSL V1.2

  • lg 24 (token radio/md) or sm 20; a 2px ring (border/lg) and a 16px or 12px dot.
  • Default scheme: selected mark/default/surface/selected, unselected mark/default/border/default; disabled uses mark/default/surface/selected-disabled and mark/default/border/disabled. Disabled is a colour, not opacity.
  • Inverse scheme: a white ring and dot, an unselected ring in border/interactive/inverse/default, and white at 40% when disabled. The published inverse binds the default mark family, so these colours are held pending a design ruling.
  • The Figma radio has no label; the code's label uses the Checkbox inks, so a disabled row still reads as disabled.

On this page