You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
3.2 KiB
88 lines
3.2 KiB
<script lang="ts">
|
|
/**
|
|
* Motion panel — the animation system as an explorable axis. Most demos
|
|
* never surfaced `motion` at all. This applies any preset from the catalog
|
|
* to a live sample (the `data-animation-style` + `data-state` content-domain
|
|
* pattern), lets you retune the duration / easing tokens, replay on demand,
|
|
* and preview the reduced-motion fallback. The selected preset name is the
|
|
* value a component's `motion` prop takes where it has one.
|
|
*/
|
|
import { DURATIONS, EASINGS, MOTION_PRESETS, type MotionKind } from './harness.svelte';
|
|
|
|
let { note = '' }: { note?: string } = $props();
|
|
|
|
let preset = $state('scale-fade');
|
|
let duration = $state('moderate');
|
|
let easing = $state('emphasized');
|
|
let reduce = $state(false);
|
|
let replayKey = $state(0);
|
|
|
|
const KINDS: MotionKind[] = ['enter/exit', 'emphasis', 'loop', 'js'];
|
|
const current = $derived(MOTION_PRESETS.find((p) => p.name === preset));
|
|
const isLoop = $derived(current?.kind === 'loop');
|
|
|
|
const sampleStyle = $derived(
|
|
`--motion-duration-enter: var(--duration-${duration}); --motion-duration-exit: var(--duration-${duration}); --motion-ease-enter: var(--ease-${easing}); --motion-ease-exit: var(--ease-${easing});`
|
|
);
|
|
</script>
|
|
|
|
<div data-uix-controls>
|
|
<div data-uix-control style="grid-column: 1 / -1;">
|
|
<span data-uix-control-label>preset <span data-uix-control-hint>the <code>motion</code> prop value</span></span>
|
|
{#each KINDS as kind}
|
|
<div data-uix-motion-kind>
|
|
<span data-uix-motion-kind-label>{kind}</span>
|
|
<span data-uix-chips role="radiogroup">
|
|
{#each MOTION_PRESETS.filter((p) => p.kind === kind) as p}
|
|
<button data-uix-chip data-active={preset === p.name} onclick={() => (preset = p.name)}>{p.name}</button>
|
|
{/each}
|
|
</span>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
|
|
<label data-uix-control>
|
|
<span data-uix-control-label>duration <span data-uix-control-hint>--duration-*</span></span>
|
|
<span data-uix-chips role="radiogroup">
|
|
{#each DURATIONS as d}
|
|
<button data-uix-chip data-active={duration === d} onclick={() => (duration = d)}>{d}</button>
|
|
{/each}
|
|
</span>
|
|
</label>
|
|
|
|
<label data-uix-control>
|
|
<span data-uix-control-label>easing <span data-uix-control-hint>--ease-*</span></span>
|
|
<span data-uix-chips role="radiogroup">
|
|
{#each EASINGS as e}
|
|
<button data-uix-chip data-active={easing === e} onclick={() => (easing = e)}>{e}</button>
|
|
{/each}
|
|
</span>
|
|
</label>
|
|
|
|
<label data-uix-control>
|
|
<span data-uix-control-label>reduced motion <span data-uix-control-hint>data-motion=reduce</span></span>
|
|
<span data-uix-switch>
|
|
<input type="checkbox" bind:checked={reduce} />
|
|
<span data-uix-switch-label>{reduce ? 'on' : 'off'}</span>
|
|
</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div data-uix-motion-stage>
|
|
<div data-uix-motion-sample-wrap data-motion={reduce ? 'reduce' : undefined}>
|
|
{#key replayKey}
|
|
<div data-uix-motion-sample data-animation-style={preset} data-state="open" style={sampleStyle}>
|
|
{preset}
|
|
</div>
|
|
{/key}
|
|
</div>
|
|
<div data-uix-motion-stage-foot>
|
|
<span data-uix-firma-meta>{current?.blurb}</span>
|
|
<button data-uix-play onclick={() => (replayKey += 1)}>↻ {isLoop ? 'remount' : 'replay'}</button>
|
|
</div>
|
|
</div>
|
|
|
|
{#if note}
|
|
<p data-uix-section-desc style="margin-top: var(--uix-space-4);">{note}</p>
|
|
{/if}
|