<!-- Protocore Design System — OverflowList -->
# OverflowList

- **Category:** Data Display (`data-display`)
- **Slug:** `data-display/overflow-list`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { OverflowList } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/data-display/overflow-list

> A single-line list that measures its items and collapses whatever overflows into a trailing +N indicator.

## How it measures

An off-screen row always holds every item at its natural width; a `ResizeObserver` on the visible container recomputes how many fit whenever the width changes, reserving room for the indicator. Because the measurement is real layout (not a guess), it handles variable-width items — tags, chips, avatars, breadcrumb segments — without you declaring widths.

Use it wherever a horizontal set might not fit: a tag row on a card, a filter summary, a toolbar of actions, a breadcrumb trail. Set `min` to always keep a few items visible, and `gap` to match your row spacing so the math is exact.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `gap` | `number` | no | `8` | Gap between items in px (also reserved before the indicator). |
| `items` | `ReactNode[]` | yes | — | The items to lay out; each is measured and shown until the row runs out of room. |
| `min` | `number` | no | `0` | Minimum number of items to keep visible even under heavy overflow. |
| `overflowIndicator` | `((hiddenCount: number, hiddenItems: ReactNode[]) => ReactNode)` | no | — | Render the overflow affordance for the collapsed tail. Defaults to a `+N` count chip. Receives the hidden count and the hidden item nodes (e.g. to populate a DropdownMenu). |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Collapsing tags

Pass an array of `items`. The list renders as many as fit on one line and collapses the rest into a `+N` count chip. Resize the container — it remeasures and adjusts the split as room grows or shrinks.

```tsx
import { OverflowList, Tag } from "@protocore/pds";

const labels = [
  "next.js",
  "typescript",
  "terraform",
  "cloudfront",
  "postgres",
  "payload",
  "s3",
  "caddy",
];

export default function OverflowListBasics() {
  return (
    <div style={{ maxWidth: 320, resize: "horizontal", overflow: "auto", padding: 8 }}>
      <OverflowList items={labels.map((l) => <Tag key={l}>{l}</Tag>)} gap={6} />
    </div>
  );
}
```

### Overflow into a menu

`overflowIndicator` replaces the default chip with your own affordance and hands you the hidden count and the hidden item nodes — drop them into a **DropdownMenu** so the collapsed items stay reachable.

```tsx
import { OverflowList, Tag, DropdownMenu } from "@protocore/pds";

const labels = [
  "next.js",
  "typescript",
  "terraform",
  "cloudfront",
  "postgres",
  "payload",
  "s3",
  "caddy",
];

export default function OverflowListMenu() {
  return (
    <div style={{ maxWidth: 300, resize: "horizontal", overflow: "auto", padding: 8 }}>
      <OverflowList
        gap={6}
        items={labels.map((l) => (
          <Tag key={l}>{l}</Tag>
        ))}
        overflowIndicator={(count, hidden) => (
          <DropdownMenu.Root>
            <DropdownMenu.Trigger asChild>
              <button type="button" className="pds-OverflowList-more" aria-label={`${count} more`}>
                +{count}
              </button>
            </DropdownMenu.Trigger>
            <DropdownMenu.Content>
              {hidden.map((item, i) => (
                <DropdownMenu.Item key={i}>{item}</DropdownMenu.Item>
              ))}
            </DropdownMenu.Content>
          </DropdownMenu.Root>
        )}
      />
    </div>
  );
}
```

## Usage

**Do**

- Feed it variable-width items — tags, chips, avatars, crumbs.
- Use `overflowIndicator` to make the tail reachable via a menu.
- Match `gap` to your visual row spacing.
- Set `min` to guarantee a few items always show.

**Don't**

- Rely on it for vertical wrapping; it's a single-line collapser.
- Hide critical actions behind `+N` with no menu to reveal them.
- Give it thousands of items; it measures every one.

## Accessibility

**Notes**

- The measurement row is `aria-hidden`, so assistive tech sees each item only once.
- The default `+N` chip carries an `aria-label` ("N more"); when you supply a menu indicator, the collapsed items remain reachable through it.

## Related

`tags-input`, `chip`, `dropdown-menu`, `breadcrumb`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
