Skip to content
Drivn logoDrivn
2 min read

React Form Components — Input, Select, Checkbox, Button

Form UI for React — Input, Textarea, Select, Combobox, Checkbox, Radio, Switch, Slider. Drivn ships each with label, error, and ref forwarding built in.

A form is the most hostile surface in a web app. Every missing htmlFor, every unlabelled error, every unfocusable control becomes a support ticket. Drivn's form family is built so that label pairing, error display, and ref forwarding are the defaults — you opt out, not in — and every control works with React Hook Form or plain useState without a wrapper.

This hub links every input-family component in Drivn with a short description and guidance on when to use which. The components share a consistent API: label, error, helperText, disabled, size, and the native underlying props. Once you have used one, the rest follow the same mental model. Server-side validation, async error display, and submit state all fit into the same shape without extra abstractions or context providers to wire at the app root. That consistency keeps new team members productive on day one.

Text entry

Use input for single-line values (email, name, URL). Use textarea for free-form text with auto-resize and a character count. Both support icons on either side, an error state that renders a red ring and message below, and a ref forward that plays nicely with React Hook Form's register().

For short, constrained entries (country, currency, priority), use select — it renders a native-feeling dropdown with keyboard support. For long lists with search, use combobox, which adds filtering, multi-select, and icon support.

Choice and toggle

For a single choice among 2-4 options, use a radio-group. For multiple independent choices, use checkbox. For a boolean on/off, use switch — visually stronger than a checkbox and more appropriate for immediate-effect toggles (dark mode, notifications on/off).

Use toggle when the control is an action ("Bold", "Italic") rather than a data state; it has a pressed visual that reads as a button rather than a form field.

Numeric ranges

For a numeric value on a continuous scale, use a slider with step snapping, vertical orientation, and size variants. Sliders are better than number inputs for values where the user needs to feel the range (volume, opacity, zoom); for exact values or large ranges, an input or a number input is faster.

Pair a slider with a small label showing the current value, and keep the step appropriate to the range (1 for 0-100, 0.1 for 0-10). Sliders are not keyboard-friendly on mobile — provide a numeric input alongside for accessibility.

Submit and validation

Every form ends in a button. Drivn's Button ships with a loading prop that handles async submission — it sets aria-busy, disables clicks, and preserves the button width. Combine it with the React Hook Form integration to bind loading state to formState.isSubmitting.

For validation messages, set the error prop on each field — do not rely on browser default tooltips, which users ignore. Consistent in-field error styling builds trust and reduces retry rate.

1'use client'
2import { useForm } from 'react-hook-form'
3import { Input } from '@/components/ui/input'
4import { Button } from '@/components/ui/button'
5
6export function SignupForm() {
7 const { register, handleSubmit, formState } = useForm<{ email: string }>()
8 return (
9 <form onSubmit={handleSubmit(console.log)}>
10 <Input
11 label="Email"
12 error={formState.errors.email?.message}
13 {...register('email', { required: 'Required' })}
14 />
15 <Button loading={formState.isSubmitting}>Sign up</Button>
16 </form>
17 )
18}
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →