# Animated Icon

> Source: https://design.nanatec.co.ke/components/animated-icon/
> A motion wrapper around Icon. It renders a real `<nana-icon>` — inheriting the entire built-in glyph set, the shared icon registry and the accessibility wiring — and layers a CSS-driven animation on top, started by a trigger.

A motion wrapper around Icon. It renders a real `<nana-icon>` — inheriting the entire built-in glyph set, the shared icon registry and the accessibility wiring — and layers a CSS-driven animation on top, started by a trigger.

Because it composes the existing Icon component, any name you can render with `<nana-icon>` — including glyphs you register yourself — works here too. It also honours `prefers-reduced-motion`: looping motion is suspended, and deliberate hover/click/manual motion is slowed.

## Preview

```html
<nana-animated-icon name="settings" animation="spin" trigger="loop"></nana-animated-icon>
```

## Installation

```bash
npm install @nana-tec/ui-components
```

## Import

```js
import "@nana-tec/ui-components/animated-icon";
```

## Basic usage

```html
<nana-animated-icon name="settings" animation="spin" trigger="loop"></nana-animated-icon>
<nana-animated-icon name="favorite" animation="beat"></nana-animated-icon>
<nana-animated-icon name="notifications" animation="shake" trigger="click"></nana-animated-icon>
```

## Animations

Ten built-in presets. Looping here so the gallery is self-demonstrating.

```html
<nana-animated-icon name="settings" animation="spin" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="refresh" animation="spin-reverse" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="favorite" animation="pulse" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="favorite" animation="beat" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="notifications" animation="bounce" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="notifications" animation="shake" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="edit" animation="flip" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="delete" animation="wobble" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="rocket" animation="float" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="check" animation="tada" trigger="loop" size="lg"></nana-animated-icon>
```

## Triggers

Control when the animation runs.

```html
<nana-animated-icon name="settings" animation="spin" trigger="loop" size="lg"></nana-animated-icon>
<nana-animated-icon name="favorite" animation="beat" trigger="hover" size="lg"></nana-animated-icon>
<nana-animated-icon name="notifications" animation="tada" trigger="click" size="lg"></nana-animated-icon>
```

```html
<nana-animated-icon name="settings" animation="spin" trigger="loop"></nana-animated-icon>
<nana-animated-icon name="favorite" animation="beat" trigger="hover"></nana-animated-icon>
<nana-animated-icon name="notifications" animation="tada" trigger="click"></nana-animated-icon>
<nana-animated-icon id="loader" name="refresh" animation="spin" trigger="manual"></nana-animated-icon>
```

## Programmatic control

With `trigger="manual"` you drive motion from JavaScript using `play()`, `pause()` and `toggle()`, and react to the `nana-animation-start` / `nana-animation-end` events.

```ts
const el = document.getElementById("loader");
el.play();    // start (restarts cleanly if already running)
el.pause();   // stop and reset to the resting frame
el.toggle();  // play if paused, pause if playing

el.addEventListener("nana-animation-start", () => console.log("started"));
el.addEventListener("nana-animation-end", () => console.log("one cycle done"));
```

## Customization

Six ways to make it yours — from a quick colour swap to a fully bespoke animation.

### 1. Colour & size

Colour follows `currentColor`, so set `color`. Size via the `size` preset or any `font-size`.

```html
<nana-animated-icon name="favorite" animation="beat" style="color: var(--nana-color-danger-600);" size="lg"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin" size="xl"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin" style="font-size: 3rem;"></nana-animated-icon>
```

```html
<nana-animated-icon name="favorite" animation="beat"
  style="color: var(--nana-color-danger-600);"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin" size="xl"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin"
  style="font-size: 3rem;"></nana-animated-icon>
```

### 2. Speed & duration

Pick a preset with `speed`, or set an exact duration with `--nana-animated-icon-duration`.

```html
<nana-animated-icon name="settings" animation="spin" speed="slow" size="lg"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin" speed="normal" size="lg"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin" speed="fast" size="lg"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin" style="--nana-animated-icon-duration: 4s;" size="lg"></nana-animated-icon>
```

```html
<nana-animated-icon name="settings" animation="spin" speed="fast"></nana-animated-icon>
<nana-animated-icon name="settings" animation="spin"
  style="--nana-animated-icon-duration: 4s;"></nana-animated-icon>
```

### 3. Your own glyphs

It shares the Icon registry — register a glyph once and animate it like any built-in.

```ts
import { registerIcons } from "@nana-tec/ui-components";

// Same registry the built-in icons use — register once, animate anywhere.
registerIcons({
  rocket: { viewBox: "0 0 24 24", paths: ["M12 2C8 6 8 10 8 14l4 4 4-4c0-4 0-8-4-12z"] },
});
```

```html
<nana-animated-icon name="rocket" animation="float"></nana-animated-icon>
```

### 4. Inline SVG

No registration needed for a one-off — drop SVG into the default slot.

```html
<nana-animated-icon animation="spin" trigger="loop">
  <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
    <path d="M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z"/>
  </svg>
</nana-animated-icon>
```

### 5. Bespoke motion

Need a motion that isn't built in? Define your own `@keyframes` and apply them to the exposed `::part(icon)`.

```html
<nana-animated-icon class="bell" name="notifications"></nana-animated-icon>
```

```css
@keyframes swing {
  20% { transform: rotate(15deg); }
  40% { transform: rotate(-10deg); }
  60% { transform: rotate(5deg); }
  80% { transform: rotate(-5deg); }
  100% { transform: rotate(0deg); }
}
.bell::part(icon) {
  animation: swing 1s ease-in-out infinite;
  transform-origin: top center;
}
```

### 6. Drop into other components

It's just an inline element that inherits colour — slot it into buttons, menus, alerts, anywhere.

```html
<nana-button variant="primary">
  <nana-animated-icon name="refresh" animation="spin" trigger="hover" slot="prefix"></nana-animated-icon>
  Sync
</nana-button>
```

## Accessibility

Pass `label` for a meaningful icon — it forwards to the inner icon's `aria-label`. Leave it empty for decorative icons, which are marked `aria-hidden`.

`prefers-reduced-motion` is honoured automatically: loop motion is suspended, and deliberate hover/click/manual motion is slowed to a calm 2s.

## API

## Methods

| Method | Description |
|---|---|
| `play()` | Start the animation; restarts cleanly if already running. |
| `pause()` | Stop and reset to the resting frame. |
| `toggle()` | Play if paused, pause if playing. |

## Events

| Event | Description |
|---|---|
| `nana-animation-start` | Fired when a play cycle begins. |
| `nana-animation-end` | Fired when a one-shot (click/manual) cycle ends. |

## CSS custom properties & parts

| Name | Kind | Description |
|---|---|---|
| `--nana-animated-icon-duration` | custom property | Override the animation duration |
| `icon` | `::part` | The composed `<nana-icon>` — target it to apply a fully custom animation |
| `(default)` | slot | Custom SVG content, used when `name` is not set |

## Related components

<ul class="related not-content">
  <li><a href="/components/icon/">Icon</a></li>
  <li><a href="/components/button/">Button</a></li>
  <li><a href="/components/alert/">Alert</a></li>
</ul>

## Storybook

See every state and prop interactively in Storybook: https://storybook.nanatec.co.ke/?path=/docs/components-animated-icon--docs
