Centrim Design System — a token-first, accessible React component system.
Forms & advanced inputs
Structural form primitives (Form, FormField, FieldSet, FormSection) and the advanced input composites built on top of them — search, numeric, password, combobox, multi-select, date/time pickers, sliders and toggle groups.
Form
`<form>` wrapper that establishes the standard vertical rhythm between fields and sections, and can disable every descendant control at once (e.g. while submitting) via a native `<fieldset disabled>` boundary.
import { Form, FormField, FieldGroup, FieldSet, FormSection } from "@/design-system";
Account details form
FormField wires label, description and validation message to each control automatically.
FormField
Connects a visible label, optional description and a single validation message (error, success or warning) to exactly one control, generating and wiring all the ids for you.
import { FormField, FormLabel, FormDescription, FormMessage } from "@/design-system";
States
Only one of error / success / warning should be set at a time.
Visible to everyone in the workspace.
Error: This slug is already taken.
Success: Endpoint responded with 200 OK.
Warning: You're close to your plan limit (18/20 used).
FormLabel, FormDescription and FormMessage standalone
Used directly when you need custom layout instead of FormField.
Rotate this key if it may have been exposed.
Warning: Last rotated 214 days ago.
FieldGroup, FieldSet & FormSection
Layout helpers for longer forms: FieldGroup places closely related fields side by side, FieldSet groups controls under a native legend, and FormSection titles a whole segment of the form.
import { FieldGroup, FieldSet, FormSection } from "@/design-system";
FieldGroup
Two related fields side by side on wide screens, stacked on narrow ones.
FieldSet
SearchInput
A text field dedicated to search: leading icon, clear affordance once there's a value, and a loading state for async results.
import { SearchInput } from "@/design-system";
Sizes
NumberInput
A numeric field with min/max/step, stepper buttons and native keyboard arrow support — for quantities, prices and other bounded numbers.
import { NumberInput } from "@/design-system";
States
Must be 100 or less.
PasswordInput
A password field with a show/hide visibility toggle that announces its pressed state, for sign-in and account forms.
import { PasswordInput } from "@/design-system";
States
Strong password.
Combobox
A single-select typeahead field for choosing one value from a longer list, such as a country or a customer — searchable rather than a long native <select>.
import { Combobox } from "@/design-system";
Country
Type to filter, use arrow keys and Enter to select.
MultiSelect
Like Combobox, but for choosing several values at once; selections render as removable tags inside the trigger.
import { MultiSelect } from "@/design-system";
Skills
Selected items appear as removable tags.
DatePicker
A single-date field: a button trigger showing the formatted date, opening a keyboard-navigable calendar popover on activation.
import { DatePicker } from "@/design-system";
Project start date
Past dates are disabled.
When work on this project begins.
States
Choose a date at least 30 days out.
DateRangePicker
Selects a start and end date together — a booking stay, a reporting period, a dashboard time filter. Always labelled: the visible label defaults to “Date range”, so the trigger is never ambiguous outside its surrounding context.
import { DateRangePicker } from "@/design-system";
When to use
- Any two-ended period: reporting windows, stays, campaign schedules.
- Dashboard filters — pair with hideLabel only when a heading already names the filter.
When not to use
- A single date — use DatePicker.
- A time of day — use TimePicker.
Default
No props — the label defaults to “Date range”.
Custom label and range selected
With description
Metrics are recalculated for the selected window.
States
Select both a start and an end date.
Hidden visible label
Use only when a nearby heading already names the control; the accessible label remains.
TimePicker
An accessible time selector presenting a listbox of time slots at a configurable step, in 12- or 24-hour format — for scheduling meetings or deliveries.
import { TimePicker } from "@/design-system";
Meeting time
15-minute increments, 24-hour clock.
12-hour format
Slider
A single-thumb slider for choosing one value within a bounded range, e.g. a budget or a volume level.
import { Slider } from "@/design-system";
Sizes
With value label and error state
Approaching storage limit.
RangeSlider
A two-thumb slider for selecting a numeric range, such as a price band or an age bracket.
import { RangeSlider } from "@/design-system";
Price range
ToggleGroup
A set of toggle buttons that are either mutually exclusive (type=’single’, e.g. text alignment) or independently toggled (type=’multiple’, e.g. notification channels).
import { ToggleGroup, ToggleGroupItem } from "@/design-system";
Single selection — text alignment
Multiple selection — text formatting
Text labels — notification channels
type=’multiple’ lets more than one item be on at once.
Form layouts
Reusable layout patterns for form bodies: single-column, two-column, compact and inline. FormLayout is a responsive grid; FormActions is the footer row for submit/cancel.
import { FormLayout, FormLayoutFull, InlineForm, FormActions } from "@/design-system";
When to use
- Single column (columns={1}) for anything the user reads top-to-bottom — the safest default.
- Two columns (columns={2}) for short, closely-related fields on wide screens; they stack below md.
- InlineForm for one-line forms such as a search bar or an invite field with a button.
- density='compact' inside dense surfaces like drawers, filter panels and settings rows.
When not to use
- Do not use multi-column layouts for long or error-prone fields — scanning across columns hurts completion.
- Do not nest FormLayout inside FieldGroup; pick one grid per row.
Two-column with a full-width field
Shown on invoices.
Compact density
density='compact' tightens the rhythm for dense surfaces.
Inline form
Side by side from sm up, stacked and full width below it.
Form actions
File upload in forms
FileUpload, Dropzone and FileList/FileItem composed inside the form field system, with upload progress rendered by the existing Progress component.
import { FileUpload, Dropzone, FileList } from "@/design-system";
When to use
- FileUpload when the upload is secondary to the rest of the form.
- Dropzone when uploading is the primary action on the surface.
- FileList to show what has been attached, with per-file progress, retry and remove.
When not to use
- Do not build a bespoke upload widget — compose these three instead.
Attachments field
PDF or PNG up to 10MB. Files upload as soon as they are added.
Drag files here
or browse from your device
invoice-2026-04.pdf
242.2 KB
Uploaded
contract-draft.docx
1.2 MB
scan.png
4.6 MB
Upload failed — file too large.
Error state
Drag files here
That file type isn't supported.
Textarea
Multi-line text field for longer free-form content such as comments or descriptions, shown here inside a FormField for context.
import { Textarea, FormField } from "@/design-system";
Project notes
Visible to everyone with access to this project.
Complete form example
This example demonstrates how individual form components can be composed into a complete, production-ready form. Use it as a reference for layout, hierarchy, spacing, validation and responsive behaviour.
When to use this pattern
Use this structure for forms that contain multiple related groups of information.
Form anatomy
- 1.Page header — breadcrumb, title and description set the context.
- 2.Form sections — Personal information, Preferences, Additional information.
- 3.Field groups — two columns for short fields, full width for long ones.
- 4.Validation — messages sit directly under the field they belong to.
- 5.Actions — Cancel and the primary Save profile, in a footer row.
Do
- Group related fields.
- Use clear labels.
- Keep forms visually scannable.
- Use helper text only when necessary.
- Keep primary actions clear.
- Use responsive layouts.
- Show validation close to the affected field.
Don't
- Put unrelated fields together.
- Use placeholder text as the only label.
- Overuse cards.
- Create unnecessary sections.
- Use colour as the only validation indicator.
- Create custom components when an existing design-system component works.
Playground
How the form looks before anything is submitted.
Create profile
Add the basic information and preferences for this profile.