Jump to a component
Core · Content
ListRow
ListRow is one row of a List: a title and a quiet line under it, with an optional icon or image before it, a meta column (a timecode) and whatever sits at the end (a switch, a button, a check). selected marks the current row the way every list and nav does: its title in ink weight with the small state-dot beside it, no fill and no edge; href makes it a link; loose gives it more room (settings lists).
Live, from @anicanon/sakuga 2.0.0
Sakuga for iOS and Android is coming
iOS
Coming soon
ListRow for iOS is in the roughs. The tokens it will read are the ones on this page, the same on every platform.
Android
Coming soon
ListRow for Android is in the roughs. The tokens it will read are the ones on this page, the same on every platform.
- Use it for
- One thing on one row of a
List: a title and a quiet line, with what sits at the end (a switch, a button, a check);loosein settings lists. - Not for
- A quiet action inside a line of textTextLink
- A row on Story with a picture, a state and the work that told itEntityRow
- Each kind of setting with its value, opening the full choicePropertyList
- Measured facts, a name and its valueFactList
- A cut on an ekonte sheetCutRow
Guidelines
- A linked row sinks on press and its picture leans in on hover; rows never take a hover fill.
onClickis for client-side navigation. - With sound on, a press on a linked row plays the press sound (README · Sound).
- One row, one thing. A row never holds two actions of the same weight.
Listwraps rows and names the list (label).attentionreads the quiet line in the text colour after the samestate-dot: a take that waits for you, asMediaCardmarks a production.lightMapgives theimagelight on art, as onThumb: its own highlights glow under the pointer, and at the centre when a linked row has keyboard focus. Never onmuted.slot="lead"replaces the icon or image (a play button);slot="main"replaces the title and quiet line (a sound's waveform and its length).checkedandonCheckgive the row aCheckboxfor bulk selection, named "Select" and the row's title; a checked row's title takes the ink weight. On a linked row the box sits beside the link, so the box chooses and the row still opens. It is notselected: that marks the current row.chevronadds a trailing chevron when the row opens a page.Listwithsurfacesets the rows in a surface, as a phone groups them.
import { Button, List, ListRow, Switch } from '@anicanon/sakuga/ui';
function stay(e) {
e.preventDefault();
}
export default function ListRowExample() {
return (
<List label="Tracks">
<ListRow
icon="video"
title="Takes’ own sound"
sub="Voices and sound from each take"
>
<Switch on label="Takes’ own sound" />
</ListRow>
<ListRow icon="volume" title="Cue 2 · wind" sub="Music" selected>
<Switch on label="Cue 2" />
</ListRow>
<ListRow
image="/art/eba-cinema.webp"
lightMap="/art/eba-cinema.light.webp"
imageWidth={56}
imageHeight={32}
title="2C · take 3"
sub="No lines yet"
>
<Button variant="secondary" size="sm">
Caption
</Button>
</ListRow>
<ListRow
image="/art/eba-s1e1.webp"
lightMap="/art/eba-s1e1.light.webp"
imageWidth={56}
imageHeight={32}
title="2A · take 1"
sub="Opens in Cut"
href="#"
onClick={stay}
/>
<ListRow
meta="2:23 + 00f"
title="Just once more."
sub="Lisa · 2A"
href="#"
onClick={stay}
/>
</List>
);
}PropsListRowProps
titlerequiredReactNodesubReactNodeiconIconNameimagestringimageStylestringimageWidthnumberimageHeightnumberlightMapstringlightbooleanmutedbooleanmetastringselectedbooleanattentionbooleanloosebooleancheckedbooleanselected, which marks the current row.onCheck(checked: boolean) => voidlabelstringchevronbooleanhrefstringonClickMouseEventHandlerchildrenReactNodeclassNamestringAn IconName is any of the names Icon lists.
Each token reads a role, and the role lands on a value in each theme. Change the role and every component that reads it follows.
Colour
listrow-attentionListRow: a line that waits for you.text-primaryneutral-925#0b0a10text-primaryneutral-0#ffffffSpace and shape
list-row-icon-sizeicon-size-smlist-row-chevron-icon-sizeicon-size-smlist-row-gapgap-mdlist-row-padding-yinset-smlist-row-edge-bottom-widthlist-row-active-scalescale-press-lglist-row-thumb-img-hover-scalescale-zoomlist-row-loose-gapgap-lglist-row-loose-padding-yinset-mdlist-row-meta-widthlist-row-words-gapgap-2xslist-row-end-gapgap-smlist-row-main-gapgap-mdlist-row-words-small-attention-gapgap-smType
list-row-fonttext-captionlist-row-meta-fonttext-smalllist-row-words-b-font-weightweight-stronglist-row-words-small-fonttext-smalllist-row-words-b-loose-fonttext-labellist-row-words-small-loose-fonttext-captionlist-row-words-small-attention-font-weightweight-stronglist-row-words-b-selected-font-weightweight-boldMotion
list-row-durationmotion-fastlist-row-easingease-standardlist-row-active-durationmotion-instantlist-row-icon-durationmotion-fastlist-row-icon-easingease-standardlist-row-thumb-light-focus-durationmotion-slowerlist-row-thumb-light-focus-easingease-standardChecked automatically with axe-core 4.11.4 against WCAG 2.2 A and AA, on the live preview above, in light and dark, on 26 October 2026.
- Result
- No issues found, in light or in dark.
- By design
- Inside List (a list named by its
label) each row is a list item read as its title, quiet line,metaand what sits at the end, marked "current" whenselectedand "waiting for you" withattention; withcheckedoronCheckits box comes first, a checkbox named "Select" and the title (labelnames it when the title is markup); pictures, icons and the chevron are hidden. Withhrefthe row is a link, with onlyonClicka link-role row, and either way Tab reaches it and Enter follows it. - Not tested
- The automated check doesn't test keyboard use, focus order or what a screen reader says. The lines above are the design system's own account of them.