v3.4.9
Cell

The foundational list row — a universal tappable element for settings, contacts, menus, and transactions.

3.4.0 3.4.0 -- 3.4.9

Overview

Cell is the fundamental building block for lists — a universal tappable row for settings, menu items, transactions, addresses, and contacts. It always fills its container width, and every preset is a locked configuration of a single CustomCell base with all slots configurable.

  • 1
    Simple
  • 2
    Icon
  • 3
    Squircle · S
  • 4
    Squircle · M
  • 5
    Squircle · L
  • 6
    Custom

States

Three states, the same on every preset — one block each. Press is feedback, not a state: see Animation.

Standard

  • 1
    Background var(--background-primary) — the row's fill.The default — any DS background token can replace it.
  • 2
    Title var(--text-and-icon-primary) — the title rows of start-text and end-text.
  • 3
    Subtitle var(--text-and-icon-secondary) — the subtitle, additional and description rows.
  • 4
    Chevron var(--text-and-icon-primary) — locked in the presets.
  • 5
    Icon var(--text-and-icon-primary) — the start-slot icon.
  • 6
    Squircle Its own Standard state — from the Squircle component.

Disabled

  • 1
    Background var(--background-primary) — unchanged.
  • 2
    Title var(--text-and-icon-disabled) — set once by .is-disabled on the root; the rows inherit it.A colour swap, not an opacity.
  • 3
    Subtitle var(--text-and-icon-disabled) — the secondary rows follow.
  • 4
    Chevron var(--text-and-icon-disabled)
  • 5
    Icon var(--text-and-icon-disabled)
  • 6
    Squircle Its own Disabled state — .squircle--disabled, from the Squircle component. A control in the end-slot takes its own disabled state the same way.

Skeleton

  • General var(--skeleton-on-white) — the placeholder fill.var(--pattern-shimmer) — the DS sweep, from the Skeleton component.The same shapes on every preset: the start-slot as a rounded box of its own size, the title and subtitle as bars. The end-slot has no placeholder.

Anatomy

Two containers: the row of four slots, and the optional description under it. Only start-text is required.

  • 1
    topContainer The horizontal row that holds the four slots; no fill of its own.Required.
  • 2
    start-slot var(--sp-s40) — its width; an IconContainer by default.An icon, a boxed icon or nothing; a Squircle in the Squircle presets. Optional.
  • 3
    start-text Body/Main Body — the title row.Body/Compact Body — the subtitle and additional rows, hidden by default.Up to three TextRow rows. Fills the width and truncates first. Required.
  • 4
    end-text The same three rows, end-aligned. Hugs its text and never truncates.Hidden by default. Optional.
  • 5
    end-slot One item — the chevron by default in the presets — or two in CustomCell.Chevron, icon, value, badge, a Checkbox, RadioButton or Switcher, Squircle, Button, Tag, Loader or Avatar — the full list is in the spec, §8. Optional.
  • 6
    description Body/Compact Body — the text, with a divider above it.Text and divider, text only or divider only. Hidden by default. Optional.

Layout

CustomCell with every slot on. The presets lock a subset of these slots; only the Squircle sizes change the start-slot and, at M, the vertical padding.

General

  • Container var(--sp-s16) — left and right padding.var(--sp-s10) — top and bottom padding.var(--sp-s8) — the same padding in the M Squircle preset.var(--sp-s8) — every gap between slots, and between two items in one end-slot.var(--sp-s48) — the minimum height; the row hugs its content above it.Fills its container's width — never sized by its content.
  • Priority The end side keeps its width and start-text truncates first. The priority can move to the start side when a layout needs it.

Slots

  • Height var(--sp-s36) — every slot's height floor.The row is as tall as its tallest slot; every slot fills that height and centres its content. The Squircle presets keep the Squircle on the row's top edge.
  • start-slot var(--sp-s40) — its width; the Squircle's own size in the Squircle presets.
  • start-text Fills the width the other slots leave.
  • end-text, end-slot Hug their content.

Squircle sizes

  • S var(--sp-s40) — the Squircle and its slot; the row is 60.
  • M var(--sp-s48) — the Squircle and its slot.var(--sp-s8) — top and bottom padding; the row is 64.
  • L var(--sp-s56) — the Squircle and its slot; the row is 76.
  • Row Height Body/Main Body — the title on every size.var(--sp-s16) — the left padding on every size.The row is the Squircle plus the vertical padding — the minimum for any number of text rows; the text centres against the Squircle.

