AppStackedList

Labeled stacked list of items (members, inbox, threads, notifications). Each row: leading element + title + meta + description + trailing actions. Rows become a single linked surface when href is set. Distinct from app-data-table (no columns / no header). Presentational and theme-driven.

Installation

pnpm
pnpm dlx @hex-core/cli add app-stacked-list

Usage

tsx
import { AppStackedList } from "@/components/ui/app-stacked-list"

Workspace members list

Avatar + name + role + actions per row.

tsx
import { AppStackedList, Avatar, AvatarFallback, Button } from "@hex-core/components";

<AppStackedList
  title="Members"
  items={[
    {
      title: "Ada Lovelace",
      description: "ada@example.com",
      meta: "Owner",
      leading: <Avatar><AvatarFallback>AL</AvatarFallback></Avatar>,
      actions: <Button variant="ghost" size="sm">Manage</Button>,
    },
  ]}
/>

API Reference

PropTypeDefaultDescription
itemsrequired
objectReadonlyArray<{ title; description?; meta?; leading?: ReactNode; actions?: ReactNode; href? }>. Set href to make the whole row a single linked anchor.
eyebrow
ReactNodeSection eyebrow above the title.
title
ReactNodeSection heading.
description
ReactNodeSection subcopy below the heading.
divided
booleantrueShow dividers between rows. Defaults to true.
className
stringAdditional classes applied to the root wrapper.

AI Guidance

When to use

Use for lists where each item is one entity (a person, a thread, a notification) — not tabular data. Set href to make the whole row a link to the item's detail page. For multi-column data, use app-data-table.

When not to use

Don't use for tabular data with sortable columns (use app-data-table). Don't put more than ~50 items without virtualization — long lists need a scroll container or pagination.

Common mistakes

  • Putting actions inside a clickable row (href set) — nested interactive elements break the row's linked behavior. Either drop the row href and link the title, OR drop per-row actions.
  • Long descriptions that wrap — the row uses `truncate`; long descriptions get clipped. Move detail to a hover popover or expanded view.
  • Using AppStackedList for what should be data-table (sortable columns) — the patterns are intentionally different.

Accessibility

When href is set the row is a single anchor with an accessible name from the title. Focus ring is inset so it doesn't get clipped by the rounded container. Trailing actions inside a linked row are an anti-pattern (nested interactive); the schema notes this.

Token budget: 944