Cluster Primitive
Free · MITHorizontal wrapping group primitive for tag lists, pills, and button groups using flex-wrap plus gap.
- Category
- Bento & Layout
- Framework
- astro
- Version
- 1.0.0
- Peer deps
- none
Install
velocityx add cluster
Free and MIT licensed — no account needed. The file lands under src/components/velocity/cluster/ by default (override with --dest), and it's yours to edit from the moment it's written.
Demo
View the live demo on the showcase site ↗
Source
Pulled live from the registry — this is the exact file velocityx add cluster writes into your project right now.
components/velocity/cluster/Cluster.astro
---
// VELOCITY COMPONENT · theming
//
// Colours here are Tailwind `primary-*` / `accent-*`, which resolve through
// the Velocity preset. Out of the box they are a neutral indigo — NOT the
// Aidxn brand — so this drops into your project without dragging our look in.
//
// ⚡ NOT USING VELOCITY? Run this once, in your project root:
//
// velocityx theme
//
// It writes velocity-preset.cjs + velocity-theme.css. Add the preset to your
// tailwind.config, import the css, then set your whole brand in ONE place:
//
// :root {
// --vx-brand: custom;
// --vx-primary-600: 220 38 38; <- your action colour
// --vx-primary-700: 185 28 28;
// }
//
// ⚠️ Raw RGB channels, space separated — NOT hex. `#DC2626` here silently
// breaks every /opacity variant in the library (bg-primary-600/20 etc).
//
// Prefer not to install anything? Find-and-replace `primary-` with your own
// scale name. Nothing else in this file depends on Velocity.
/**
* Cluster — Horizontal grouping primitive that wraps gracefully (tag
* lists, filter pills, button groups, badge rows). Uses `flex-wrap` + `gap`
* so items reflow onto new lines with consistent spacing in both axes —
* no manual `mr-2 mb-2` combinatorics that break on wrap.
*/
export interface Props {
as?: 'div' | 'ul';
space?: 1 | 2 | 3 | 4 | 5 | 6 | 8;
align?: 'start' | 'center' | 'end' | 'baseline';
justify?: 'start' | 'center' | 'end' | 'between';
className?: string;
}
const {
as: As = 'div',
space = 2,
align = 'center',
justify = 'start',
className = '',
} = Astro.props;
const SPACE: Record<number, string> = {
1: 'gap-1', 2: 'gap-2', 3: 'gap-3', 4: 'gap-4', 5: 'gap-5', 6: 'gap-6', 8: 'gap-8',
};
const ALIGN: Record<string, string> = {
start: 'items-start',
center: 'items-center',
end: 'items-end',
baseline: 'items-baseline',
};
const JUSTIFY: Record<string, string> = {
start: 'justify-start',
center: 'justify-center',
end: 'justify-end',
between: 'justify-between',
};
---
<As class:list={['flex flex-wrap', SPACE[space], ALIGN[align], JUSTIFY[justify], className]}>
<slot />
</As>
Theming
Uses the shared primary-* / accent-* scale — see Theming if colours look unstyled after install.