Selection controls

  • 1
    Row (Default) var(--sp-s24) — the drawn box, without its safe zone, in the chevron column.The row is the hit area and the control.
  • 2
    Separate var(--sp-s48) — the control's own hit area, dashed.var(--sp-s12) — its overlap on every side, into the row's padding instead of layout space, so the row and the box sit exactly as in Row.
  • RadioButton, Switcher RadioButton follows Checkbox. Switcher draws its 52 × 32 container; its safe zone is vertical only, 8 above and below.

Card-wrap

  • Wrapper var(--sp-s16) — the corner radius.var(--sp-s16) — the horizontal margin from the container.Owns the radius and overflow: hidden, so the press overlay clips to the corners. The cell keeps its own padding.

RTL

  • 1
    LTR The default. start-slot on the left, end-slot on the right.
  • 2
    RTL The row mirrors: the end-slot on the left, the start-slot on the right; the text aligns to the start side.Only the chevron mirrors among the icons; a Switcher takes its own RTL variant. The web takes the direction from dir="rtl" — opt-in per instance.

Animation

Motion follows the motion system § 6.1 — pushHighlight, the press without scale. The row has three motions of its own — the press, the disabled colour change and the skeleton's shimmer; a selection control brings its own.

Press

Rest
Pressed — the overlay, frozen
Live — press the row
Live, separate — the row presses, the checkbox does not
  • General --component-push-highlight — press and release, 150 ms linear.var(--shadow-pressed) — the overlay over the row's background; it fades in and out.No scale: a scaled row would push its neighbours. The same on every preset.
  • Separate Only the row action presses the row; a press on the end-slot control leaves the row still.
  • Repeated Taps The press plays on every tap of an enabled row; the action runs once — the first tap runs it and a tap inside the window opened by the last accepted one is ignored, so a quick double tap opens a chevron row's screen once and toggles a selection row once.
  • Platforms Android — the native ripple over the row.iOS — the table-cell highlight, a background change.Flutter — an InkWell with its splash in the press overlay colour, black 10% (the State/PressedStateOverlay style).
  • Reduced Motion Handled at the token: motion.css zeroes every --component-* inside prefers-reduced-motion: reduce, so the overlay appears without a fade; no override of its own.

Disabled

Standard
Disabled
  • Colour Change --transforming-state-default — 200 ms slow-ease-out, Standard ↔ Disabled.The text and icon colour moves to var(--text-and-icon-disabled) and back; no opacity.
  • Nested Components A Squircle or a control runs its own disabled transition.
  • Reduced Motion --transforming-state-default — zeroed at the token, so the colour changes in one frame.

Selection control

Live — a Checkbox row
Live — RadioButton rows
  • The Control's Own --transforming-state-default — the control's own motion, 200 ms; see Checkbox and RadioButton.The row adds only its press; there is no selected tint to animate.
  • Switcher Keeps its own motion on iOS and Android; it has no web build yet.The knob drags as well as taps: in a row, a drag that carries it across toggles the row the same way as a tap. A switch that cannot change does not follow the finger.

Skeleton

LTR
RTL — the sweep runs the other way
  • Shimmer var(--pattern-shimmer) — the DS sweep on every shape, from the Skeleton component.It runs in reverse in RTL.
  • Reduced Motion var(--pattern-shimmer) — zeroed at the token, so the skeleton holds still.

Usage

Cell is the row of a list — settings, menus, contacts, trip history, a choice.

  • 1
    A Settings List Rows that open a screen: an icon, a title and the chevron. The presets lock the rest, so every list reads the same.
  • 2
    One Choice Out Of Several RadioButton rows: the whole row is the control and the list is the radiogroup. Any number of choices is Checkbox rows; an on/off setting is a Switcher row.
  • 3
    ✕ A Tinted Row As The Selection Cell has no selected state — a tint is colour alone and is not announced. Put a Checkbox or a RadioButton in the end-slot; the control carries the selection.
  • 4
    ✕ A Lone Row On A Screen Cell is a list building block. One row on its own goes in the card-wrap, which gives it the radius and the margin of a button.
  • 5
    ✕ Three Actions In One Row A row carries at most two: its own action and one control (controlTarget: separate). More actions go to a swipe or a context menu.

Settings

1✓ A settings list — rows that open a screen

Share my trip

2✓ One choice — RadioButton rows, the row is the control

Payment

3✕ A tinted row as the selection
4✕ A lone row on a screen

Saved places

5✕ Three actions in one row

Accessibility

A row is one focus stop — or two when its control is a separate target. The full model and the per-platform tables live in cell-a11y.md.

