Actions

Morph

Animate an icon or text when its value changes.

Usage

Import morph from @mielui/svelte/actions/morph and attach it to a visual wrapper. Change key with the displayed value. Duration defaults to 220 milliseconds.

<script lang="ts">
    import { Moon02Icon as Moon, Sun03Icon as Sun } from '@hugeicons/core-free-icons';
    import { morph } from '@mielui/svelte/actions/morph';
    import { Button } from '@mielui/svelte/components/button';
    import HugeiconsIcon from '@mielui/svelte/hugeicons-icon';

    let night = $state(false);

    function toggleAppearance() {
        night = !night;
    }
</script>
<Button variant="outline" onclick={toggleAppearance} aria-label="Switch appearance preview">
    <span class="inline-flex size-5" aria-hidden="true" use:morph={{ key: night }}>
        <HugeiconsIcon icon={night ? Moon : Sun} size={20} />
    </span>
    <span class="inline-block w-12 text-left" use:morph={{ key: night }}>
        {night ? 'Night' : 'Day'}
    </span>
</Button>

SVG and text

Matching closed SVG shapes interpolate their geometry. Different icon structures use the same fixed-cell rotation, scale, and crossfade as Copy Button. Text changes use a short blur and crossfade.

Composition and accessibility

Use a span inside your existing button, not the button itself. Keep the button's accessible label outside the animation. The visual copy is hidden from assistive technology and cannot receive input. Give text a stable width if surrounding controls should not move.

Reduced-motion preferences skip the animation. The visual layer stays inside its wrapper during scrolling and resizing. Interrupted transitions continue from the current visual state, and unmount restores the original content.

Changing a count

Keep the animated number in a fixed-width wrapper. The surrounding label and button stay in place while the count changes.

API reference

morph attaches to an HTMLElement and cleans up when it unmounts. Pass an options object.

  • key Required
    unknown

    Change it when the displayed content changes.

  • duration
    number

    Transition length in milliseconds.

    Default 220