Skip to main content

Form inputs

Components for data entry and user selection.

Components

ComponentPurpose
InputSingle-line text (text, email, tel, password, number, search, URL)
TextareaMulti-line text entry
SelectPick one option from a dropdown
CheckboxesPick one or more from a visible set
Radio groupPick exactly one from a visible set
Radio cardSingle-select with card-style layout (payment methods, route comparison)
Date inputStructured day/month/year fields
SwitchOn/off toggle for settings
TogglePressable button for toggling states (bold, italic, view mode)
Multi selectSearchable dropdown with chips for multiple selections
Input OTPIndividual digit fields for one-time passwords
File uploaderDrag-and-drop or browse file upload
Date pickerCalendar popover with typed date entry
Currency inputFormatted money input with symbol and code
Phone inputPhone number with country code selector
Password inputShow/hide toggle with optional strength meter
Masked inputAuto-formatted entry (card number, expiry, CVV)
Form fieldWraps 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, and url types
  • Error messages appear below the input with aria-describedby
  • Size inputs to match expected content length
Input anatomy
1
3
5
We will send a verification link
4
Enter a valid email address
6
  1. 1Container / border
  2. 2Label
  3. 3Placeholder text
  4. 4Helper text
  5. 5Error icon
  6. 6Error message
Input states
DefaultAs it appears on your ID
Focus
Filled
Read-only
ErrorEnter a valid email address
Disabled
Skeleton

Select

Pick one option from a dropdown.

  • Default empty option prompts selection ("Select a reason")
  • If more than 15 options, use Search select instead
Select states
Default
Hover
Focus
Disabled
ErrorPlease select a transfer reason

Checkboxes

Pick one or more from a visible set.

  • Group related checkboxes with a <fieldset> and legend
  • Supports indeterminate state for "select all" patterns
Checkbox
Notifications
Checkbox states
Unchecked
Checked
Focus
Indeterminate
Disabled
Disabled checked

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
Date input
For example, 15 03 2026

Switch

Binary toggle for settings that take effect immediately.

  • Use switch for instant changes; use checkbox for form submissions

Sizes

SizeTrack (W x H)ThumbUse case
sm24 x 14px12pxCompact lists, settings rows
default32 x 18px16pxStandard forms
lg48 x 28px24pxHero toggles, meets WCAG 2.2 AA target size
Switch
Switch sizes
sm (24×14)
default (32×18)
lg (48×28)
Switch states
Off
On
Hover (off)
Hover (on)
Focus
Disabled (off)
Disabled (on)

Toggle

Pressable button that switches between on and off states. Used for formatting options or view toggles. Supports icon-only or icon+text.

Toggle states
Default
Hover
Focus
Pressed
Disabled

Textarea

Multi-line text entry for notes, messages, and descriptions.

  • Vertical resize by default
  • Character count indicator for max-length fields
Textarea

Max 200 characters.

0/200
Textarea states
ErrorPlease provide at least 10 characters
Disabled

Radio 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 group
Delivery speed

Radio card

Single-select where each option carries more visual weight than a standard radio button. Built on RadioGroup keyboard semantics.

Variants

VariantUse caseIcon size
compactSimple lists (payment method, ID type, coin)32px
expandedComparisons with detail rows (transfer routes, plans)40px
Radio card (compact)
Credit cardVisa, Mastercard, Amex
Bank transferDirect from your bank account
Crypto walletUSDC, USDT, BTC, ETH
Mobile moneyNot available in your region

Radio card variants

Expanded cards include a separator, key-value detail rows, and an optional badge (Cheapest, Fastest, Recommended).

States

StateVisual treatment
Unselected1px border, white background
HoverDarker border, subtle shadow
Focus-visible2px primary border, focus ring
Selected2px primary border, tinted background, filled indicator
DisabledDimmed, 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
Radio card (expanded)
Bank transferArrives in 1-2 business days
Fee$2.99
Exchange rate1 USD = 1,380 KRW
Recipient gets$247.01
Cheapest
Crypto transferArrives in 5-30 minutes
Fee$4.50
NetworkUSDC on Polygon
Recipient gets$245.50
Fastest

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
Search select

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
  • maxDisplay controls chip count before "+N more"
  • max limits total selections
Multi select

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
OTP input
Enter the 6-digit code sent to your phone.

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

StatusVisual treatment
PendingMuted icon, file size
UploadingPrimary icon, progress bar, percentage
CompleteGreen check, success border
ErrorRed alert, error border, message
File uploader — interactive

Drag and drop or browse

PDF, JPG, PNG up to 10 MB

File uploader — status states
passport.pdf65%
x
proof_of_address.pdf
selfie.png
File exceeds 10 MB limit

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
Date picker — interactive
Default
Disabled
Error
Please select a valid date

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

VariantSuffixWhen to use
StaticInputGroupText with currency codeSingle-currency fields (receive amount)
SelectableSelect dropdownMulti-currency fields (send amount)

Sizes

SizeHeightFontUse case
default40px--ds-text-baseStandard form fields
hero3rem--ds-text-2xl, boldPrimary amount entry (send flow)
Currency input
Default
$
C$10 CAD — C$10,000 CAD
Read-only
$
USD
Error
$
CAD
Maximum transfer amount is $10,000.00 CAD
Disabled
$
CAD

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
  • suggestedCountries prop shows a "Suggested" group at the top
Phone input
Default
We will send a verification code
Suggested countries
Error
Enter a valid phone number
Disabled

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.

ScoreLabelWidthColor
1Weak25%red-500
2Fair50%yellow-500
3Good75%accent-500
4Strong100%green-600

Scoring: +1 for 8+ characters, +1 for a digit, +1 for a special character, +1 for 12+ characters with all above met.

Password input
Default
With strength indicator
Use letters, numbers, and symbols
Error
Must be at least 8 characters
Disabled

Masked input

Auto-formatted text entry. Mask characters: 0 = digit, A = letter, * = alphanumeric. Everything else is a literal separator inserted automatically.

Presets

PresetPatternUse case
MASKS.CARD_NUMBER0000 0000 0000 0000Credit/debit card
MASKS.CARD_EXPIRY00/00Card expiry (MM/YY)
MASKS.CVV_30003-digit CVV
MASKS.CVV_400004-digit CVV (Amex)
MASKS.DATE00/00/0000Date (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.

Masked input — Card payment
Card number
Expiry date
CVV
Masked input — States
Error
Enter a complete card number
Disabled
Read-only
Visa

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.

  • FormLabel links to the input via htmlFor
  • FormDescription shows helper text, hidden when an error is active
  • FormMessage shows the error with role="alert"
  • Required fields get an asterisk in the label
Form field — default

As it appears on your ID

Auto-generated, cannot be changed

Form field — error

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".