Forms

Native form controls dressed in deep black: thin borders that take the accent on focus, labels and messages wired for screen readers automatically.

Fields and labels

Wrap a control in Field: it renders the label, the hint or the error, and passes id, aria-describedby and aria-invalid to the control. Nothing to wire by hand.

This address is not valid.

TSDemo.tsx
<Field label="Name" required>
  <Input autoComplete="name" />
</Field>
<Field label="Email" error="This address is not valid.">
  <Input type="email" defaultValue="name@" />
</Field>

Select and textarea

Select is the native list, accessible and mobile friendly, with a thin chevron. Its placeholder stays grey until something is chosen.

We reply within two business days.

TSDemo.tsx
<Field label="Subject" hint="We reply within two business days.">
  <Select placeholder="Choose a subject">
    <option value="quote">Quote request</option>
    <option value="support">Support</option>
    <option value="other">Other</option>
  </Select>
</Field>
<Field label="Message">
  <Textarea placeholder="Your message" />
</Field>

Checkbox and switch

Both are native checkboxes: forms, keyboard and screen readers work as usual. The switch is announced as a switch. Use a checkbox for a choice that is submitted, a switch for a setting that applies right away.

TSDemo.tsx
<Checkbox label="I accept the terms of use" defaultChecked />
<Checkbox label="Receive the newsletter" description="One email a month, no ads." />
<Switch label="Notifications" description="Get notified of replies." defaultChecked />
<Switch label="Compact mode" disabled />

Controlled fields

Controls forward every native attribute and their ref: they work with React state, form libraries (React Hook Form, Formik) and server actions alike.

const [email, setEmail] = useState("");
const error = email && !email.includes("@") ? "This address is not valid." : undefined;

<Field label="Email" error={error}>
  <Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
</Field>

Field

PropTypeDefaultDescription
labelReactNode–Visible label, tied to the control.
hintReactNode–Help shown under the control.
errorReactNode–Replaces the hint and marks the control as invalid.
requiredbooleanfalseAdds an accent asterisk and sets required on the control.
idstring–Control id; generated when omitted.

Input, Textarea, Select

PropTypeDefaultDescription
invalidboolean–Forces the error style; set automatically by a Field with an error.
placeholderstring–On Select: an empty option shown, in grey, until something is chosen.
…propsnative attributes–Every attribute of input, textarea or select, and a ref.

Checkbox, Switch

PropTypeDefaultDescription
labelReactNode–Label; the whole block is clickable.
descriptionReactNode–Extra detail under the label.
…propsComponentProps<"input">–checked, defaultChecked, onChange, disabled, name… and a ref.