Particle Field
Ambient floating particle system with CSS-only staggered animations.
pnpm dlx @glinui/cli@latest add particle-fieldPresence for every page, in one hook
Show who is viewing, typing and pointing without running your own socket servers or paying per connection.
Works with
- Vercel
- GitHub
- Cloudflare
- Astro
Installation$
pnpm dlx @glinui/cli@latest add particle-fieldPrefer the package?
Usage$
Place ParticleField inside a relative container with overflow-hidden. Particles float upward with deterministic positioning, no layout shift between renders.
Examples$
Variants$
import { ParticleField } from "@glinui/ui"
export function Variants() { return ( <div data-glin-theme="dark" className="grid w-full gap-3 sm:grid-cols-3"> <div className="relative isolate flex h-44 items-end overflow-hidden rounded-xl bg-[var(--surface-0)] p-3"> <ParticleField count={30} /> <span className="relative z-10 rounded-full bg-black/70 px-2.5 py-1 text-xs font-medium text-white">Default</span> </div> <div className="relative isolate flex h-44 items-end overflow-hidden rounded-xl bg-[var(--surface-0)] p-3"> <ParticleField count={30} shape="square" maxSize={5} /> <span className="relative z-10 rounded-full bg-black/70 px-2.5 py-1 text-xs font-medium text-white">Squares</span> </div> <div className="relative isolate flex h-44 items-end overflow-hidden rounded-xl bg-[var(--surface-0)] p-3"> <ParticleField count={24} distance={140} duration={10} /> <span className="relative z-10 rounded-full bg-black/70 px-2.5 py-1 text-xs font-medium text-white">Long drift</span> </div> </div> )}Behind a dashboard header$
Production, last 24 hours
API overview
- Requests
- 2.41M
- +8.2% vs yesterday
- p95 latency
- 184 ms
- -12 ms vs yesterday
- Error rate
- 0.03%
- -0.01% vs yesterday
import { ParticleField, Button, Heading, Text } from "@glinui/ui"
const stats = [ ["Requests", "2.41M", "+8.2%"], ["p95 latency", "184 ms", "-12 ms"], ["Error rate", "0.03%", "-0.01%"]]
export function UsageHeader() { return ( <section data-glin-theme="dark" className="relative isolate flex min-h-[22rem] w-full flex-col justify-end gap-6 overflow-hidden rounded-xl bg-[var(--surface-0)] p-6 sm:p-8"> <ParticleField count={40} /> <div className="relative z-10 flex flex-wrap items-end justify-between gap-4"> <div className="flex flex-col gap-1"> <Text variant="eyebrow">Production, last 24 hours</Text> <Heading level={2} size="md">API overview</Heading> </div> <div className="flex gap-2"> <Button size="sm" variant="outline">Export CSV</Button> <Button size="sm">Create alert</Button> </div> </div> <dl className="relative z-10 grid gap-3 sm:grid-cols-3"> {stats.map(([label, value, delta]) => ( <div key={label} className="rounded-xl border border-[var(--line-soft)] bg-[var(--surface-1)] p-4"> <dt className="text-xs text-[var(--color-muted)]">{label}</dt> <dd className="mt-1 text-2xl font-semibold tabular-nums text-[var(--color-foreground)]">{value}</dd> <dd className="text-xs text-[var(--tone-success-text)]">{delta} vs yesterday</dd> </div> ))} </dl> </section> )}Accessibility$
- The component renders with
aria-hidden, invisible to assistive technologies. - Purely decorative; carries no semantic meaning.
Reduced Motion$
All particle animations are paused via motion-reduce:[animation:none]. The static particles remain visible.
API Reference$
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
color | string | No | - | Particle color |
count | number | No | 30 | Number of particles |
distance | number | No | 200 | Float distance in px |
duration | number | No | 5 | Float duration in seconds |
maxSize | number | No | 5 | Max particle size in px |
minSize | number | No | 2 | Min particle size in px |
shape | "circle" | "square" | No | "circle" | Particle shape |
Source$
import { ParticleField } from "@glinui/ui"Generated API Snapshot
Beta
Generated API Snapshot
BetaAuto-extracted from TypeScript source in packages/ui/src/components/particle-field.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.
Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata
Primary Props Type
ParticleFieldProps
ParticleFieldProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
color | string | No | - | Particle color |
count | number | No | 30 | Number of particles |
distance | number | No | 200 | Float distance in px |
duration | number | No | 5 | Float duration in seconds |
maxSize | number | No | 5 | Max particle size in px |
minSize | number | No | 2 | Min particle size in px |
shape | "circle" | "square" | No | "circle" | Particle shape |