Skip to content
Esc
↑↓navigate↵open⌘Jpreview

← All examples

Slideshow

Source code

<script lang="ts">
	import { mercury, presence, type Variants } from '@omicrxn/mercury';

	const slides = ['One', 'Two', 'Three', 'Four'];
	let index = $state(0);
	let direction = $state(1);

	function paginate(step: number) {
		direction = step;
		index = (index + step + slides.length) % slides.length;
	}

	// Variants receive `custom`: the exiting slide reads the *latest* direction from
	// `presence`, so it leaves the way the new one comes from.
	const slide: Variants = {
		enter: (dir: number) => ({ x: dir * 120, opacity: 0 }),
		center: { x: 0, opacity: 1 },
		exit: (dir: number) => ({ x: dir * -120, opacity: 0 })
	};
</script>

<div class="flex flex-col items-center gap-4">
	<div class="relative flex h-32 w-56 items-center justify-center overflow-hidden">
		{#key index}
			<div
				class="box flex size-28! items-center justify-center text-lg font-semibold text-demo-fill-foreground"
				transition:presence={{ mode: 'popLayout', custom: direction }}
				{@attach mercury({
					custom: direction,
					variants: slide,
					initial: 'enter',
					animate: 'center',
					exit: 'exit',
					transition: { type: 'spring', duration: 0.4, bounce: 0.15 }
				})}
			>
				{slides[index]}
			</div>
		{/key}
	</div>
	<div class="flex gap-2">
		<button
			type="button"
			class="min-h-11 rounded-md border border-demo-stroke px-4 text-sm font-medium"
			onclick={() => paginate(-1)}>Previous</button
		>
		<button
			type="button"
			class="min-h-11 rounded-md border border-demo-stroke px-4 text-sm font-medium"
			onclick={() => paginate(1)}>Next</button
		>
	</div>
</div>