All components
Input
A hand-drawn Base UI input across its types and states.
Default
Types
With value
Invalid
Disabled
Installation
Add Input with the shadcn CLI.
npx shadcn@latest add https://sketchcn.chuwii.com/r/input.json
Examples
Labelled fields, search bars and live validation.
Labelled field with a hint
We only use this to send you sketches.
import { Input } from "@/components/ui/input";

export function EmailField() {
  const id = useId();

  return (
    <div className="flex w-full flex-col gap-1.5">
      <label htmlFor={id} className="text-sm">
        Email
      </label>
      <Input id={id} type="email" placeholder="[email protected]" />
      <span className="text-muted-foreground text-xs">
        We only use this to send you sketches.
      </span>
    </div>
  );
}
Search bar
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";

export function SearchBar({ onSearch }: { onSearch: (term: string) => void }) {
  const [term, setTerm] = useState("");

  return (
    <div className="flex w-full items-center gap-2">
      <Input
        value={term}
        onChange={(event) => setTerm(event.target.value)}
        placeholder="Search sketches"
      />
      <Button size="icon" aria-label="Search" onClick={() => onSearch(term)}>
        <Search />
      </Button>
    </div>
  );
}
Live validation
import { Input } from "@/components/ui/input";

export function UsernameField() {
  const [username, setUsername] = useState("");
  const isTooShort = username.length > 0 && username.length < 3;

  return (
    <div className="flex w-full flex-col gap-1.5">
      <Input
        value={username}
        aria-invalid={isTooShort}
        onChange={(event) => setUsername(event.target.value)}
        placeholder="Username"
      />
      {isTooShort && (
        <span className="text-destructive text-xs">
          Usernames need at least 3 characters.
        </span>
      )}
    </div>
  );
}