Form controls
Style native HTML controls with CSS. State variants handle their appearance.
Text input
Add input to a text field or textarea.
Set aria-invalid="true" to show an error.
The focus ring stays inside the field.
That handle is taken. Choose another.
<div class="flex flex-col gap-2">
<label for="email" class="text-label text-rambutan-200">Email</label>
<input id="email" name="email" type="email" placeholder="you@bruhs.dev" class="input" />
</div>
<div class="flex flex-col gap-2">
<label for="handle" class="text-label text-rambutan-200">Handle</label>
<input id="handle" name="handle" value="bruh" aria-invalid="true" aria-describedby="handle-error" class="input" />
<p id="handle-error" class="text-body-sm text-lychee-300">That handle is taken. Choose another.</p>
</div>
<div class="flex flex-col gap-2 sm:col-span-2">
<label for="bio" class="text-label text-rambutan-200">Bio</label>
<textarea id="bio" name="bio" rows="3" placeholder="A short bio" class="input"></textarea>
</div> Segmented control
Use a segmented control to choose one of two to four views.
Mark the active item with the ARIA state that matches its role.
The class supports aria-pressed, aria-selected and aria-checked.
<div class="segmented" role="group" aria-label="View">
<button type="button" class="segmented-item" aria-pressed="true">Preview</button>
<button type="button" class="segmented-item" aria-pressed="false">Code</button>
</div> Select
Use a native <select> with a custom chevron.
The wrapper carries the focus ring. Examples below show the available sizes and states.
Choose a fruit to continue.
Checkbox
Set input.indeterminate = true in JavaScript for a partial selection.
CSS handles the appearance through :indeterminate and group-not-has-indeterminate.
Radio
Toggle
Rules
Give every control a name and an accessible label.
Use input for text fields. Use inset-ring for custom control outlines.
Make choice controls larger on mobile with size-5 sm:size-4.
Leave a gap between a field and its button, or place the button inside the field.