Cluster
since v2.1.0Horizontal flex row with wrapping — enforces spacing-scale gap values.
Install
Add the package and import the component.
pnpm add @hey-mike/tungstenpnpm add @hey-mike/tungstenimport { Cluster } from '@hey-mike/tungsten';import { Cluster } from '@hey-mike/tungsten';Preview
Same fixtures used by the visual-regression suite.
Usage
apps/docs/app/snapshots/cluster/page.tsx
import { Cluster } from '@hey-mike/tungsten';
import { HeroSpecimen } from '../_components/HeroSpecimen';
const TAGS = ['design', 'system', 'tokens', 'components', 'layout', 'motion', 'color', 'type'];
function Tag({ label }: { label: string }) {
return (
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-1 font-mono text-xs text-ink-2">
{label}
</span>
);
}
export default function ClusterSnapshot() {
return (
<main data-testid="snapshot-root" className="bg-page text-ink-1 min-h-screen py-8">
<h1 className="text-ink-2 mb-8 px-8 font-mono text-sm uppercase tracking-widest">Cluster</h1>
<dl className="flex flex-col gap-10 px-8">
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=2</dt>
<dd className="m-0">
<Cluster gap={2}>
{TAGS.map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 (default)</dt>
<dd className="m-0">
<Cluster gap={4}>
{TAGS.map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=6 · align=center</dt>
<dd className="m-0">
<Cluster gap={6} align="center">
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-1 font-mono text-xs text-ink-2">small</span>
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-3 font-mono text-xs text-ink-2">tall</span>
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-1 font-mono text-xs text-ink-2">small</span>
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-3 font-mono text-xs text-ink-2">tall</span>
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 · justify=between</dt>
<dd className="m-0">
<Cluster gap={4} justify="between">
{['left', 'center', 'right'].map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=3 · align=baseline · wrapping</dt>
<dd className="m-0">
<Cluster gap={3} align="baseline">
{[...TAGS, 'accessibility', 'dark mode', 'spacing', 'icons'].map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
</dl>
{/* Gallery thumbnail (`?hero`): a few pills wrap into two tidy rows.
Hidden in the detail view; revealed by the hero CSS. */}
<div data-hero-specimen className="hidden">
<HeroSpecimen>
<Cluster gap={2}>
{['design', 'system', 'tokens', 'layout', 'motion'].map((t) => (
<Tag key={t} label={t} />
))}
</Cluster>
</HeroSpecimen>
</div>
</main>
);
}
import { Cluster } from '@hey-mike/tungsten';
import { HeroSpecimen } from '../_components/HeroSpecimen';
const TAGS = ['design', 'system', 'tokens', 'components', 'layout', 'motion', 'color', 'type'];
function Tag({ label }: { label: string }) {
return (
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-1 font-mono text-xs text-ink-2">
{label}
</span>
);
}
export default function ClusterSnapshot() {
return (
<main data-testid="snapshot-root" className="bg-page text-ink-1 min-h-screen py-8">
<h1 className="text-ink-2 mb-8 px-8 font-mono text-sm uppercase tracking-widest">Cluster</h1>
<dl className="flex flex-col gap-10 px-8">
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=2</dt>
<dd className="m-0">
<Cluster gap={2}>
{TAGS.map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 (default)</dt>
<dd className="m-0">
<Cluster gap={4}>
{TAGS.map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=6 · align=center</dt>
<dd className="m-0">
<Cluster gap={6} align="center">
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-1 font-mono text-xs text-ink-2">small</span>
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-3 font-mono text-xs text-ink-2">tall</span>
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-1 font-mono text-xs text-ink-2">small</span>
<span className="bg-brand-overlay-08 border border-brand-overlay-20 rounded-lg px-3 py-3 font-mono text-xs text-ink-2">tall</span>
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=4 · justify=between</dt>
<dd className="m-0">
<Cluster gap={4} justify="between">
{['left', 'center', 'right'].map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
<div>
<dt className="text-ink-3 mb-2 font-mono text-xs">gap=3 · align=baseline · wrapping</dt>
<dd className="m-0">
<Cluster gap={3} align="baseline">
{[...TAGS, 'accessibility', 'dark mode', 'spacing', 'icons'].map((t) => <Tag key={t} label={t} />)}
</Cluster>
</dd>
</div>
</dl>
{/* Gallery thumbnail (`?hero`): a few pills wrap into two tidy rows.
Hidden in the detail view; revealed by the hero CSS. */}
<div data-hero-specimen className="hidden">
<HeroSpecimen>
<Cluster gap={2}>
{['design', 'system', 'tokens', 'layout', 'motion'].map((t) => (
<Tag key={t} label={t} />
))}
</Cluster>
</HeroSpecimen>
</div>
</main>
);
}
Props
Surface specific to <Cluster />.
| Prop | Type | Default | Description |
|---|---|---|---|
| gap | 0 | 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12 | 4 | — |
| align | "start" | "center" | "end" | "baseline" | — | Cross-axis alignment. stretch is intentionally absent — use Stack for column layouts. |
| justify | "start" | "center" | "end" | "between" | "around" | — | — |