ActionBar
A 72px tappable bar — a leading visual, a title and description, and one trailing chevron, button or switch.
action-barOpen in Figma ↗Container that pairs with banners and cards. Holds an icon or image, title, description and a trailing action, giving context for that action.
Use for: an actionable row inside a section, card or banner.
Not for: standalone page rows — use list-item.
Choosing: default in light sections. Inverse when the surrounding surface is dark or glass.
Rules: always sits inside a parent container, never directly on a page.
import SwiftUI import EandTokens // action-bar: 72pt, r20, padding 0/16, gap 12. 40pt r12 leading tile, title/xs over a // body/md description (both the scheme ink), one trailing trigger: a button, a switcher // or a 20pt chevron in a 24pt box. struct ActionBar: View { let title: String; let subtitle: String var body: some View { HStack(spacing: EandSpacing.md) { Image(systemName: "headphones") .frame(width: EandScale.scale40, height: EandScale.scale40) .background(EandColor.surfaceBaseDefault, in: RoundedRectangle(cornerRadius: EandRadius.radius4)) VStack(alignment: .leading, spacing: 0) { Text(title).font(.system(size: EandTypography.titleXs.size, weight: EandTypography.titleXs.weight)) Text(subtitle).font(.system(size: EandTypography.bodyMd.size)) } .lineLimit(1) Spacer(minLength: 0) Image(systemName: "chevron.right").font(.system(size: EandIcon.lg)) .frame(width: EandIcon.xl, height: EandIcon.xl) } .foregroundColor(EandColor.textDefaultDefault) .padding(.horizontal, EandSpacing.lg).frame(height: EandScale.scale72) .background(EandColor.surfaceRaisedDefault) .clipShape(RoundedRectangle(cornerRadius: EandRadius.radius7)) } }
When to use
- Use for a row the user acts on: a settings entry, a prompt to top up, a shortcut into a flow, a feature toggle. Figma points tappable rows here rather than to the list item.
- Don't use for read-only data such as a balance or a price (use ListRow), or for a grid of shortcuts (use QuickAction).
Anatomy
- Leading (optional) —
icon, an icon or image in a 40px tile. - Text —
titleintitle/xsandsubtitleinbody/md, both in the scheme ink, each a single line that truncates. - Trigger — one of:
- Stack —
stackadds two glass layers that peek out below the bar, for a pile of related prompts. It renders with the inverse scheme only.
Choosing a surface
colorScheme sets the ink. When it is unset, it follows the surface: the glass and midnight
surfaces and white-transparent are inverse, the rest default.
| Family | surface |
|---|---|
| Default ink | default (surface/raised/default), subtle (surface/base/default), sunken (surface/sunken/default), glass with colorScheme="default" |
| Inverse ink | glass (20% white with a blur), white-transparent (20% white), midnight-base, midnight-raised, midnight-transparent |
<ActionBar
surface="midnight-raised"
title="Running low on data"
subtitle="Add 5 GB for AED 25"
action={<Button size="sm">Top up</Button>}
/>
<ActionBar title="Wi-Fi calling" subtitle="Call over any network" switcher={{ defaultChecked: true }} />Deprecated and changed
inverse is deprecated; use colorScheme="inverse". white-transparent moved to the
inverse family in V1.2, so it now renders white ink.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
action? | ReactNode | — | Trailing action — typically a <Button>. Only one trailing trigger; do not combine with chevron or switcher. |
chevron? | boolean | — | Show a trailing chevron instead of a button — the whole bar becomes the tap target. |
colorScheme? | 'default' | 'inverse' | — | Figma color-scheme: the ink. Defaults from surface — inverse for the dark/glass
surfaces, else default. Set default with surface="glass" for the light-family glass. |
icon? | ReactNode | — | Leading visual (icon or image) shown in a 40×40 tile. Omit for text at the leading edge. |
inverse? | boolean | — | Deprecated. Use colorScheme="inverse" (or surface="glass"). |
stack? | boolean | — | Multiple-stack — layered "stacked cards" look. Inverse scheme only (Figma type=multiple). |
subtitle? | ReactNode | — | Secondary line — body.md, truncates with ellipsis (Figma limit ~21 chars). |
surface? | 'default' | 'glass' | 'midnight-base' | 'midnight-raised' | 'subtle' | 'sunken' | 'white-transparent' | 'midnight-transparent' | — | Backing surface. Light family: default·subtle·sunken·glass; inverse family:
glass·white-transparent·midnight-base·midnight-raised·midnight-transparent. |
switcher? | boolean | SwitcherProps | — | Trailing switcher (Figma trigger=switcher). true, or the Switcher props. |
title? | ReactNode | — | Primary line — title.xs (Figma limit ~18 chars). |
Design
Figma source: action-bar — etisalat Consumer App DSL V1.2
- 72px tall (
scale/72), 16px side padding (spacing/lg), 20px radius (border-radius/7), 12px gap (spacing/md). - Leading tile: 40px at
border-radius/4, onsurface/base/default, orwhite/a15on the inverse scheme. - The description binds
text/default/default(ortext/default/inverse), the same ink as the title, not a subtle step. - The chevron is a 20px glyph in a 24px box.
- Stack: two 64px layers at a 16px radius (
border-radius/6) onsurface/glass/white/mdwith a blur, inset 6 and 12px, each peeking 10px below the one above, for a 92px total.