Animated Icons
A motion-driven action icon set. Six glyphs — copy, share, bookmark, arrow, sparkles, undo — whose hover animation encodes the meaning of the action. Every transition is a two-state spring, so the motion is fully interruptible.
copy
share
bookmark
arrow
sparkles
undo
Customize
Icon set
20px
accent (token)
Installation
npx shadcn@latest add https://craftbits.dev/r/animated-icons.jsonUsage
import { AnimatedIcon } from "@craft-bits/core";
<AnimatedIcon name="copy" />Understanding the component
- Two-state springs, not keyframes. Every glyph animates between exactly two states — rest and hover. The spring interpolates from its current position whenever the state flips, so hovering off mid-flight reverses the motion smoothly instead of snapping back to zero.
- Spring tokens. Stroke draws and small scales use
SPRINGS.snap. The overshoot motions (bookmark drop, undo rotation, share node pulse) use a tuned bouncy spring for that "tactile" landing. - Reduced-motion fallback. When the OS-level
prefers-reduced-motionis on — orpausedis explicitly set — the icon renders its rest-state body with no transitions. The glyph stays legible and identifiable; only the motion disappears. ANIMATED_ICONSmap. The full motion-aware glyph map is exported so consumers can iterate the set or compose custom layouts without re-listing names.
Variants / Examples
// Iterate the full set.
import { AnimatedIcon, ANIMATED_ICON_NAMES } from "@craft-bits/core";
{ANIMATED_ICON_NAMES.map((name) => (
<AnimatedIcon key={name} name={name} />
))}
// Override the accent color used on hover / focus.
<AnimatedIcon name="sparkles" accentColor="#a855f7" />
// Force the static fallback (e.g. inside a print stylesheet).
<AnimatedIcon name="undo" paused />Props
| Prop | Type | Default | Description |
|---|---|---|---|
name | 'copy' | 'share' | 'bookmark' | 'arrow' | 'sparkles' | 'undo' | required | Which glyph to render. |
size | number | 20 | Pixel diameter of the inner SVG glyph. |
accentColor | string | var(--cb-color-accent) | Border tint applied on hover / focus. |
paused | boolean | false | When true, skip animations and render the rest-state glyph. |
className | string | — | Extra classes merged onto the outer tile span. |
Accessibility
- The tile and inner SVG are marked
aria-hidden="true"by default — these are decorative micro-interactions. If the icon stands alone as a button, wrap it in a button with anaria-label. - Hover and focus both trigger the animation, so keyboard users get the same affordance as pointer users.
usePrefersReducedMotionshort-circuits every animation when the OS-level setting is on; the icon falls back to a static glyph automatically.
Credits
- Extracted from:
terminal-dreams(src/components/principles/AnimatedIcons.tsx).