Skip to main content

Overview

Svelte 5 Animations components follow a consistent structure that makes them easy to understand, maintain, and customize. Each component is organized in a modular way with clear separation of concerns.

Directory Organization

All animation components are located in src/lib/components/magic-ui/ with each component in its own directory:
src/lib/components/magic-ui/
├── shine-border/
│   ├── shine-border.svelte
│   └── index.ts
├── animated-beam/
│   ├── animated-beam.svelte
│   ├── types.ts
│   ├── index.ts
│   ├── use-gradient-coordinates.svelte.ts
│   ├── use-path-calculator.svelte.ts
│   └── use-resize-observer.svelte.ts
├── marquee/
│   ├── marquee.svelte
│   └── index.ts
└── border-beam/
    ├── border-beam.svelte
    └── index.ts

Component File Structure

Simple Components

Most components have a minimal structure with two files:
<script lang="ts">
  import { cn } from "$lib/utils";
  import type { HTMLAttributes } from "svelte/elements";

  interface Props extends HTMLAttributes<HTMLDivElement> {
    borderWidth?: number;
    duration?: number;
    shineColor?: string | string[];
  }

  let {
    borderWidth = 1,
    duration = 14,
    shineColor = "#000000",
    class: className,
    style,
    ...restProps
  }: Props = $props();

  let computedStyle = $derived.by(() => {
    // Computed styles logic
  });
</script>

<div
  style={computedStyle}
  class={cn("motion-safe:animate-shine", className)}
  {...restProps}
/>

Complex Components

More complex components include additional files for types and utilities:
<script lang="ts">
  import { motion } from "motion-sv";
  import { cn } from "$lib/utils";
  import type { AnimatedBeamProps } from "./types";
  import { usePathCalculator } from "./use-path-calculator.svelte";
  import { useGradientCoordinates } from "./use-gradient-coordinates.svelte";
  import { useResizeObserver } from "./use-resize-observer.svelte";

  let {
    containerRef,
    fromRef,
    toRef,
    curvature = 0,
    duration = Math.random() * 3 + 4,
    // ... more props
  }: AnimatedBeamProps = $props();
</script>

<svg><!-- SVG rendering --></svg>

Props Pattern

TypeScript Interface

Components define their props using TypeScript interfaces that often extend standard HTML attributes:
interface Props extends HTMLAttributes<HTMLDivElement> {
  borderWidth?: number;
  duration?: number;
  shineColor?: string | string[];
}

Svelte 5 Props

The new Svelte 5 $props() rune is used with destructuring and default values:
let {
  borderWidth = 1,
  duration = 14,
  shineColor = "#000000",
  class: className,
  style,
  ...restProps
}: Props = $props();

Common Props

Most animation components share these common props:
  • class - Custom CSS classes (renamed to className internally)
  • duration - Animation duration in seconds
  • delay - Animation delay in seconds
  • style - Custom inline styles
  • ...restProps - All other HTML attributes

Derived State with Runes

Components use Svelte 5’s $derived and $derived.by runes for reactive computed values:
let computedStyle = $derived.by(() => {
  const baseStyles = `
    --border-width: ${borderWidth}px;
    --duration: ${duration}s;
  `;
  return style ? `${baseStyles} ${style}` : baseStyles;
});

Utility Integration

All components use the cn() utility function from $lib/utils to merge Tailwind CSS classes:
import { cn } from "$lib/utils";

// Usage in template
class={cn(
  "motion-safe:animate-shine pointer-events-none",
  className
)}

Animation Libraries

Components use these core animation libraries:
  • motion-sv - Svelte port of Framer Motion for declarative animations
  • runed - Svelte 5 runes utilities
  • Tailwind CSS animations - Via tw-animate-css package

Multi-File Components

Some complex components like file-tree and terminal consist of multiple Svelte files:
file-tree/
├── file-tree.svelte      (main component)
├── folder.svelte         (sub-component)
├── file.svelte           (sub-component)
├── collapse-button.svelte (sub-component)
└── index.ts              (exports)

Registry Configuration

Every component is defined in registry.json with metadata:
{
  "name": "shine-border",
  "type": "registry:block",
  "title": "Shine Border",
  "description": "A component that adds a shining animated border effect",
  "files": [
    {
      "path": "./src/lib/components/magic-ui/shine-border/shine-border.svelte",
      "type": "registry:component",
      "target": "magic/shine-border/shine-border.svelte"
    },
    {
      "path": "./src/lib/components/magic-ui/shine-border/index.ts",
      "type": "registry:file",
      "target": "magic/shine-border/index.ts"
    }
  ],
  "dependencies": [],
  "cssVars": {
    "theme": {
      "animate-shine": "shine var(--duration) infinite linear"
    }
  }
}

Next Steps

Installation Methods

Learn how to install and add components to your project

Customization

Discover how to customize components for your needs

Build docs developers (and LLMs) love