Detent web components
By Shane Logsdon

Media & effects

Gravity Particle Burst

Implemented

Pointer-driven gravity particle feedback

detent-gravity-particle-burst

Port status
Catalog status
implemented
Origin
upstream
Phase
4
Wave
phase-4-canvas
Group
Media & effects
Commit release

4.0 KB gzip for the class module

Variants

Press any button: one burst of particle-count particles starts at the pointer and settles out. The burst is event-driven, not a loop — after the last particle dies the element schedules zero frames. The canvas overlay is aria-hidden and pointer-events: none, so it never blocks the button or a screen reader.

Publish release

The last button has no slotted content, so the slot fallback shows its label. With prefers-reduced-motion: reduce no particles fly at all and the button stays fully usable; the label/particleCount properties are the documented controls.

Recorded states

  • reduced motion recorded state; no setter

Usage

Import

import '/components/gravity-particle-burst/define.js';

// or register it yourself
import { DetentGravityParticleBurst } from '/components/gravity-particle-burst/gravity-particle-burst.js';

Attributes

  • label
  • particle-count

Properties

No properties are recorded for this component.

Slots

  • default

Events

No events are recorded for this component.

Example

Runnable example: site/examples/gravity-particle-burst.ts. The snippet below is generated from the catalogued attributes.

<detent-gravity-particle-burst
  label="Create particle burst"
  particle-count="34"
></detent-gravity-particle-burst>

Source

The pinned upstream source for this row:

  • src/components/ui/GravityParticleBurst.tsx sha256 f5d6735cf564…

Native files

The native module and its artifacts:

  • src/components/gravity-particle-burst/gravity-particle-burst.ts
  • src/components/gravity-particle-burst/styles.css
  • src/components/gravity-particle-burst/define.ts
  • docs/components/gravity-particle-burst.md
  • site/examples/gravity-particle-burst.ts
  • tests/browser/gravity-particle-burst.spec.ts
  • evidence/components/gravity-particle-burst.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
labellabelstring'Create particle burst'Kebab-case attribute; camelCase property.
particle-countparticleCountnumber34Kebab-case attribute; camelCase property.

Properties

No property-only values are recorded for this component.

Events

No custom events are recorded for this component.

Slots

Slots
SlotNotes
defaultConsumer content; rendered through a slot, never re-created.

CSS customisation

  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • particleCount defaults to 34 (catalog row and upstream meta) although the pinned source destructures 36; the catalog row is the API authority. Owner confirmed 34 on 2026-10-29.
  • lucide-react Sparkles becomes a local decorative inline SVG (ISC notice retained, PC-11.5).
  • The dark-only palette (#0E0E0E / #FAFAFA) becomes the shared theme tokens so the button is legible in light and dark (17.93:1 / 13.86:1).
  • particle-count is bounded to 0..400 and rounded; an empty label falls back to the default so the internal button always has an accessible name.
  • An in-flight burst is cancelled on disconnection instead of being left in the particle list.
  • label is the documented slot fallback (upstream children || label).

What it does

A real <button> with a pointer-triggered canvas particle burst: the particles inherit the pointer origin, arc under gravity and friction, and settle out.

Upstream behaviour
  • Particles inherit a shared origin from the pointer location
  • Canvas rendering keeps the effect performant without many DOM nodes
  • Gravity and friction make particles arc and settle naturally
Differences from upstream
  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • `lucide-react` icon components replaced with local SVG assets (ISC notice retained).
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • particleCount defaults to 34 (catalog row and upstream meta) although the pinned source destructures 36; the catalog row is the API authority. Owner confirmed 34 on 2026-10-29.
  • lucide-react Sparkles becomes a local decorative inline SVG (ISC notice retained, PC-11.5).
  • The dark-only palette (#0E0E0E / #FAFAFA) becomes the shared theme tokens so the button is legible in light and dark (17.93:1 / 13.86:1).
  • particle-count is bounded to 0..400 and rounded; an empty label falls back to the default so the internal button always has an accessible name.
  • An in-flight burst is cancelled on disconnection instead of being left in the particle list.
  • label is the documented slot fallback (upstream children || label).
Previous: Blob Menu Next: Hamburger Menu

Docs

Components

Project