GradientDeck
AI ComponentsNewJournalFigma

Free tools and components
for everyday web development.

Explore the tools
AI ComponentsJournalGradientDeck UIGradientDeck SkillAboutFigma pluginContactAdvertise
GRADIENTDECKGRADIENTDECKGRADIENTDECKDECK

© 2026 GradientDeck

PrivacyReport a bug
Back to top

    Animated SVG icons.

    Search 150+ icons built with Motion and Lucide. Hover or tap an icon to preview its animation, then copy the React component or download the .tsx file.

    React · TSX
    THE TOOLBOX14

    Surfaces

    Background gradients
    Text gradients
    Mesh gradients
    Patterns
    Liquid glass
    Box shadows
    Blobs

    Motion

    Animations
    Animated icons

    Color

    Color palettes
    Image color picker
    Palette visualizer
    Tailwind colors

    Connect

    Figma plugin
    Explore the toolbox
    154 iconsBuilt with Motion & Lucide
    1
    Calendar1
    Paperclip
    ToggleLeft
    Clapperboard
    BatteryFull
    Grape
    AArrowDown
    Activity
    ALargeSmall
    AArrowUp
    AirVent
    Airplay
    AlarmClock
    AlarmClockCheck
    Clock8
    AlarmSmoke
    Album
    AlignCenter
    AlignCenterHorizontal
    AlignCenterVertical
    Anchor
    Annoyed
    Aperture
    Angry
    AtSign
    AudioWaveform
    AudioLines
    BadgeAlert
    BadgeDollarSign
    BadgeCheck
    Atom
    BellRing
    Bike
    Blocks
    Bomb
    Blend
    Bold
    Bug
    BringToFront
    Cable
    ChartColumn
    ChartPie
    ChartColumnBig
    ChartGantt
    ChartLine
    ChartNoAxes
    Check
    ChevronsLeft
    ChevronsRight
    ChevronLeft
    ChevronRight
    ChevronUp
    ChevronDown
    ChevronsDown
    ChevronsUp
    CheckCheck
    ChevronsUpDown
    Chrome
    Braces
    Brackets
    Box
    ChevronFirst
    ChevronLast
    CircleDashed
    CircleDotDashed
    CircleFadingArrowUp
    CircleHelp
    CircleChevronDown
    CircleChevronLeft
    CircleChevronRight
    CircleChevronUp
    Rocket
    ClipboardCopy
    Crop
    Earth
    Download
    CloudDrizzle
    CloudDownload
    Code
    Codesandbox
    Dice6
    Disc3
    Flame
    User
    Expand
    Delete
    Copy
    ScanText
    Fan
    FileChartColumn
    FileChartPie
    FlameKindling
    Grip
    HardDriveDownload
    IterationCcw
    IterationCw
    LoaderPinwheel
    Bolt
    Group
    HeartHandshake
    LayoutGrid
    Link2
    Maximize2
    Nfc
    Users
    BluetoothSearching
    Cpu
    Plane
    Origami
    Network
    PartyPopper
    Podcast
    ScanHeart
    Slack
    SlidersVertical
    Martini
    Magnet
    Trees
    Wifi
    Wine
    Waves
    ThumbsUp
    ThumbsDown
    Squirrel
    TestTubes
    WandSparkles
    SprayCan
    SmartphoneNfc
    FileStack
    Archive
    Undo
    AppWindowMac
    Antenna
    Cast
    Salad
    Music
    Ungroup
    Sparkles
    Shell
    Globe
    Compass
    Percent
    Linkedin
    Cake
    ThermometerSnowflake
    Wind
    Folders
    PackageOpen
    Boxes
    BookMarked
    Wand
    Heater
    SwatchBook
    Layers

    How to use the animated icons in React

    The library has 155 icons drawn from Lucide's SVG paths and animated with Motion. Each one is a single, self-contained React component in a .tsx file: it renders an inline SVG and plays its animation while the pointer is over it. Hover or tap an icon in the grid to preview it, then copy the component source, download that icon's .tsx file, or use Download all to get every icon as animated-icons.zip, with one .tsx file per icon in an icons folder.

    Adding an icon to a project

    The only dependency is the motion package; you do not need Lucide installed, because the SVG paths are written into each file. Save the file in your components folder under the icon's name and import it by name, since every file uses a named export. The files start with "use client", so in the Next.js App Router you can import them from a server component and they will render as client components.

    The files are TypeScript. In a JavaScript project, rename the file to .jsx and delete the props interface, the import type line, and the type annotations; the rest is plain JSX.

    tsx
    // npm install motion
    import { Rocket } from "@/components/icons/Rocket";
    
    export function LaunchButton() {
      return (
        <button type="button" className="launch-button">
          <Rocket width={20} height={20} stroke="currentColor" aria-hidden="true" />
          Launch
        </button>
      );
    }

    Props and the wrapper element

    Every icon accepts width and height (both 28 by default), stroke (#ffffff by default), and strokeWidth (2 by default). The white default suits dark interfaces like this site, but on a light background the icon is invisible until you pass a color. Passing stroke="currentColor" makes the icon follow the text color of its parent, which also makes hover and dark-mode color changes work without extra props.

    Any other SVG attribute you pass, such as className, style, or aria-hidden, goes onto the <svg> element. The SVG sits inside a <div> wrapper with 8px of padding, a pointer cursor, user-select: none, and flex centering, and the hover handlers are attached to that wrapper. Two consequences: the hover area is the whole padded box, not just the strokes, and the icon takes up 16px more than its width and height in each direction. In a tight button or toolbar, edit the style object in the file or remove the padding.

    How the animation is triggered

    Each file defines Motion variants named normal and animate and drives them with useAnimation. Moving the pointer onto the wrapper starts animate; moving it off returns to normal. Some icons play once per hover and others loop while the pointer stays: 36 of the 155 files use repeat: Infinity. Activity, for example, redraws its pulse line with a 1.5 second draw followed by a 0.5 second pause. To change speed or easing, edit the transition inside the variants object at the top of the file.

    Touch screens have no hover. Mobile browsers send compatibility mouse events after a tap, so an icon usually starts animating when tapped and stops when something else is tapped. The wrapper is not focusable, so keyboard users never trigger the animation. If the motion should respond to a whole button rather than the icon, move the trigger out of the icon: add a prop and start the controls from an effect, then set that prop from the button's hover and focus handlers.

    tsx
    // Inside the icon file: let the parent decide when to animate
    import { useEffect } from "react";
    
    const Rocket = ({ active = false, ...props }: RocketProps & { active?: boolean }) => {
      const controls = useAnimation();
    
      useEffect(() => {
        controls.start(active ? "animate" : "normal");
      }, [active, controls]);
    
      // ...remove onMouseEnter and onMouseLeave from the wrapper div
    };
    
    // In the parent
    const [active, setActive] = useState(false);
    
    <button
      onMouseEnter={() => setActive(true)}
      onMouseLeave={() => setActive(false)}
      onFocus={() => setActive(true)}
      onBlur={() => setActive(false)}
    >
      <Rocket active={active} stroke="currentColor" aria-hidden="true" />
      Launch
    </button>

    Accessibility: labels and reduced motion

    The SVG has no title or role. Next to a visible text label, pass aria-hidden="true" so screen readers skip it. In an icon-only button, put the accessible name on the button with aria-label="Download", not on the SVG.

    The icons do not check prefers-reduced-motion themselves. Wrapping your app in <MotionConfig reducedMotion="user"> handles part of it: Motion then turns off transform animations (x, y, scale, rotate) for people who ask for reduced motion, but it keeps other values animating. That leaves path-drawing icons such as Activity, which animate pathLength and opacity, still moving. To stop every icon, read useReducedMotion in the file and skip the start call.

    tsx
    import { motion, useAnimation, useReducedMotion } from "motion/react";
    
    // inside the component
    const controls = useAnimation();
    const reduceMotion = useReducedMotion();
    
    <div
      onMouseEnter={() => {
        if (!reduceMotion) controls.start("animate");
      }}
      onMouseLeave={() => controls.start("normal")}
    >

    Bundle size and performance

    Every icon imports from the same package, motion/react (almost always just motion and useAnimation), so Motion is added to your bundle once no matter how many icons you use; each additional icon only adds its own paths and variants. If your project already depends on framer-motion, change the import to "framer-motion", which exports the same names, instead of installing a second copy of the library. Nothing animates until a hover starts, so a page full of idle icons does no animation work. If you only need a few static icons, plain Lucide is lighter; use these where the motion adds feedback, such as a copy button that confirms or a download icon that moves on hover.

    Questions

    Do I need to install Lucide?
    No. Each file contains its own SVG paths. The only dependency is the motion package (npm install motion).
    Why can't I see the icon?
    The default stroke is white (#ffffff). On a light background, pass stroke="currentColor" to follow the surrounding text color, or a specific color such as stroke="#1d293d".
    Can I use these icons without React?
    Not as they are. The animation is written with Motion's React components. You can copy the path data into plain SVG markup for a static icon, and for CSS-only motion use the CSS animation generator instead.
    How do I make an icon animate when its button is hovered or focused?
    Add an active prop to the icon that starts the animate or normal variant from a useEffect, remove the wrapper's mouse handlers, and set active from the button's onMouseEnter, onMouseLeave, onFocus, and onBlur handlers, as in the example above.
    AI Components for React and Tailwind ↗CSS animation generator ↗Tailwind colors for stroke values ↗Journal: animated SVG icons with Motion ↗

    Updated October 14, 2026