Monorepo for Tangled
tangled.org
1<script module lang="ts">
2 import { tv, type VariantProps } from "tailwind-variants";
3
4 export const select = tv({
5 base: "w-full appearance-none rounded border bg-background-default px-3 py-2 pr-9 text-sm outline-none transition-colors disabled:cursor-not-allowed",
6 variants: {
7 error: {
8 false:
9 "border-border-default focus:border-border-strong focus:ring-1 focus:ring-border-strong",
10 true: "border-border-danger bg-background-danger-subtle text-foreground-danger focus:border-border-focus-danger focus:ring-1 focus:ring-border-focus-danger"
11 },
12 disabled: {
13 false: "",
14 true: "text-foreground-disabled"
15 }
16 },
17 compoundVariants: [
18 {
19 error: true,
20 disabled: true,
21 class:
22 "border-border-danger-subtle bg-background-danger-subtle text-foreground-danger-subtle"
23 }
24 ],
25 defaultVariants: {
26 error: false,
27 disabled: false
28 }
29 });
30
31 export type SelectVariants = VariantProps<typeof select>;
32
33 const chevron = tv({
34 base: "pointer-events-none absolute right-3 top-1/2 size-3.5 -translate-y-1/2 text-foreground-subtle",
35 variants: {
36 error: {
37 true: "text-foreground-danger"
38 },
39 disabled: {
40 true: "text-foreground-disabled"
41 }
42 },
43 compoundVariants: [
44 {
45 error: true,
46 disabled: true,
47 class: "text-foreground-danger-subtle"
48 }
49 ]
50 });
51</script>
52
53<script lang="ts">
54 import ChevronDown from "$icon/chevron-down";
55 import type { HTMLSelectAttributes } from "svelte/elements";
56 import type { Snippet } from "svelte";
57
58 interface Props extends Omit<HTMLSelectAttributes, "class" | "value"> {
59 value?: string;
60 error?: boolean;
61 disabled?: boolean;
62 class?: string;
63 children?: Snippet;
64 }
65
66 let {
67 value = $bindable(""),
68 error = false,
69 disabled = false,
70 class: className,
71 children,
72 ...rest
73 }: Props = $props();
74
75 const classes = $derived(select({ error, disabled, class: className }));
76</script>
77
78<div class="relative">
79 <select bind:value {disabled} aria-invalid={error} class={classes} {...rest}>
80 {#if children}
81 {@render children()}
82 {/if}
83 </select>
84 <ChevronDown class={chevron({ error, disabled })} aria-hidden="true" />
85</div>