ComponentsList

List

atom

Rows of items with lead media, meta and trailing actions or badges.

Library
Your files and account.
Storage
Account

Recipe CSS

This is the exact CSS your kit ships for List — token-driven, so it re-themes with every knob. Get it (and the rest) from the configurator's Use kit panel.

/* === List (Tier 4 #16) ===============================================
 * Generic list primitive — sections, dividers, leading slot (icon or
 * avatar circle), title + sub, optional trailing slot (chevron / value
 * / text-link). Rows volgen het row grammar (--k-row-h-lg). */
.list {
  display: flex;
  flex-direction: column;
  margin: calc(var(--k-s-4) * -1) 0;
}
.list__section {
  padding: var(--k-s-12) 0 var(--k-s-4);
  font-size: var(--k-type-caption);
  font-weight: var(--k-weight-semibold);
  letter-spacing: var(--k-track-eyebrow);
  text-transform: uppercase;
  color: var(--k-fg-faint);
  /* Sticky section header (the iOS grouped-list pattern): pins to the top when the
     list lives in a scroll container, so the group label stays in view as its rows
     scroll under it. A no-op in normal flow. Opaque bg so rows don't show through. */
  position: sticky; top: 0; z-index: 1;
  background: var(--k-surface);
}
.list__section:first-child { padding-top: var(--k-s-4); }
.list__item {
  display: flex;
  align-items: center;
  gap: var(--k-row-gap, 10px);
  /* Horizontal padding + matching negative margin = the hover bg breathes into
     the card padding while the CONTENT stays edge-aligned with the section
     labels. border-radius makes the hover follow the Box radius (no more square
     grey at Soft). Same idiom as menu/nav rows. */
  position: relative;
  padding: var(--k-s-8);
  margin-inline: calc(var(--k-s-8) * -1);
  border: 0;
  border-radius: var(--k-radius-sm);
  background: transparent;
  text-align: left;
  font: inherit;
  color: var(--k-fg);
  cursor: pointer;
}
/* Divider = a FLAT top line via a pseudo-element, NOT border-top — so it never
   inherits the row's Box radius (border-top would curve down at the corners on
   Soft). The radius now rounds only the hover bg; the divider stays straight.
   Width follows the Borders control (--k-bw → gone at Off); inset by the radius
   so it meets the rounded hover corner cleanly (full-bleed at Box=None). */
.list__item::before {
  content: '';
  position: absolute;
  top: 0;
  left: var(--k-radius-sm);
  right: var(--k-radius-sm);
  height: var(--k-bw, 1px);
  background: var(--k-border);
}
.list__item:first-of-type::before { content: none; }
.list__item:hover { background: var(--k-state-hover); }
/* Selected row (Invariant I2) — a row picked in a master/detail or multi-select
   list. Was missing (only --unread existed), so the most-used flat row sat a tier
   behind its own siblings (.list__row / .navrow both carry it). The chromatic fill
   + the selected-edge match the table/menu selected language → reads at any depth. */
.list__item[aria-selected="true"], .list__item.is-selected {
  background: var(--k-state-selected-bg, var(--k-primary-soft));
  box-shadow: var(--k-selected-edge);
}
.list__item[aria-selected="true"]:hover, .list__item.is-selected:hover { filter: brightness(0.98); }
/* Hit-target floor (Invariant I4) — an interactive row clears the WCAG-2.2 24px
   target even at Compact density; generalises the .tbl guard so list rows stop
   being a per-component afterthought. */
button.list__item, a.list__item, .list__item:has(input, button, a, [role="button"]) { min-block-size: var(--k-hit-min); }
.list__lead {
  flex-shrink: 0;
  width: calc(var(--k-in-h-default) - 0.25rem);
  height: calc(var(--k-in-h-default) - 0.25rem);
  display: grid;
  place-items: center;
  border-radius: var(--k-radius-sm);
}
.list__lead--icon {
  background: var(--k-primary-soft);
  color: var(--k-primary-soft-fg);
}
.list__lead--icon svg { width: var(--k-icon-sm); height: var(--k-icon-sm); }
.list__lead--avatar {
  background: var(--k-secondary-soft);
  color: var(--k-secondary-soft-fg);
  border-radius: 50%;
  font-size: var(--k-type-eyebrow);
  font-weight: var(--k-weight-semibold);
}
.list__body { flex: 1; min-width: 0; }
.list__title {
  font-size: var(--k-type-small);
  font-weight: var(--k-weight-medium);
  color: var(--k-fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.list__sub {
  font-size: var(--k-type-eyebrow);
  color: var(--k-fg-muted);
  margin-top: 1px;
}
.list__trail {
  flex-shrink: 0;
  color: var(--k-fg-muted);
  display: flex;
  align-items: center;
}
.list__trail--text {
  font-size: var(--k-type-eyebrow);
  font-weight: var(--k-weight-medium);
  color: var(--k-primary);
}
/* --- List CONTAINER variants — one row system; the container sets divider +
   hover behaviour, the slot/title modifiers do the rest.
     .list           default — top-divider rows, hover (data / entity lists)
     .list--flush    no dividers, hover (tight feeds: notifications, inbox)
     .list--settings bottom-divider rows, static (settings: title/desc + control) */
.list--flush .list__item::before { content: none; }
.list--settings .list__item {
  border-top: 0;
  border-bottom: var(--k-divider);
  padding: var(--k-s-14) 0;
  margin-inline: 0;
  border-radius: 0;
  cursor: default;
}
/* Settings rows are square (radius 0) + keep their own straight border-bottom. */
.list--settings .list__item::before { content: none; }
.list--settings .list__item:hover { background: transparent; }
.list--settings .list__item:last-of-type { border-bottom: 0; }
.list--settings .list__title { font-weight: var(--k-weight-semibold); }
/* Lead variant — neutral round icon chip (notifications / system rows) */
.list__lead--icon-muted {
  background: var(--k-surface-sunken);
  color: var(--k-fg-muted);
  border-radius: 50%;
}
.list__lead--icon-muted svg { width: var(--k-icon-md); height: var(--k-icon-md); }
/* Title size — larger + wrapping, for notification/feed rows */
.list__title--lg { font-size: var(--k-type-body); white-space: normal; }
/* Unread row — bold title + trailing dot */
.list__item--unread .list__title { font-weight: var(--k-weight-bold); }
.list__dot { width: var(--k-dot); height: var(--k-dot); border-radius: 50%; background: var(--k-primary); flex: none; align-self: center; }
/* --cols: two-column stacked list (Tailwind "stacked list, two columns") — rows
   flow into two columns on a wide container, one when narrow; section headings
   span the full width. Reset the row's negative inline margin so the hover bg
   doesn't bleed into the column gutter. */
.list--cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); column-gap: var(--k-s-24); margin: 0; }
.list--cols .list__item { margin-inline: 0; }
.list--cols .list__section { grid-column: 1 / -1; }
/* --sticky: section headings pin to the top while their group scrolls past
   (Tailwind "stacked list with sticky headings"). Put the list in a scroll
   container; the heading gets a surface fill so rows don't show through it. */
.list--sticky .list__section { position: sticky; top: 0; z-index: 1; background: var(--k-surface); }