Input
A 48px text input: visible focus, a 3:1 border on every surface and errors from aria-invalid.
Installation
$ pnpm dlx shadcn@latest add @ssntl/inputUsage
import { Input } from "@/components/ui/input"
<Input type="email" autoComplete="email" placeholder="ana@studio.com" />- 48px tall, the same as buttons, so a field and its action line up.
- The border uses the input token (3:1 on every surface); focus darkens it and shows the ring.
- Use the right type and autoComplete. The placeholder shows an example value, never the label.
- Errors come from aria-invalid plus a hint that says how to fix it (see Field).
Code
import * as React from "react"
import { cn } from "@/lib/utils"
// Essential Design `es-input`: 48px (the height of buttons), `card` fill, a 1px
// `input` border that meets 3:1 on every surface, `radius-sm`. Focus darkens the
// border and shows the ring; errors come from aria-invalid, never color alone.
function Input({
className,
type = "text",
...props
}: React.ComponentProps<"input">) {
return (
<input
data-slot="input"
type={type}
className={cn(
"h-12 w-full min-w-0 rounded-sm border border-input bg-card px-4 text-body text-foreground",
"transition-[border-color] duration-(--duration-fast) ease-out placeholder:text-muted-foreground",
"hover:border-muted-foreground focus:border-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
"disabled:cursor-not-allowed disabled:opacity-40 aria-invalid:border-destructive",
"file:mr-3 file:border-0 file:bg-transparent file:font-medium",
className
)}
{...props}
/>
)
}
export { Input }