This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / web / src / lib / components / ui / Input.svelte
2.3 kB 80 lines
1<script module lang="ts"> 2 import { tv, type VariantProps } from "tailwind-variants"; 3 4 export const inputField = tv({ 5 base: "flex min-h-9 items-center gap-2 rounded-sm border bg-background-default px-2 py-1 transition-colors", 6 variants: { 7 error: { 8 false: 9 "border-border-default focus-within:border-border-strong focus-within:ring-1 focus-within:ring-border-strong", 10 true: "border-border-danger bg-background-danger-subtle text-foreground-danger focus-within:border-border-focus-danger focus-within:ring-1 focus-within:ring-border-focus-danger" 11 }, 12 disabled: { 13 false: "", 14 true: "cursor-not-allowed bg-background-inset text-foreground-disabled" 15 } 16 }, 17 defaultVariants: { 18 error: false, 19 disabled: false 20 } 21 }); 22 23 export type InputFieldVariants = VariantProps<typeof inputField>; 24</script> 25 26<script lang="ts"> 27 import type { Component } from "svelte"; 28 import type { HTMLInputAttributes, SvelteHTMLElements } from "svelte/elements"; 29 import Spinner from "./Spinner.svelte"; 30 31 interface Props extends Omit<HTMLInputAttributes, "class" | "value"> { 32 value?: string; 33 error?: boolean; 34 disabled?: boolean; 35 loading?: boolean; 36 iconLeft?: Component<SvelteHTMLElements["svg"]>; 37 iconRight?: Component<SvelteHTMLElements["svg"]>; 38 /** static, non-editable trailing text shown inside the field, e.g. a domain suffix */ 39 suffix?: string; 40 class?: string; 41 } 42 43 let { 44 value = $bindable(""), 45 error = false, 46 disabled = false, 47 loading = false, 48 iconLeft, 49 iconRight, 50 suffix, 51 class: className, 52 ...rest 53 }: Props = $props(); 54 55 const classes = $derived(inputField({ error, disabled, class: className })); 56</script> 57 58<div class={classes}> 59 {#if iconLeft} 60 {@const IconLeft = iconLeft} 61 <IconLeft class="size-4 shrink-0 text-foreground-subtle" aria-hidden="true" /> 62 {/if} 63 <input 64 bind:value 65 {disabled} 66 aria-invalid={error} 67 aria-busy={loading} 68 class="flex-1 bg-transparent text-sm outline-none placeholder:text-foreground-placeholder disabled:cursor-not-allowed" 69 {...rest} 70 /> 71 {#if suffix} 72 <span class="shrink-0 text-sm text-foreground-muted select-none">{suffix}</span> 73 {/if} 74 {#if loading} 75 <Spinner class="size-4 shrink-0" /> 76 {:else if iconRight} 77 {@const IconRight = iconRight} 78 <IconRight class="size-4 shrink-0 text-foreground-subtle" aria-hidden="true" /> 79 {/if} 80</div>