Harness-engineering svelte-transitions-animations

Svelte Transitions and Animations

install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/svelte-transitions-animations" ~/.claude/skills/intense-visions-harness-engineering-svelte-transitions-animations-ecfda3 && rm -rf "$T"
manifest: agents/skills/codex/svelte-transitions-animations/SKILL.md
source content

Svelte Transitions and Animations

Add enter/exit animations, list reordering motion, and spring physics to Svelte elements using built-in and custom transitions

When to Use

  • You need elements to animate in/out when they enter or leave the DOM based on conditional rendering
  • You want to animate list reordering when items move within an
    {#each}
    block
  • You need smooth value transitions (progress bars, counters) using tweened or spring stores
  • You are building custom animation functions for reusable transition effects

Instructions

Built-in transitions:

  1. Import and apply transitions from
    svelte/transition
    . They run when the element is conditionally rendered:
<script>
  import { fade, fly, slide, scale, blur } from 'svelte/transition'
  let show = $state(true)
</script>

<button onclick={() => show = !show}>Toggle</button>

{#if show}
  <div transition:fade>Fades in and out</div>
  <div transition:fly={{ y: 20, duration: 300 }}>Flies from below</div>
  <div transition:slide>Slides open/closed</div>
{/if}
  1. Use
    in:
    and
    out:
    directives to apply different transitions for enter and exit:
{#if show}
  <div in:fly={{ x: -100 }} out:fade>
    Flies in from left, fades out
  </div>
{/if}
  1. Pass parameters to customize built-in transitions:
<div transition:fly={{ x: 0, y: 50, duration: 400, easing: quintOut }}>
  Parameterized fly
</div>

Import easing functions from

svelte/easing
:
linear
,
cubicIn
,
cubicOut
,
cubicInOut
,
quintOut
,
elasticOut
,
backOut
, etc.

Custom transitions:

  1. Write a custom transition function that returns CSS keyframes or a tick function:
// CSS-based custom transition (most performant)
function swoosh(node: Element, { duration = 300 } = {}) {
  return {
    duration,
    css: (t: number) => `
      transform: translateX(${(1 - t) * 100}%) rotate(${(1 - t) * 45}deg);
      opacity: ${t};
    `,
  };
}
// JS-based tick function (for canvas or non-CSS animations)
function typewriter(node: Element, { speed = 40 } = {}) {
  const text = node.textContent ?? '';
  return {
    duration: text.length * speed,
    tick: (t: number) => {
      node.textContent = text.slice(0, Math.floor(t * text.length));
    },
  };
}

Animating list items with animate:flip:

  1. Use
    animate:flip
    to smoothly reorder elements in
    {#each}
    blocks when items move:
<script>
  import { flip } from 'svelte/animate'
  import { fade } from 'svelte/transition'

  let items = $state(['A', 'B', 'C', 'D'])

  function shuffle() {
    items = [...items].sort(() => Math.random() - 0.5)
  }
</script>

<button onclick={shuffle}>Shuffle</button>

{#each items as item (item)}
  <div animate:flip={{ duration: 300 }} transition:fade>
    {item}
  </div>
{/each}

Note:

(item)
— the key expression — is required for
animate:flip
to track element identity.

Tweened and spring stores for smooth value transitions:

  1. Use
    tweened
    for smooth numeric value interpolation (progress bars, counters):
<script>
  import { tweened } from 'svelte/motion'
  import { cubicOut } from 'svelte/easing'

  const progress = tweened(0, { duration: 500, easing: cubicOut })

  function complete() { progress.set(1) }
</script>

<progress value={$progress} />
<button onclick={complete}>Complete</button>
  1. Use
    spring
    for physics-based motion that overshoots and settles:
<script>
  import { spring } from 'svelte/motion'

  const pos = spring({ x: 0, y: 0 }, { stiffness: 0.1, damping: 0.25 })
</script>

<div
  style="transform: translate({$pos.x}px, {$pos.y}px)"
  onmousemove={(e) => pos.set({ x: e.clientX, y: e.clientY })}
/>

Deferred transitions (crossfade):

  1. Use
    crossfade
    to animate an element from one position to another across the DOM (shared element transition):
<script>
  import { crossfade } from 'svelte/transition'
  const [send, receive] = crossfade({ duration: 400 })
</script>

{#if inList}
  <div in:receive={{ key: item.id }} out:send={{ key: item.id }}>
    {item.name}
  </div>
{:else}
  <div in:receive={{ key: item.id }} out:send={{ key: item.id }}>
    {item.name}
  </div>
{/if}

Details

How transitions work:

Svelte compiles

transition:
,
in:
, and
out:
directives into JavaScript that runs when the element is added to or removed from the DOM. CSS-based transitions run entirely on the compositor thread and do not block the main thread.

global
modifier:

By default, transitions only run when the direct parent

{#if}
changes. Add
:global
to run the transition when any ancestor condition changes:

{#if outerCondition}
  {#if innerCondition}
    <div transition:fade|global>
      Fades when either condition changes
    </div>
  {/if}
{/if}

Transition events:

Listen to transition lifecycle events:

<div
  transition:fly
  onintrostart={() => console.log('entering')}
  onintroend={() => console.log('entered')}
  onoutrostart={() => console.log('leaving')}
  onoutroend={() => console.log('left')}
/>

Performance considerations:

  • Prefer CSS-based custom transitions (return
    css
    ) over JS tick functions — CSS runs off the main thread
  • Avoid animating
    width
    /
    height
    — use
    transform: scaleX()
    and
    transform: scaleY()
    instead
  • slide
    animates height and may cause layout thrash on complex elements; prefer
    scale
    or custom transitions for performance-sensitive cases

Source

https://svelte.dev/docs/svelte/transition

Process

  1. Read the instructions and examples in this document.
  2. Apply the patterns to your implementation, adapting to your specific context.
  3. Verify your implementation against the details and edge cases listed above.

Harness Integration

  • Type: knowledge — this skill is a reference document, not a procedural workflow.
  • No tools or state — consumed as context by other skills and agents.

Success Criteria

  • The patterns described in this document are applied correctly in the implementation.
  • Edge cases and anti-patterns listed in this document are avoided.