The core animation engine. Importable as AnimatedIcon from svelte-animated-icon.
<script>
import { AnimatedIcon } from 'svelte-animated-icon';
</script>
<AnimatedIcon svg={mySvgString} template="spin" size={32} /> Props
| Prop | Type | Default | Required | Notes |
|---|---|---|---|---|
svg | string | - | yes | Pre-stripped inner SVG markup. No <svg> wrapper, no bounding <rect fill="none">. |
template | string | 'draw' | A template id - see Templates Catalog. | |
size | number | 24 | Rendered pixel size; sets <svg width> and <svg height>. | |
trigger | 'hover' \| 'mount' \| 'controlled' | 'hover' | See Triggers. | |
active | boolean | false | When trigger="controlled", animates while true. | |
loop | boolean | false | Force the template to repeat forever. | |
speed | number | 1 | Duration / delay multiplier (2 = twice as fast). | |
easing | string \| null | null | Override the template’s easing. null keeps the template’s own. | |
class | string | '' | Extra class on the wrapper. | |
color | string | - | Text/icon color (sets inline style="color: …"). |
Exported methods
Bind to the component instance to drive animation imperatively:
<script>
import { AnimatedIcon } from 'svelte-animated-icon';
let icon = $state();
export function replay() {
icon.stopAnimation();
icon.startAnimation();
}
</script>
<AnimatedIcon bind:this={icon} svg={mySvg} template="draw" trigger="controlled" />
<button onclick={replay}>Replay</button> startAnimation(): void
Cancels any in-flight animation, then runs the configured template against the current SVG. Reads the latest values of template, loop, speed, and easing from props.
stopAnimation(): void
Cancels all in-flight animations and calls clearProps() to strip the inline styles the template set (stroke-dasharray, stroke-dashoffset, opacity, transform, transform-box, transform-origin, fill, fill-opacity). The icon returns to its rest state.
Render output
The component renders (with any additional HTML attributes/styles/events forwarded):
<div class="animated-icon {className}" role="img" style="color: {color}; ...anyOtherStyles" onmouseenter=… onmouseleave=… ...anyOtherAttributes>
<svg bind:this={svgEl} width={size} height={size} viewBox="0 0 256 256"
style="overflow: visible; display: block;">
{@html svg}
</svg>
</div> - The wrapper has
role="img"by default. Override accessibility or add extra event handlers via standard props. See Accessibility. - The inner
<svg>has a fixedviewBox="0 0 256 256"- required for templates to do their geometry tricks. xmlns="http://www.w3.org/2000/svg"is set on the inner<svg>.
Reactivity model
The component uses two $effect blocks internally:
- Mount trigger - if
trigger === 'mount'andsvgis set, callsstartAnimation()once. - Controlled trigger - if
trigger === 'controlled', starts or stops based onactive. The effect’s cleanup callsstopAnimation(), so flippingtriggeraway from'controlled'(or changingactive/svg) cancels any in-flight animation. Looping animations are stopped cleanly this way.
Type import
The Props interface is exported from the component’s <script module> block, and re-exported as AnimatedIconProps from the package root:
import type { AnimatedIconProps } from 'svelte-animated-icon'; See Core Exports and Types for the rest of the public surface.