Sticker
Square illustrated stickers in two flavors per name — a lightweight
static SVG and a Lottie-driven animated version. Stickers ship in their
own package, @antadesign/stickers (a companion to @antadesign/anta,
kept separate so apps that don’t use stickers never install
lottie-web). Each one is its own named export, so the consumer’s
bundler ships only the stickers actually used. The static variant is
the default; reach for the animated one explicitly when you want
motion.
npm install @antadesign/stickers # pulls @antadesign/anta + lottie-webBoth flavors are JSX wrappers over two custom elements,
<a-sticker>and<a-sticker-animated>, registered by@antadesign/stickers/elements. Plain HTML/JS consumers can drive the elements directly viasetAttributeinstead of using the JSX wrappers — see Non-React consumers below.
The full set is also published as a Telegram sticker pack.
Props
Both flavors share the same base props; the animated flavor adds paused.
Sticker{Name} (static)
| Prop | Type | Description |
|---|---|---|
size? | number | Edge length in pixels. Stickers are always square. Defaults to 256. |
label? | string | Accessible name. When set, the sticker is exposed as role="img" + aria-label. Omitted ⇒ aria-hidden="true" (decorative). |
Inherited props (className, style).
Sticker{Name}Animated (Lottie)
Same as the static base, plus:
| Prop | Type | Description |
|---|---|---|
paused? | boolean | number | true freezes at the current frame; a number freezes at that time in seconds. Omit (or pass false) to play. |
Sizing
Pass size (a number, in pixels) to control width and height together.
Default is 256. Stickers are always square.
<StickerVacation /> // 256×256<StickerVacation size={128} /> // 128×128<StickerVacationAnimated size={64} /> // 64×64Internally, size is applied as the --sticker-size CSS custom
property on the rendered <a-sticker> / <a-sticker-animated>. The
base CSS rule reads it as
width: var(--sticker-size, 256px); height: var(--sticker-size, 256px).
That means consumer CSS (or a parent’s variable cascade) can drive
sticker size too:
.sticker-grid { --sticker-size: 96px; }Animation control
paused only applies to Sticker{Name}Animated. It maps to the
element’s observed paused attribute:
<StickerCodingAnimated /> // autoplay, looping<StickerCodingAnimated paused /> // freeze at the current frame<StickerCodingAnimated paused={1.5} /> // freeze at 1.5 seconds<StickerCodingAnimated paused={false} /> // explicitly play (same as omitted)Adding your own stickers
@antadesign/stickers ships a generator script at
@antadesign/stickers/generate-stickers.mjs. Drop your sources in a
folder structured the same way as the built-in set — one subfolder per
sticker, with a <name>.json (Lottie) and/or <name>.svg (static
pose):
my-stickers/ happy/ happy.json happy.svg sad/ sad.jsonThen point the generator at it:
node ./node_modules/@antadesign/stickers/dist/generate-stickers.mjs \ --input ./my-stickers \ --output ./src/my-generated-stickersThe emitted modules import their Sticker / StickerAnimated runtime
wrappers from @antadesign/stickers by default; pass --package <name>
to point them at a different specifier (e.g. your own re-export).
Out comes one <name>.ts per static sticker and one <name>-animated.ts
per animated sticker, plus an index.ts barrel. Import and use:
import { StickerHappy, StickerSadAnimated } from './my-generated-stickers'
<StickerHappy size={96} /><StickerSadAnimated paused={1.5} />Source conventions
- Animated stickers are
<name>.jsonLottie payloads. - Either file is optional — supply just the SVG for a static-only sticker, just the JSON for an animated-only one, or both.
Conflicting names
If a generated sticker has the same name as one of the pack’s built-ins
(e.g. vacation), the generator prints a warning. The built-in sticker
imported from @antadesign/stickers is unaffected — your generated
barrel exposes yours under your own import path.
Non-React consumers
The custom elements <a-sticker> and <a-sticker-animated> are
framework-agnostic. Each generated module exports the raw payload
(svg string for static, animationJson string for animated)
alongside the JSX component, so non-React consumers can pull just the
data and drive the elements directly:
import { svg } from '@antadesign/stickers/vacation'import { animationJson } from '@antadesign/stickers/vacation-animated'
const still = document.createElement('a-sticker')still.setAttribute('svg', svg)still.style.setProperty('--sticker-size', '128px')document.body.appendChild(still)
const movie = document.createElement('a-sticker-animated')movie.setAttribute('animation', animationJson)document.body.appendChild(movie)The static element renders the SVG into its own shadow DOM; the
animated element drives a shadow-DOM <svg> via lottie-web. Both
consume their payload through the svg / animation HTML attribute —
the JSX wrapper passes the same data, just through React/Preact’s
prop layer.
SSR
@antadesign/stickers/elements references browser APIs (HTMLElement,
customElements, lottie-web). In SSR contexts (Astro, Next.js) gate
the import behind a client boundary — same rule as anta’s own elements.
The sticker components themselves render fine on the server (just JSX);
only the underlying custom-element classes need the browser.