personal web client for Bluesky
typescript solidjs bluesky atcute
at trunk 1.9 kB view raw
1import { type JSX } from 'solid-js'; 2 3import { createId } from '~/lib/hooks/id'; 4import { useTextareaAutosize } from '~/lib/hooks/textarea-autosize'; 5 6import { useFieldset } from './fieldset'; 7 8export interface TextareaInputProps { 9 ref?: (node: HTMLTextAreaElement) => void; 10 label?: string; 11 required?: boolean; 12 disabled?: boolean; 13 placeholder?: string; 14 error?: string | null | undefined | false; 15 value?: string; 16 headerAccessory?: JSX.Element; 17 onInput?: (ev: InputEvent) => void; 18 maxRows?: number; 19 minRows?: number; 20} 21 22const TextareaInput = (props: TextareaInputProps) => { 23 const fieldset = useFieldset(); 24 const id = createId(); 25 26 const hasValue = 'value' in props; 27 const isDisabled = () => fieldset.disabled || !!props.disabled; 28 29 const hasLabel = 'label' in props; 30 const hasHeaderAccessory = 'headerAccessory' in props; 31 32 return ( 33 <div class={`flex flex-col gap-2` + (isDisabled() ? ` opacity-50` : ``)}> 34 {(hasLabel || hasHeaderAccessory) && ( 35 <div class="flex justify-between gap-2"> 36 <label for={id} class="overflow-hidden break-words text-sm font-medium text-contrast"> 37 {props.label} 38 </label> 39 40 {props.headerAccessory} 41 </div> 42 )} 43 44 <textarea 45 ref={(node) => { 46 props.ref?.(node); 47 48 const getter = hasValue ? () => props.value : undefined; 49 useTextareaAutosize(node, getter, { 50 maxRows: props.maxRows, 51 minRows: props.minRows, 52 }); 53 }} 54 id={id} 55 required={props.required} 56 disabled={isDisabled()} 57 value={hasValue ? props.value : ''} 58 onInput={props.onInput} 59 placeholder={props.placeholder} 60 class="resize-none rounded border border-outline-md bg-background px-3 py-2 text-sm leading-6 text-contrast outline-2 -outline-offset-2 outline-accent placeholder:text-contrast-muted focus:outline" 61 /> 62 63 {props.error && <p class="text-de text-error">{props.error}</p>} 64 </div> 65 ); 66}; 67 68export default TextareaInput;