Overflow List

A single-row list (avatars, tags, breadcrumbs-like items) that measures the available width and folds whatever doesn't fit into a "+N" indicator, instead of wrapping or clipping.

Real use · assignee avatars, resizable to see the fold point

ALGHATKJMHRPBLTB

Tags with custom overflow renderer

design-systemaccessibilityperformancedark-modetokenstypographymotion

Using Overflow List

Silica ships one design system through three paths. They share a class vocabulary but are not interchangeable — pick the one that matches what you are building.

Plain HTML — CSS classes

The Tailwind v4 plugin. Works in any framework or none — Rails, Django, PHP, Go, a static file. This path ships no JavaScript, so Overflow List is styled but inert: its behavior comes from overflow-list. For that behavior with no framework, use the node-tree path below.

/* in your CSS */
@import "tailwindcss";
@plugin "@wizeworks/silicaui";

Root class overflow-list, with 3 modifiers:

  • .overflow-list
  • .overflow-list-badge
  • .overflow-list-measure
  • .overflow-list-popup

React

Typed components over those same classes, with behavior and accessibility from Base UI.

npm i @wizeworks/silicaui-react
import { OverflowList } from "@wizeworks/silicaui-react";

Props

PropTypeRequiredDescription
itemsT[]yes—
renderItem(item: T, index: number) => React.ReactNodeyes—
renderOverflow(hiddenItems: T[]) => React.ReactNodenoRender the trailing overflow indicator given the items that didn't fit. Default: a "+N" badge that opens a popover listing them (via renderItem).
gapnumbernoGap between items, in px. Default 8.
classNamestringno—
"aria-label"stringno—

Source of the demo above

The exact file that renders the examples above, so it can never drift from them. It imports a few of this site’s own layout helpers (../lib/…), so read it for the component calls rather than copying it whole.

Show source
import { useState } from "react";
import { OverflowList, Avatar, Badge } from "@wizeworks/silicaui-react";
import { Section } from "../lib/Section";

const PEOPLE = [
    "Ada Lovelace",
    "Grace Hopper",
    "Alan Turing",
    "Katherine Johnson",
    "Margaret Hamilton",
    "Radia Perlman",
    "Barbara Liskov",
    "Tim Berners-Lee",
];

const TAGS = ["design-system", "accessibility", "performance", "dark-mode", "tokens", "typography", "motion"];

export function OverflowListDemo() {
    const [width, setWidth] = useState(420);

    return (
        <>
            <Section title="Real use · assignee avatars, resizable to see the fold point">
                <div className="flex flex-col gap-3">
                    <input
                        type="range"
                        min={120}
                        max={640}
                        value={width}
                        onChange={(e) => setWidth(Number(e.target.value))}
                        className="max-w-md"
                    />
                    <div style={{ width }} className="rounded-box border border-base-300 p-3">
                        <OverflowList
                            items={PEOPLE}
                            renderItem={(name) => (
                                <Avatar key={name} alt={name} color="primary" size="sm">
                                    {name
                                        .split(" ")
                                        .map((w) => w[0])
                                        .join("")}
                                </Avatar>
                            )}
                        />
                    </div>
                </div>
            </Section>

            <Section title="Tags with custom overflow renderer">
                <div className="w-80 rounded-box border border-base-300 p-3">
                    <OverflowList
                        items={TAGS}
                        gap={6}
                        renderItem={(tag) => (
                            <Badge key={tag} color="neutral" variant="soft">
                                {tag}
                            </Badge>
                        )}
                        renderOverflow={(hidden) => (
                            <Badge color="primary" variant="soft" title={hidden.join(", ")}>
                                +{hidden.length} more
                            </Badge>
                        )}
                    />
                </div>
            </Section>
        </>
    );
}

Vanilla — node tree to HTML

overflow-list — real items reparent into the panel behind a "+N" trigger once they don't fit; params.maxVisible forces a fixed count when real layout isn't available (see overflow-list.ts). Build a node tree, project it with toHtml(), and let the zero-dependency runtime hydrate it. This is the path for generated or user-authored documents — a site builder, CMS output, a static export.

npm i @wizeworks/silicaui-html @wizeworks/silicaui-behaviors
import { atom, toHtml } from "@wizeworks/silicaui-html";

const node = atom("OverflowList", "overflow-list", { /* props */ }, [/* children */]);
const markup = toHtml(node);

Styling on this path is the class string in the second argument — the same classes as the Plain HTML section above. There is no color prop here; write "overflow-list overflow-list-primary" rather than passing a colour as a prop.

Takes children
yes
Hydrated by
overflow-list

Load @wizeworks/silicaui-behaviors on the page or this markup renders correctly and does nothing.

The full API for Overflow List, on every path, is available through the Silica MCP server.