No.232 · Cursors· New
Confetti Click
The ordinary arrow, untouched — every click pops a handful of paper confetti: strips, squares, curls and dots thrown up from the click, tumbling over and fluttering sideways as they fall away. Hold a moment before letting go for a bigger pop.
The prompt
Written for the variant you picked above: Party
Build a wrapper that turns clicks into little confetti bursts while leaving the normal cursor alone. Props: children, mix (one of two palettes), global (listen on the whole window with a fixed full-screen canvas), motion, className and style. The layer (a small module): a canvas over the host with pointer-events none, sized by a ResizeObserver at DPR ≤ 2, in host-local coordinates corrected for a scaled host. pointerdown on the main button starts a hold; past 120ms a ring arc grows round the press point and fills over 650ms; pointerup releases a burst with a power from 1 to 2.2. A click with detail 0 (keyboard activation) bursts from the middle of that element. The loop runs only while something moves. Particles (pure functions): seeded randomness, a spray of velocities spread evenly across an arc with jitter, and one step with exponential drag, gravity and an optional sideways sway. The burst: 22 × power pieces thrown upwards across an arc of about 140–180° at 260–520px/s × √power, each a strip, a square, a curl (an open arc stroke) or a dot, 5–9px, in the palette. Steady gravity (620px/s²) with strong drag (2.6/s) makes them hang and drift down like paper, with a sideways flutter of 26px/s. Each spins, and tumbles — scaled on one axis by the cosine of a fast phase, with a darker face when it's turned away. They live 1.3–2.2s and fade over the last quarter. Reduced motion replaces the pop with one soft ring that fades in 600ms. Selected variant — Party (party): Bright party confetti (#ff3d6e, #ffb000, #2bc48a, #2f7bff, #a35bff, #ff7a2f) on a warm cream #fff8ee page. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: Click anywhere for a pop of confetti; hold before releasing for a bigger one. Keyboard activation of a button or link pops from its centre. Motion: Pieces fly up and flutter down over 1.3–2.2s; the charge ring fills over 650ms. Reduced motion shows a single fading ring. Accessibility: The native cursor and every control are untouched; the canvas is aria-hidden and ignores the pointer. Keyboard clicks get the effect too. Responsive behavior: The canvas follows the host's size; with global it covers the window. Touch: Taps pop too; a long press charges a bigger one. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.
Notes
- Interaction
- Click anywhere for a pop of confetti; hold before releasing for a bigger one. Keyboard activation of a button or link pops from its centre.
- Motion
- Pieces fly up and flutter down over 1.3–2.2s; the charge ring fills over 650ms. Reduced motion shows a single fading ring.
- Accessibility
- The native cursor and every control are untouched; the canvas is aria-hidden and ignores the pointer. Keyboard clicks get the effect too.
- Responsive
- The canvas follows the host's size; with global it covers the window.
- On touch
- Taps pop too; a long press charges a bigger one.