Form inputs
Components for data entry and user selection.
Components
| Component | Purpose |
|---|---|
| Input | Single-line text (text, email, tel, password, number, search, URL) |
| Textarea | Multi-line text entry |
| Select | Pick one option from a dropdown |
| Checkboxes | Pick one or more from a visible set |
| Radio group | Pick exactly one from a visible set |
| Radio card | Single-select with card-style layout (payment methods, route comparison) |
| Date input | Structured day/month/year fields |
| Switch | On/off toggle for settings |
| Toggle | Pressable button for toggling states (bold, italic, view mode) |
| Multi select | Searchable dropdown with chips for multiple selections |
| Input OTP | Individual digit fields for one-time passwords |
| File uploader | Drag-and-drop or browse file upload |
| Date picker | Calendar popover with typed date entry |
| Currency input | Formatted money input with symbol and code |
| Phone input | Phone number with country code selector |
| Password input | Show/hide toggle with optional strength meter |
| Masked input | Auto-formatted entry (card number, expiry, CVV) |
| Form field | Wraps label, input, helper text, and error message |
Input
Single-line text entry. Each input requires a visible label above the field.
- Supports
text,email,tel,password,number,search, andurltypes - Error messages appear below the input with
aria-describedby - Size inputs to match expected content length
- 1Container / border
- 2Label
- 3Placeholder text
- 4Helper text
- 5Error icon
- 6Error message
Select
Pick one option from a dropdown.
- Default empty option prompts selection ("Select a reason")
- If more than 15 options, use Search select instead
Checkboxes
Pick one or more from a visible set.
- Group related checkboxes with a
<fieldset>and legend - Supports indeterminate state for "select all" patterns
Date input
Date entry using three separate fields for day, month, and year.
- Hint text shows expected format (e.g., "15 03 2026")
- Validates each field independently
- Preferred over date picker for birth dates and ID documents
Switch
Binary toggle for settings that take effect immediately.
- Use switch for instant changes; use checkbox for form submissions
Sizes
| Size | Track (W x H) | Thumb | Use case |
|---|---|---|---|
sm | 24 x 14px | 12px | Compact lists, settings rows |
default | 32 x 18px | 16px | Standard forms |
lg | 48 x 28px | 24px | Hero toggles, meets WCAG 2.2 AA target size |
Toggle
Pressable button that switches between on and off states. Used for formatting options or view toggles. Supports icon-only or icon+text.
Textarea
Multi-line text entry for notes, messages, and descriptions.
- Vertical resize by default
- Character count indicator for max-length fields
Max 200 characters.
0/200Radio group
Pick exactly one from a visible set.
- Vertical layout by default; horizontal for 2-3 short options
- Pre-select a default when a common choice exists
Radio card
Single-select where each option carries more visual weight than a standard radio button. Built on RadioGroup keyboard semantics.
Variants
| Variant | Use case | Icon size |
|---|---|---|
compact | Simple lists (payment method, ID type, coin) | 32px |
expanded | Comparisons with detail rows (transfer routes, plans) | 40px |
Radio card variants
Expanded cards include a separator, key-value detail rows, and an optional badge (Cheapest, Fastest, Recommended).
States
| State | Visual treatment |
|---|---|
| Unselected | 1px border, white background |
| Hover | Darker border, subtle shadow |
| Focus-visible | 2px primary border, focus ring |
| Selected | 2px primary border, tinted background, filled indicator |
| Disabled | Dimmed, not-allowed cursor |
Rules
- Maximum 6 options per group
- Don't mix compact and expanded in the same group
- No interactive elements inside a card
- Pre-select only when paired with a badge explaining why
Search select
Searchable dropdown for picking one option from a long list. Opens a popover with auto-focused search, powered by cmdk.
- Selected item shows a check mark; selecting again deselects
- Escape clears search first, then closes on second press
- Hidden input for native form submission
Multi select
Searchable dropdown for picking multiple options. Selected items appear as removable chips.
- Popover stays open after each selection
- Backspace removes the last chip
maxDisplaycontrols chip count before "+N more"maxlimits total selections
2 selected
Input OTP
Separate fields for each digit of a one-time password.
- Auto-focuses the next field on input
- Paste fills all fields at once
File uploader
Compound component for file upload. Primary use: KYC verification (ID documents, proof of address, selfie).
Four parts: FileUpload (root state manager), FileUploadDropzone (drag-and-drop area), FileUploadItem (file row with progress), and FileUploadItemList (renders all items).
States
| Status | Visual treatment |
|---|---|
| Pending | Muted icon, file size |
| Uploading | Primary icon, progress bar, percentage |
| Complete | Green check, success border |
| Error | Red alert, error border, message |
Drag and drop or browse
PDF, JPG, PNG up to 10 MB
Date picker
Single date selection with typed input and calendar popover.
- Typing-first: dashes insert automatically as users type
DD-MM-YYYY - Month/year dropdown navigation for fast jumping (ideal for DOB)
- Invalid input reverts to previous valid date on blur
Currency input
Formatted money input with currency symbol prefix and code suffix. Uses inputMode="decimal" for the right mobile keyboard without native spinners.
- Focus shows raw number (
1250.00), blur applies locale formatting (1,250.00) - Fraction digits adapt to currency (KRW = 0, USD = 2)
- Currency symbol from
Intl.NumberFormat-- no hardcoded table
Variants
| Variant | Suffix | When to use |
|---|---|---|
| Static | InputGroupText with currency code | Single-currency fields (receive amount) |
| Selectable | Select dropdown | Multi-currency fields (send amount) |
Sizes
| Size | Height | Font | Use case |
|---|---|---|---|
default | 40px | --ds-text-base | Standard form fields |
hero | 3rem | --ds-text-2xl, bold | Primary amount entry (send flow) |
Phone input
Phone number entry with country code selector. Uses a SearchSelect dropdown showing flag and dial code alongside a tel input.
- Accepts raw digits only -- paste strips non-numeric characters
suggestedCountriesprop shows a "Suggested" group at the top
Password input
Password entry with show/hide toggle. Eye icon toggles type between password and text, then returns focus to the input.
Strength indicator
When showStrength is true and value is non-empty, a strength bar appears below.
| Score | Label | Width | Color |
|---|---|---|---|
| 1 | Weak | 25% | red-500 |
| 2 | Fair | 50% | yellow-500 |
| 3 | Good | 75% | accent-500 |
| 4 | Strong | 100% | green-600 |
Scoring: +1 for 8+ characters, +1 for a digit, +1 for a special character, +1 for 12+ characters with all above met.
Masked input
Auto-formatted text entry. Mask characters: 0 = digit, A = letter, * = alphanumeric. Everything else is a literal separator inserted automatically.
Presets
| Preset | Pattern | Use case |
|---|---|---|
MASKS.CARD_NUMBER | 0000 0000 0000 0000 | Credit/debit card |
MASKS.CARD_EXPIRY | 00/00 | Card expiry (MM/YY) |
MASKS.CVV_3 | 000 | 3-digit CVV |
MASKS.CVV_4 | 0000 | 4-digit CVV (Amex) |
MASKS.DATE | 00/00/0000 | Date (DD/MM/YYYY) |
For expiry masks, typing a first digit > 1 auto-prepends "0" (typing "5" becomes "05"). detectCardBrand(digits) returns "visa", "mastercard", "amex", or "unknown" for dynamic card icons.
Form field
Wraps a label, input, helper text, and error into one accessible unit. You provide the input as children -- FormField doesn't render its own.
FormLabellinks to the input viahtmlForFormDescriptionshows helper text, hidden when an error is activeFormMessageshows the error withrole="alert"- Required fields get an asterisk in the label
As it appears on your ID
Auto-generated, cannot be changed
We will send a verification link
Enter a valid email address
Use letters, numbers, and symbols
Must be at least 8 characters
You can change this later
Design and accessibility
Every input needs a visible label above the field. Error states use color, icon, and text together -- never color alone. Group related inputs with a <fieldset> and legend.
All error inputs must include aria-invalid="true" and aria-describedby pointing to the error message. Switch uses role="switch" with aria-checked. Radio cards convey selection through three independent signals: border weight, background tint, and indicator fill.
Components requiring aria-label (no visible label rendered): CurrencyInput, PhoneInput, PasswordInput, MaskedInput. Password strength uses role="status" with aria-live="polite".