Marble UI
← Components

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>

PropTypeDefaultDescription
getLabel *required(item: T) => string—
items *requiredT[]—
renderItem *required(item: T) => ReactNode—
classNamestring—
gapnumber6
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}
/>
  • renderItem draws the visible chips; getLabel gives the menu text for hidden ones. Every item renders twice (once invisibly, to measure), so keep renderItem free of side effects and fixed ids.
  • The “+N” button is labelled “N more” and opens a Menu of hidden labels. If your chips are links or buttons, pass getHref(item) and/or onAction(item) so the hidden entries navigate or act from the menu too.
  • It measures its parent’s width, so give it a bounded container. gap is in pixels (default 6); about 44 px is reserved for the “+N” button.
Example source · show
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