SparkleWrapper

PreviousNext

Animates its children with a bounce-enter while Diamond sparkle icons burst outward, fading and scaling to nothing. Use it to celebrate any element on mount.

'use client';

import { useState } from 'react';
import { SparkleWrapper } from '@/ui/SparkleWrapper';
import { Icon } from '@clubmed/trident-icons';

export function SparkleWrapperDemo() {
  const [key, setKey] = useState(0);

  return (
    <div className="flex flex-col items-center gap-48 p-48">
      <SparkleWrapper className="text-green" count={3} key={key}>
        <Icon name="CheckFilled" className="!text-green" width="75px" />
      </SparkleWrapper>

      {/* <SparkleWrapper key={`b-${key}`}>
        <span className="text-h4 font-bold">🎉 Congratulations!</span>
      </SparkleWrapper> */}

      <button
        type="button"
        onClick={() => setKey((k) => k + 1)}
        className="px-20 py-10 rounded-pill border-2 border-black font-semibold text-b3 hover:bg-black hover:text-white transition-colors cursor-pointer"
      >
        Replay animation
      </button>
    </div>
  );
}

Installation

npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/sparkle-wrapper.json

Usage

import { SparkleWrapper } from '@/ui/SparkleWrapper';
 
export function Component() {
  return (
    <SparkleWrapper>
      <div className="bg-saffron px-20 py-12 rounded-pill font-bold">New feature</div>
    </SparkleWrapper>
  );
}

How it works

When the component mounts, two things happen simultaneously:

  1. Children animate in with bounce-enter — scaling up from 50%, overshooting slightly, then settling at natural size.
  2. 8 Diamond sparkles burst outward from the center in all directions (every 45°), each scaling down from 100% to 0 while fading out. Delays are staggered between 0–100ms and sizes vary (10–16px) for a natural, organic burst.

Both animations run once and do not repeat.

Delaying the sparkles

Pass delay (in milliseconds) to hold the sparkle burst back while the children still bounce in immediately. Sparkles are not rendered at all until the delay elapses, so nothing is visible beforehand. A good starting point is to let the bounce settle first:

<SparkleWrapper delay={400}>
  <Icon name="CheckFilled" width="75px" />
</SparkleWrapper>

API Reference

SparkleWrapper

PropTypeDefaultDescription
childrenReactNode—The content to animate on mount
countnumber7Minimum number of sparkles (renders count to count + 3)
delaynumber0Milliseconds to wait before the sparkles start flying; children animate immediately
classNamestringundefinedAdditional classes applied to the root div
...propsHTMLAttributes<HTMLDivElement>—All standard div attributes are forwarded

Notes

  • The root element is inline-flex so it shrinks to fit its content. Wrap it in a block container if you need full-width layout.
  • Animations fire once on mount. To replay them, unmount and remount the component (use a key prop). Changing delay after the sparkles have started does not replay them.
  • Sparkle icons are aria-hidden="true" — they are purely decorative and invisible to assistive technology.
  • The bounce-enter duration is 500ms; sparkles complete in 600ms. Nothing lingers after 700ms (including the longest 100ms delay).