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 / Field.svelte
1.7 kB 69 lines
1<script module lang="ts"> 2 import { tv, type VariantProps } from "tailwind-variants"; 3 4 export const field = tv({ 5 slots: { 6 root: "flex flex-col gap-1.5", 7 label: "typography-paragraph-small font-medium text-foreground-default", 8 subtitle: "typography-paragraph-small text-foreground-muted" 9 }, 10 variants: { 11 // settings forms label their fields in small caps; the onboarding steps use 12 // sentence case, so the casing is a variant rather than baked into the slot 13 labelCase: { 14 upper: { label: "tracking-wide uppercase" }, 15 normal: { label: "" } 16 } 17 }, 18 defaultVariants: { 19 labelCase: "upper" 20 } 21 }); 22 23 export type FieldVariants = VariantProps<typeof field>; 24</script> 25 26<script lang="ts"> 27 import type { Snippet } from "svelte"; 28 import type { HTMLAttributes } from "svelte/elements"; 29 30 interface Props extends Omit<HTMLAttributes<HTMLDivElement>, "class" | "children"> { 31 label?: string; 32 subtitle?: string; 33 for?: string; 34 required?: boolean; 35 labelCase?: FieldVariants["labelCase"]; 36 class?: string; 37 children: Snippet<[{ id: string }]>; 38 } 39 40 let { 41 label, 42 subtitle, 43 for: forId, 44 required = false, 45 labelCase = "upper", 46 class: className, 47 children, 48 ...rest 49 }: Props = $props(); 50 51 const generatedId = $props.id(); 52 const id = $derived(forId ?? generatedId); 53 const slot = $derived(field({ labelCase })); 54</script> 55 56<div class={slot.root({ class: className })} {...rest}> 57 {#if label} 58 <label for={id} class={slot.label()}> 59 {label} 60 {#if required} 61 <span class="text-foreground-danger">*</span> 62 {/if} 63 </label> 64 {/if} 65 {@render children({ id })} 66 {#if subtitle} 67 <p class={slot.subtitle()}>{subtitle}</p> 68 {/if} 69</div>