This repository has no description
1<script module lang="ts">
2 import { tv, type VariantProps } from "tailwind-variants";
3
4 export const textareaField = tv({
5 base: "min-h-20 w-full resize-y rounded border bg-background-default px-3 py-2 text-sm transition-colors placeholder:text-foreground-placeholder focus:outline-none",
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: "cursor-not-allowed resize-none bg-background-inset text-foreground-disabled"
15 },
16 readonly: {
17 false: "",
18 true: "cursor-default resize-none bg-background-subtle"
19 }
20 },
21 defaultVariants: {
22 error: false,
23 disabled: false,
24 readonly: false
25 }
26 });
27
28 export type TextareaFieldVariants = VariantProps<typeof textareaField>;
29</script>
30
31<script lang="ts">
32 import type { HTMLTextareaAttributes } from "svelte/elements";
33 import Spinner from "./Spinner.svelte";
34
35 interface Props extends Omit<HTMLTextareaAttributes, "class" | "value"> {
36 value?: string;
37 error?: boolean;
38 disabled?: boolean;
39 loading?: boolean;
40 readonly?: boolean;
41 class?: string;
42 }
43
44 let {
45 value = $bindable(""),
46 error = false,
47 disabled = false,
48 loading = false,
49 readonly = false,
50 class: className,
51 ...rest
52 }: Props = $props();
53
54 const classes = $derived(textareaField({ error, disabled, readonly, class: className }));
55</script>
56
57<div class="relative">
58 <textarea
59 bind:value
60 {disabled}
61 {readonly}
62 aria-invalid={error}
63 aria-busy={loading}
64 class={classes}
65 {...rest}></textarea>
66 {#if loading}
67 <Spinner class="absolute right-2 top-2 size-4" />
68 {/if}
69</div>