fractalsvelte mascot fractalsvelte fractalsvelte

Svelte 5 component · fractalsvelte-ui · Motion

SharedElement

A declarative hero transition wrapper that smoothly morphs spatial geometry and border radius between views using Web Animations API FLIP math.

Install

SharedElement is a Svelte 5 shared element component in @fractaldesign/fractalsvelte-ui. It works in SvelteKit and in any Svelte 5 app.

pnpm add @fractaldesign/fractalsvelte-ui

Import

import
import { SharedElement } from '@fractaldesign/fractalsvelte-ui';

Usage

Example
<SharedElement duration={400}>Click me</SharedElement>

Props

Also accepts every attribute of HTMLAttributes, spread onto the root element.

NameTypeDefault
name string —
duration number 400
class string ''

Snippets

NameTypeDefault
children Snippet —

Source

Show the SharedElement.svelte source
SharedElement.svelte
<script lang="ts">
	import { onDestroy, onMount, type Snippet } from 'svelte';
	import type { HTMLAttributes } from 'svelte/elements';
	import { playSharedElementTransition, recordSharedElement } from '../../view-transitions.js';

	interface Props extends HTMLAttributes<HTMLDivElement> {
		name: string;
		duration?: number;
		class?: string;
		children?: Snippet;
	}

	let {
		name,
		duration = 400,
		class: className = '',
		children,
		...restProps
	}: Props = $props();

	let element: HTMLDivElement | undefined = $state();

	onMount(() => {
		if (element) {
			playSharedElementTransition(name, element, duration);
		}
	});

	onDestroy(() => {
		if (element) {
			recordSharedElement(name, element);
		}
	});
</script>

<div
	bind:this={element}
	class="f-shared-element {className}"
	style="view-transition-name: {name};"
	{...restProps}
>
	{#if children}
		{@render children()}
	{/if}
</div>

<style>
	@layer fractalsvelte-ui.components {
		.f-shared-element {
			display: inline-block;
			box-sizing: border-box;
			will-change: transform, border-radius;
		}
	}
</style>