ComponentsVertical List Cell
Lists

Vertical List Cell

The primitive behind every vertical list. A row cell rotated onto the vertical axis: a full-height column with a leading edge at the top, vertical title/subtitle, and a trailing accessory at the bottom.

$ npx verticallyworks add vertical-list-cell
Design question

A horizontal list cell is [leading] [title/subtitle] … [trailing accessory] laid out as a full-width row. What is its shape when the list stacks as columns and scrolls right-to-left?

Decision

Rotate the cell's anatomy, don't rotate the cell. Leading moves to the top (reading start), title and subtitle become vertical text, and the disclosure accessory sits at the bottom pointing down · along the reading axis, not across it.

Default

The primitive behind every vertical list. A cell is a full-height column · leading index at the top, vertical title + subtitle, and a trailing accessory (a down-pointing disclosure chevron, or a status pill) at the bottom. Cells stack as columns and the list scrolls right-to-left.

tsx
1import { VerticalListCell } from "@/components/vw/vertical-list-cell"
2
3export function ContentsList() {
4 return (
5 <div role="listbox" aria-label="목차" style={{ display: "flex", flexDirection: "row-reverse", gap: 12, overflowX: "auto" }}>
6 {chapters.map((c, i) => (
7 <VerticalListCell
8 key={c.title}

Source

The exact file npx verticallyworks add vertical-list-cell copies into your project · yours to edit. Styling comes entirely from the design tokens.

tsx
1"use client";
2
3/**
4 * VerticalListCell · the primitive behind every vertical list.
5 *
6 * Rotate the cell's anatomy, not the cell: leading moves to the top (the
7 * reading start), title and subtitle become vertical text columns reading
8 * right→left, and the disclosure accessory sits at the bottom pointing down,

Guidance

Do
  • Put the leading element (index, icon, avatar) at the top · the reading-start edge
  • Point the disclosure chevron down (rotate 90°): 'forward' is downward along the vertical axis
  • Keep every cell the same height so the row of columns reads as one list
  • Give each cell a 44px+ hit target and stack cells right-to-left
Don't
  • Rotate a finished horizontal cell with transform: rotate(90deg)
  • Leave the chevron pointing right · it should follow the reading axis, not the scroll edge
  • Mix upright and vertical text within the same cell for title and subtitle

Accessibility

Container role='listbox' (or 'list'); each cell role='option' with aria-selected (or a plain button). Keyboard: arrow keys move selection; the visual R→L order must match DOM/tab order.

Open question

When the accessory is an interactive control (toggle, stepper), should it keep the bottom position, or move beside the title so the primary tap target stays central?