Overflow List
Preview: Tags
Shows as many items as fit on one line and collapses the rest into a "+N" menu. Re-measures on resize. Pass `renderItem` for the visible chips and `getLabel` for the menu text. If the chips are links or buttons, pass `getHref` and/or `onAction` so the same entries in the "+N" menu navigate or act too.
Import
import { OverflowList } from '@marbleui/ui'Props
<OverflowList>
| Prop | Type | Default | Description |
|---|---|---|---|
| getLabel *required | (item: T) => string | — | |
| items *required | T[] | — | |
| renderItem *required | (item: T) => ReactNode | — | |
| className | string | — | |
| gap | number | 6 | |
| getHref | (item: T) => string | undefined | — | |
| onAction | (item: T) => void | — |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: React Aria Button. Follow the primitive's docs for the full keyboard map.
Usage notes
One row of chips that shows what fits and collapses the rest into a “+N” menu, re-measured when the container resizes. For selectable or removable tags use TagGroup; to wrap onto more lines use HStack with wrap.
<OverflowList
items={labels}
renderItem={(label) => <Badge>{label}</Badge>}
getLabel={(label) => label}
/>
renderItemdraws the visible chips;getLabelgives the menu text for hidden ones. Every item renders twice (once invisibly, to measure), so keeprenderItemfree of side effects and fixedids.- The “+N” button is labelled “N more” and opens a
Menuof hidden labels. If your chips are links or buttons, passgetHref(item)and/oronAction(item)so the hidden entries navigate or act from the menu too. - It measures its parent’s width, so give it a bounded container.
gapis in pixels (default 6); about 44 px is reserved for the “+N” button.
Example source · show· hide
import { Avatar } from '../avatar'
import { Badge } from '../badge'
import { OverflowList } from './overflow-list'
const tags = ['design-system', 'accessibility', 'react-aria', 'tailwind', 'motion', 'charts', 'ai', 'dark-mode', 'i18n', 'tokens']
const people = ['Maya Chen', 'Charles Webb', 'Ada Park', 'Grace Hopper', 'Leo Martins', 'Priya Nair', 'Sam Okafor']
export const styles = {
Tags: () => <div className="w-[26rem] max-w-full resize-x overflow-hidden rounded-xl border border-border p-3"><OverflowList items={tags} getLabel={(t) => t} renderItem={(t) => <Badge>{t}</Badge>} /><p className="mt-2 text-xs text-fg-subtle">Drag the corner to resize.</p></div>,
People: () => <div className="w-64 rounded-xl border border-border p-3"><OverflowList items={people} gap={4} getLabel={(p) => p} renderItem={(p) => <span className="inline-flex items-center gap-1 rounded-full bg-surface-muted py-0.5 pr-2 pl-0.5 text-xs text-fg"><Avatar size="xs" name={p} />{p.split(' ')[0]}</span>} /></div>,
}Source: packages/ui/src/overflow-list/overflow-list.tsx
Catalog
- Category
- data-display
- Priority
- Extra
- Primitive
- custom