Tap to open
A row with a chevron — the focus ring frozen
A Checkbox row — live
RadioButton rows — live
Tap to open
Separate — the row action, then its control; live
Disabled
Skeleton
  • 1
    Tappable Row <button type="button"> — the button role natively; type="button" keeps a cell inside a form from submitting it.The name comes from the cell's own text — title, then subtitle. aria-label only when that text is not a good name.TalkBack: "{title}, {subtitle}", Button, "Double tap to activate".VoiceOver: "{title}, {subtitle}", .button, "Double tap to activate".
  • 2
    Chevron The hint "Tap to open" — aria-describedby to a visually hidden span; the chevron itself is not announced.TalkBack: "Double tap to open". VoiceOver: "Double tap to open".
  • 3
    Focus Ring var(--sp-s2) — the ring's width; :focus-visible only.--text-and-icon-primary — its colour.var(--sp-s2) — the inward offset: a list clips its rows, so an outer ring would not show.The same ring on .cell__action; on a row cell it is the control's ring too.
  • 4
    Checkbox Row The row is the control: role="checkbox" and aria-checked on the row, its text the name. The box inside is drawn without its safe zone and carries aria-hidden="true" — announced once, by the row.TalkBack: "{title}, {subtitle}, Checkbox, Not checked", "Double tap to toggle".VoiceOver: one element; the box's state merges into the row's traits — selected / not selected; "Double tap to toggle setting".aria-checked, data-ds-state and the box's --selected class change in one handler. A Switcher row is the same with role="switch".After a toggle the new state is read at once, the focus still on the row — the state lives on the row's own element. A state left on the box is never reported; one written only into the label is not reliably read.UI tests read the state on the row: Android checked, iOS value (Switcher) / selected trait (Checkbox, RadioButton), web aria-checked.Cell has no selected state of its own and no aria-selected — a selected row is announced through its control.
  • 5
    RadioButton Rows The list is the group: role="radiogroup" with its own name; each row role="radio".One Tab stop — tabindex="0" on the selected row, or on the first enabled row when the selected one is disabled.TalkBack: "{title}, {subtitle}, Radio button, Checked, 1 of 2"; "Double tap to select", none once selected.VoiceOver: the selected trait; "Double tap to select", none once selected.
  • 6
    Row Action .cell__action — a <button> stretched over the cell, first in the DOM, so it takes the focus first.The root is a <div>: a <button> cannot contain another button — the trap of this model.TalkBack: "{title}", Button, with "{subtitle}" as its description and the row's hint.VoiceOver: "{title}, {subtitle}", .button, the row's hint.The text block is aria-hidden="true" so swipe navigation does not read it a second time; the label and description references still resolve.
  • 7
    Its Control A second focus stop with its own role, aria-checked and name — the title.TalkBack: "{title}, Checkbox, Not checked". VoiceOver: "{title}", its own trait and state.
  • 8
    Disabled Native disabled — out of the Tab order, the trait announced. The control inside takes its own disabled state.TalkBack: "Disabled" after the label, no hint; the row stays in swipe navigation and a double tap does nothing. A selected row reads its value first — "Checked", then "Disabled".VoiceOver: "Dimmed", no activation hint; the row stays in the rotor. A selected row reads "Selected", then "Dimmed".The trap: on a separate cell .is-disabled on the <div> is visual only — disabled goes on both buttons.
  • 9
    Skeleton Not focusable, not announced: the shapes are aria-hidden, and the loading list carries the busy state once — aria-busy="true" on the web. VoiceOver announces the container once.
  • Keyboard Tab moves between cells; a RadioButton list is one stop, a separate cell two.Space and Enter activate a plain or chevron cell. On a Checkbox row Space toggles, on a RadioButton row it selects, and Enter does nothing; the arrows move the choice in a list and skip disabled rows.The trap: a row is a real <button>, which synthesizes a click on Enter — a bare click handler would toggle a Checkbox row on Enter. The handler flags Enter on keydown and swallows that click, so Enter stays free to submit the form.
  • Target Size var(--sp-s48) — the row's minimum height; the whole row is the target.The separate control keeps its own 48 × 48 area inside the row.
  • Reduced Motion --component-push-highlight — the press overlay appears in one frame.--transforming-state-default — the disabled colour changes in one frame.var(--pattern-shimmer) — the shimmer holds still. All zeroed at the token.
  • Contrast --text-and-icon-primary on --background-primary — the title, the icon, the chevron and the focus ring: ≈ 17.8:1 Day / ≈ 17.0:1 Night.--text-and-icon-secondary — the subtitle: ≈ 5.25:1 / ≈ 7.92:1, above 4.5:1.A selection control keeps its own pairs — see its spec.