51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import type { TextareaHTMLAttributes } from 'react';
|
|
import { cn } from '../../lib/cn';
|
|
|
|
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
label?: string;
|
|
hint?: string;
|
|
error?: string;
|
|
className?: string;
|
|
}
|
|
|
|
export function Textarea({
|
|
label,
|
|
hint,
|
|
error,
|
|
required,
|
|
className,
|
|
disabled,
|
|
...rest
|
|
}: TextareaProps) {
|
|
return (
|
|
<label className={cn('flex flex-col gap-1.5 font-sans', disabled && 'cursor-not-allowed', className)}>
|
|
{label && (
|
|
<span className="text-sm font-semibold text-slate-700">
|
|
{label}
|
|
{required && <span className="text-ruby-600"> *</span>}
|
|
</span>
|
|
)}
|
|
<div
|
|
className={cn(
|
|
'flex rounded-md border transition-[border-color,box-shadow] duration-150 overflow-hidden',
|
|
disabled ? 'bg-sunk border-border-subtle' : 'bg-card',
|
|
error ? 'border-ruby-600' : !disabled && 'border-border-default focus-within:ring-2 focus-within:ring-navy-600/20 focus-within:border-navy-600',
|
|
)}
|
|
>
|
|
<textarea
|
|
required={required}
|
|
disabled={disabled}
|
|
className={cn(
|
|
'flex-1 w-full min-h-[80px] p-3 border-none outline-none bg-transparent font-sans text-base resize-y',
|
|
disabled ? 'text-muted cursor-not-allowed' : 'text-strong',
|
|
)}
|
|
{...rest}
|
|
/>
|
|
</div>
|
|
{(hint || error) && (
|
|
<span className={cn('text-xs', error ? 'text-ruby-600' : 'text-faint')}>{error || hint}</span>
|
|
)}
|
|
</label>
|
|
);
|
|
}
|