This repository has no description
1<script lang="ts">
2 import type { Snippet } from "svelte";
3 import type { HTMLInputAttributes } from "svelte/elements";
4 import Check from "$icon/check";
5 import Minus from "$icon/minus";
6
7 interface Props extends Omit<HTMLInputAttributes, "type" | "class" | "checked" | "children"> {
8 checked?: boolean;
9 indeterminate?: boolean;
10 disabled?: boolean;
11 class?: string;
12 children?: Snippet;
13 }
14
15 let {
16 checked = $bindable(false),
17 indeterminate = $bindable(false),
18 disabled = false,
19 class: className,
20 children,
21 ...rest
22 }: Props = $props();
23
24 const labelClasses = $derived(
25 `inline-flex items-center gap-2 cursor-pointer ${disabled ? "cursor-not-allowed text-foreground-disabled" : ""} ${className ?? ""}`
26 );
27</script>
28
29<label class={labelClasses}>
30 <span class="relative inline-flex size-4 shrink-0">
31 <input
32 type="checkbox"
33 bind:checked
34 bind:indeterminate
35 {disabled}
36 class="peer size-4 shrink-0 appearance-none rounded border border-border-strong bg-background-default transition-colors duration-150 hover:bg-background-subtle checked:border-foreground-default checked:bg-foreground-default indeterminate:border-foreground-default indeterminate:bg-foreground-default focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-foreground-default disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-50"
37 {...rest}
38 />
39 <Check
40 class="pointer-events-none absolute inset-0 m-auto hidden size-3.5 text-background-default peer-checked:block peer-indeterminate:hidden peer-disabled:opacity-50"
41 aria-hidden="true"
42 />
43 <Minus
44 class="pointer-events-none absolute inset-0 m-auto hidden size-3.5 text-background-default peer-indeterminate:block peer-disabled:opacity-50"
45 aria-hidden="true"
46 />
47 </span>
48 {#if children}
49 <span>{@render children()}</span>
50 {/if}
51</label>