Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061<script lang="ts"> import type { Snippet } from "svelte"; import { buttonIcon, type ButtonIconVariants } from "#lib/components/ui/Button.svelte"; import { CROSSFADE_DURATION, CROSSFADE_EASING } from "#lib/motion/spring.ts";
interface Props { on: boolean; failed?: boolean; size?: ButtonIconVariants["size"]; offLabel: string; onLabel: string; labelClass?: string; off: Snippet<[string]>; onIcon: Snippet<[string]>; err: Snippet<[string]>; }
let { on, failed = false, size = "small", offLabel, onLabel, labelClass, off, onIcon, err }: Props = $props();
const icon = $derived(buttonIcon({ size })); const face = $derived(failed ? "err" : on ? "on" : "off"); const layer = (key: typeof face) => `swap-layer ${icon}${key === face ? "" : " swap-icon-out"}`;
let armed = $state(false);
const armOnClick = (node: HTMLElement) => { const control = node.closest("button, a") ?? node; const arm = () => (armed = true); control.addEventListener("click", arm, { capture: true }); return () => control.removeEventListener("click", arm, { capture: true }); };</script>
<span class="contents" {@attach armOnClick} style:--swap-duration={armed ? `${CROSSFADE_DURATION}ms` : "0ms"} style:--swap-easing={CROSSFADE_EASING}> <span class={["grid", icon]} aria-hidden="true"> {@render off(layer("off"))} {@render onIcon(layer("on"))} {@render err(layer("err"))} </span> <span class={["grid", labelClass]} aria-hidden="true"> <span class={["whitespace-nowrap swap-layer", on && "swap-label-out"]}>{offLabel}</span> <span class={["whitespace-nowrap swap-layer", !on && "swap-label-out"]}>{onLabel}</span> </span> <span class="sr-only">{on ? onLabel : offLabel}</span></span>