Liking cljdoc? Tell your friends :D

x-confetti

A celebration effect component that emits a burst of confetti particles on demand. Stateless: configuration lives in attributes; the particle simulation is ephemeral. Triggering is imperative via el.fire() — confetti is an event, not a state.

Attributes

AttributeValuesDefault
modeoverlay | inlineoverlay
origintop | center | bottom | pointtop
countinteger, clamped to [1, 300]80
spreaddegrees, clamped to [0, 180] (half-angle around base)60
velocitypx/frame, clamped to [1, 60]14
gravitypx/frame², clamped to [-2, 2]0.25
durationms, clamped to [200, 20000] (max particle lifetime)4000
colorscomma-separated CSS colorstheme palette
shapescomma-separated subset of square,circle,ribbon,starsquare,ribbon
auto-fireboolean (presence) — fires once per element instanceabsent
disabledboolean (presence) — fire() is a no-opabsent

Invalid values are silently corrected to defaults. The colors and shapes attributes accept whitespace around commas.

For origin="center" and origin="point", particles are launched in all directions (the spread attribute has no effect). For top and bottom, particles spread ±spread° around the vertical axis.

auto-fire triggers exactly once per element instance, on its first connectedCallback. Removing and re-adding the attribute, or detaching and reattaching the element, will not re-fire — use el.fire() for explicit re-triggering.

Properties

All attributes have matching JS properties that reflect to/from their HTML attribute. The boolean auto-fire attribute maps to the autoFire JS property.

Methods

fire(options?)

Trigger a burst. Returns void. Concurrent calls are additive — each call adds particles to the live simulation.

options is an optional plain object. Any field omitted falls back to the current attribute value:

FieldTypeNotes
countnumberParticles to spawn (clamped to [1, 300]).
originstringSame vocabulary as the origin attribute.
originXnumberCSS pixels relative to the canvas. Used only when origin === "point".
originYnumberCSS pixels relative to the canvas. Used only when origin === "point".
spreadnumberHalf-angle in degrees, clamped to [0, 180].
velocitynumberInitial speed (px/frame), clamped to [1, 60].
gravitynumberPer-frame acceleration, clamped to [-2, 2].
durationnumberMax particle lifetime (ms), clamped to [200, 20000].
colorsstring | string[]Override palette for this burst.
shapesstring | string[]Override shapes for this burst.
const c = document.querySelector("x-confetti");
c.fire();                                            // use current config
c.fire({ count: 120, origin: "center" });            // omni-burst
c.fire({ origin: "point", originX: 200, originY: 80 });
c.fire({ colors: ["#ff0066", "#00ccaa", "gold"] });

Events

EventDetailWhen
x-confetti-fire{ count: number, origin: string }At the start of every fire() call (also fires on auto-fire and under reduced motion).
x-confetti-end{ duration: number }When the last live particle has despawned. Under reduced motion, fires immediately with duration: 0.

Both events bubble and are composed; neither is cancelable.

Slots

None. The component is decorative-only.

Shadow parts

PartElementPurpose
canvas-wrap<div>Absolute-positioned container for the canvas.
canvas<canvas>The 2D drawing surface.

Target with ::part() to override layout (rare):

x-confetti::part(canvas-wrap) { /* e.g. clip with border-radius */ }

Accessibility

  • The host is aria-hidden="true", tabindex="-1", and pointer-events: none — it never traps focus or steals interaction.
  • Under @media (prefers-reduced-motion: reduce), fire() skips the particle simulation but still dispatches x-confetti-fire and an immediate x-confetti-end. Consumers can use these events to provide non-visual feedback (haptics, sound, status messages) when motion is suppressed.

Modes

  • mode="overlay" (default) — host becomes position: fixed; inset: 0 with z-index: var(--x-confetti-z-index, 9999). Drop a single instance anywhere in the DOM and call fire() for full-page celebrations.
  • mode="inline" — host becomes position: relative and the canvas fills its bounding box. Useful for celebrating within a specific surface (a card, a banner). The host needs an explicit size from CSS.

Mobile / responsive

  • The canvas is automatically resized via ResizeObserver and accounts for devicePixelRatio (capped at 2 for performance).
  • Default count is 80. The cap of 300 keeps RAF cost predictable on low-end devices. Tune via the count attribute or fire({count}).
  • No pointer interaction (the component does not listen for pointer events).

Styling

Override CSS custom properties on the host element:

x-confetti {
  --x-confetti-z-index: 1100;
}

Custom properties

PropertyDefaultPurpose
--x-confetti-z-index9999Stacking context for mode="overlay".

Confetti color comes from the colors attribute (or its default theme palette: --x-color-primary, --x-color-accent, --x-color-success, --x-color-warning, --x-color-info).

Examples

<!-- Drop-in overlay; fire from a button -->
<x-confetti id="party"></x-confetti>
<button onclick="document.getElementById('party').fire()">Celebrate</button>

<!-- Auto-fire on success page -->
<x-confetti auto-fire count="150" duration="6000"></x-confetti>

<!-- Inline burst inside a card -->
<x-spotlight-card style="position:relative">
  <x-confetti mode="inline" origin="bottom" velocity="22"></x-confetti>
  <h2>You did it!</h2>
</x-spotlight-card>

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close