Skip to content
All Taste components

Forms

Text field

A labelled input with help text, focus ring and an error state.

default · focus · error · disabled

import { cn } from "@/lib/utils";

interface TextFieldProps extends React.InputHTMLAttributes<HTMLInputElement> {
  label: string;
  help?: string;
  error?: string;
}

export function TextField({ label, help, error, id, className, ...props }: TextFieldProps) {
  const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
  return (
    <div className="grid gap-1.5">
      <label htmlFor={fieldId} className="text-[13px] font-medium text-fg">{label}</label>
      <input
        id={fieldId}
        aria-invalid={error ? true : undefined}
        aria-describedby={help || error ? fieldId + "-note" : undefined}
        className={cn(
          "h-9 w-full rounded border border-border-strong bg-bg px-3 text-sm text-fg outline-none transition",
          "placeholder:text-fg-subtle focus:border-primary focus:ring-[3px] focus:ring-primary/20",
          "aria-[invalid=true]:border-danger aria-[invalid=true]:ring-[3px] aria-[invalid=true]:ring-danger/15",
          "disabled:bg-surface disabled:text-fg-subtle",
          className,
        )}
        {...props}
      />
      {(error || help) && (
        <p id={fieldId + "-note"} className={cn("text-xs", error ? "text-danger" : "text-fg-subtle")}>{error ?? help}</p>
      )}
    </div>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.