23fa6137ff
Introduce cva-driven Button, form, card, table, and segmented controls. Use clsx and tailwind-merge through a shared cn helper so callers can override component defaults without relying on global semantic CSS. Control sizes define minimum heights while icon-only actions retain stable square dimensions.
44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import { cva, type VariantProps } from "class-variance-authority";
|
|
import { splitProps, type JSX } from "solid-js";
|
|
import { cn } from "../../lib/cn";
|
|
|
|
export const textareaVariants = cva(
|
|
"min-h-36 w-full rounded-md border border-line bg-white px-3 py-3 text-sm text-ink outline-none transition-colors focus:border-brand disabled:cursor-not-allowed disabled:opacity-45 aria-invalid:border-coral-strong",
|
|
{
|
|
variants: {
|
|
resize: {
|
|
vertical: "resize-y",
|
|
none: "resize-none",
|
|
},
|
|
typography: {
|
|
mono: "font-mono",
|
|
sans: "font-sans",
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
resize: "vertical",
|
|
typography: "mono",
|
|
},
|
|
},
|
|
);
|
|
|
|
export type TextareaProps = JSX.TextareaHTMLAttributes<HTMLTextAreaElement> &
|
|
VariantProps<typeof textareaVariants>;
|
|
|
|
/** Standard multiline input with explicit resize and typography variants. */
|
|
export function Textarea(props: TextareaProps) {
|
|
const [local, rest] = splitProps(props, ["resize", "typography", "class", "children"]);
|
|
return (
|
|
<textarea
|
|
{...rest}
|
|
data-slot="textarea"
|
|
class={cn(
|
|
textareaVariants({ resize: local.resize, typography: local.typography }),
|
|
local.class,
|
|
)}
|
|
>
|
|
{local.children}
|
|
</textarea>
|
|
);
|
|
}
|