Design assets
12 items · Updated 2 hours ago
A vertical list of repeating rows, for interfaces where every row shares a shape: an optional leading region, the content, and an optional trailing region. Rows can carry dividers, hover highlighting, or a heading link stretched across the whole row for a click-anywhere target. A row can also be a <details> element that discloses extra content in place.
12 items · Updated 2 hours ago
2.4 MB · Updated yesterday
8.1 MB · Updated last week
<ul class="stacked-list" style="max-inline-size: 32rem">
<li>
<article>
<div>
<h3>Design assets</h3>
<p>12 items · Updated 2 hours ago</p>
</div>
</article>
</li>
<li>
<article>
<div>
<h3>Q1 Report</h3>
<p>2.4 MB · Updated yesterday</p>
</div>
</article>
</li>
<li>
<article>
<div>
<h3>Brand guidelines</h3>
<p>8.1 MB · Updated last week</p>
</div>
</article>
</li>
</ul>
12 items · Updated 2 hours ago
2.4 MB · Updated yesterday
8.1 MB · Updated last week
<ul class="stacked-list is-divided" style="max-inline-size: 32rem">
<li>
<article>
<div>
<h3>Design assets</h3>
<p>12 items · Updated 2 hours ago</p>
</div>
</article>
</li>
<li>
<article>
<div>
<h3>Q1 Report</h3>
<p>2.4 MB · Updated yesterday</p>
</div>
</article>
</li>
<li>
<article>
<div>
<h3>Brand guidelines</h3>
<p>8.1 MB · Updated last week</p>
</div>
</article>
</li>
</ul>
<ul class="stacked-list is-compact is-divided" style="max-inline-size: 18rem">
<li>
<article class="is-interactive">
<div>
<h4><a href="#">April</a></h4>
</div>
<div class="trailing">3</div>
</article>
</li>
<li>
<article class="is-interactive">
<div>
<h4><a href="#">March</a></h4>
</div>
<div class="trailing">4</div>
</article>
</li>
<li>
<article class="is-interactive">
<div>
<h4><a href="#">February</a></h4>
</div>
<div class="trailing">2</div>
</article>
</li>
</ul>
12 items · Updated 2 hours ago
2.4 MB · Updated yesterday
8.1 MB · Updated last week
<ul class="stacked-list is-divided" style="max-inline-size: 32rem">
<li>
<article>
<div class="leading text-primary">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
/>
</svg>
</div>
<div>
<h3>Design assets</h3>
<p>12 items · Updated 2 hours ago</p>
</div>
</article>
</li>
<li>
<article>
<div class="leading text-success">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
<polyline points="14 2 14 8 20 8" />
</svg>
</div>
<div>
<h3>Q1 Report.xlsx</h3>
<p>2.4 MB · Updated yesterday</p>
</div>
</article>
</li>
<li>
<article>
<div class="leading text-danger">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
<polyline points="14 2 14 8 20 8" />
</svg>
</div>
<div>
<h3>Brand Guidelines.pdf</h3>
<p>8.1 MB · Updated last week</p>
</div>
</article>
</li>
</ul>
12 items · Updated 2 hours ago
2.4 MB · Updated yesterday
8.1 MB · Updated last week
<ul class="stacked-list is-divided" style="max-inline-size: 36rem">
<li>
<article>
<div class="leading text-primary">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
/>
</svg>
</div>
<div>
<h3>Design assets</h3>
<p>12 items · Updated 2 hours ago</p>
</div>
<div class="trailing">
<span class="cluster gap-2xs">
<span class="badge is-accent text--2">Shared</span>
</span>
</div>
</article>
</li>
<li>
<article>
<div class="leading text-success">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
/>
<polyline points="14 2 14 8 20 8" />
</svg>
</div>
<div>
<h3>Q1 Report.xlsx</h3>
<p>2.4 MB · Updated yesterday</p>
</div>
<div class="trailing">
<span class="badge is-success text--2">Synced</span>
</div>
</article>
</li>
<li>
<article>
<div class="leading text-danger">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
/>
<polyline points="14 2 14 8 20 8" />
</svg>
</div>
<div>
<h3>Brand Guidelines.pdf</h3>
<p>8.1 MB · Updated last week</p>
</div>
<div class="trailing">
<span class="badge is-warning text--2">Review</span>
</div>
</article>
</li>
</ul>
Taylor Kim · #312 · 3 hours ago
Casey Park · #308 · yesterday
Jordan Lee · #305 · 2 days ago
<ul class="stacked-list is-divided" style="max-inline-size: 36rem">
<li>
<article class="is-interactive">
<div class="leading">
<span class="avatar is-sm">
<img src="https://picsum.photos/seed/sl1/64/64" alt="" />
</span>
</div>
<div>
<h3><a href="#">Build failing after dependency update</a></h3>
<p>Taylor Kim · #312 · 3 hours ago</p>
</div>
<div class="trailing">
<span class="badge is-danger text--2">Open</span>
</div>
</article>
</li>
<li>
<article class="is-interactive">
<div class="leading">
<span class="avatar is-sm">
<img src="https://picsum.photos/seed/sl2/64/64" alt="" />
</span>
</div>
<div>
<h3><a href="#">Pagination offset off by one</a></h3>
<p>Casey Park · #308 · yesterday</p>
</div>
<div class="trailing">
<span class="badge is-success text--2">Resolved</span>
</div>
</article>
</li>
<li>
<article class="is-interactive">
<div class="leading">
<span class="avatar is-sm">
<img src="https://picsum.photos/seed/sl3/64/64" alt="" />
</span>
</div>
<div>
<h3><a href="#">Color tokens missing in dark mode</a></h3>
<p>Jordan Lee · #305 · 2 days ago</p>
</div>
<div class="trailing">
<span class="badge is-warning text--2">In review</span>
</div>
</article>
</li>
</ul>
8.1 MB · Updated last week
Logo lockups, color tokens, and approved typeface pairings. Two pages flagged for the next round of review; comments are pending.
Read-only · Last touched 2024
<ul class="stacked-list is-divided" style="max-inline-size: 36rem">
<li>
<details>
<summary>
<div class="leading text-success">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
/>
<polyline points="14 2 14 8 20 8" />
</svg>
</div>
<div>
<h3>Q1 Report.xlsx</h3>
<p>2.4 MB · Updated yesterday</p>
</div>
<div class="trailing">
<span class="badge is-success text--2">Synced</span>
</div>
</summary>
<div class="flow">
<p>
Final quarterly numbers for the leadership review. Regional breakdowns,
gross margin trends, and the headcount summary.
</p>
<p class="cluster gap-2xs">
<a href="#" class="button is-sm">Open</a>
<a href="#" class="button is-sm is-ghost">Share</a>
<a href="#" class="button is-sm is-ghost">Download</a>
</p>
</div>
</details>
</li>
<li>
<details>
<summary>
<div class="leading text-danger">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
/>
<polyline points="14 2 14 8 20 8" />
</svg>
</div>
<div>
<h3>Brand Guidelines.pdf</h3>
<p>8.1 MB · Updated last week</p>
</div>
<div class="trailing">
<span class="badge is-warning text--2">Review</span>
</div>
</summary>
<div>
<p>
Logo lockups, color tokens, and approved typeface pairings. Two pages
flagged for the next round of review; comments are pending.
</p>
</div>
</details>
</li>
<li>
<article>
<div class="leading text-primary">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
/>
</svg>
</div>
<div>
<h3>Archive (legacy)</h3>
<p>Read-only · Last touched 2024</p>
</div>
</article>
</li>
</ul>
Stacked list -- vertical row stack with optional dividers and an
(optional leading) | content | (optional trailing) layout per row.
Used for file/asset browsers, ticket queues, notification feeds,
settings rows, and similar repeating-row UIs where the row carries
chrome (padding, optional divider, optional hover) and a
three-region layout. For single-line nav rows with current-page
state and a rail, use .sidebar-link / .sidebar-nav. For menu rows
inside a popover use .dropdown.
Structure -- classed slots around a bare content div:
<ul class="stacked-list is-divided">
<li>
<article> <-- row; <article>, <section>,
<div class="leading"> <div>, or <details>
...
</div>
<div> <-- content region
<h3>Title</h3>
<p>Description</p>
</div>
<div class="trailing">...</div>
</article>
</li>
</ul>
.leading and .trailing are slot classes on generic <div>s (the
class is the hook, so any element works; <div> is canonical).
Generic elements carry no ARIA role, so the slots add no landmark
noise no matter which row element the author picks or where the
page nests the list. DOM order determines visual side via flex;
the growing content div pushes the trailing slot to the row's end
automatically.
Row element: <article> for self-contained pieces (file entries,
tickets, comments), <div> otherwise, <details> for revealable
rows (see below). <section> is accepted but adds nothing while
unnamed and becomes a region landmark per row if named; prefer
<article> or <div>. The CSS doesn't care which the author picks;
the .stacked-list class on the container is what scopes the
rules.
Revealable rows -- <details> as the row element
For rows that need to disclose extra content in-place (file
metadata, ticket comments, settings detail) the row element is
<details> and the three-region flex layout lives on <summary>:
<li>
<details>
<summary>
<div class="leading">...</div>
<div>
<h3>Title</h3>
<p>Description</p>
</div>
<div class="trailing">...</div>
</summary>
<div>
Revealed content. Any HTML.
</div>
</details>
</li>
A chevron at the trailing edge of <summary> rotates on open (same
idiom as .details; --details-chevron-* tokens reused so the
disclosure affordance reads consistently library-wide). The
global details::details-content rule in details.css animates the
expand/collapse -- no JS, no duplicated transition rules.
The reveal pane is every child of <details> except <summary>; it
inherits the row's inline padding and gets a small block-end
padding so its last child doesn't crash into the row's border.
Otherwise unopinionated -- consumer's HTML, no background, no
divider, no scoped tokens.
Revealable rows and .is-interactive are mutually exclusive by
design. The stretched heading-anchor click target and the native
<summary> click target would conflict; pick one shape per row.
Heading level (h2-h6) is the author's choice per document
hierarchy; the row normalizes visual size.
Whole-row interactivity -- .is-interactive on the row
Mirrors card.is-interactive: the heading's anchor receives a
::after that fills the row's bounds, so a click anywhere in the
row activates the link. The link's accessible name stays the
heading text, and nested interactive elements in the trailing
slot (a dropdown trigger, a button) remain operable because the
trailing slot is lifted with position: relative above the
stretched layer. Other nested interactives the consumer adds
inside the content div are their responsibility to lift.
Region alignment
Leading and trailing slots default to align-self: flex-start so
icons and avatars sit at the top of the row alongside the
heading. Override per-region via --stacked-list-leading-align /
--stacked-list-trailing-align (any align-self value: flex-start,
center, flex-end, stretch, baseline).
Source: src/css/stacked-list.css
.stacked-list
| Class | Kind | Description |
|---|---|---|
.is-divided | variant | Adds 1px border between sibling rows |
.is-compact | variant | Denser padding and tighter gap |
.is-interactive | variant | Hover highlight and stretched heading link for whole-row click |
| Slot | Description |
|---|---|
> .leading | Leading slot. Aligns to flex-start by default; tokenized so consumers can center an avatar in tightly-packed rows, etc. |
> .trailing | Trailing slot. Same flex-start default, independent token. |
> div:not(.leading, .trailing) | Content region -- bare <div> between the slots. Itself a flex column so heading and description stack with a small gap without consumers needing to wrap them in .flow. |
:is(h2, h3, h4, h5, h6) | Header region |
| Token | Default | Description |
|---|---|---|
--stacked-list-padding-block | var(--ui-pad-block-snug) | Row block-axis padding |
--stacked-list-padding-inline | var(--ui-pad-inline-snug) | Row inline-axis padding |
--stacked-list-gap | var(--ui-gutter-snug) | Gap between leading, content, and trailing regions |
--stacked-list-radius | var(--radius-sm) | Row corner radius, visible on hover |
--stacked-list-content-gap | var(--ui-gutter-tight) | Gap between heading and description in the content region |
--stacked-list-divider-color | var(--color-border-subtle) | Border color between rows when .is-divided is active |
--stacked-list-leading-align | flex-start | Vertical alignment of the leading slot |
--stacked-list-trailing-align | flex-start | Vertical alignment of the trailing slot |
--stacked-list-header-font-size | var(--font-size-base) | Heading font size |
--stacked-list-content-font-size | var(--font-size-xs) | Description and paragraph font size |
--stacked-list-chevron-size | 0.5em | Size of the revealable-row chevron |
--stacked-list-chevron-color | var(--color-text-muted) | Color of the revealable-row chevron |