Skip to content

Built · v0.1 · Figma set

Input

Inputs are how people hand text to the app: a phone number, an email, a search. There is one field component. It is underlined, not boxed, and everything optional around it (label, icons, helper text, counter) is a toggle rather than a variant. Six variants exist, and every one of them is a state.

DefaultEmailEnter your email
FilledEmailuser@email.com
SuccessEmailuser@email.comEmail verified successfully
ErrorEmailuser@Please enter a valid email address
DisabledEmailEnter your email
ReadOnlyEmailuser@email.com

Every field above is drawn at the dimensions of the built set. Flip the theme (top right) and they move through Light and Navy on tokens alone.

Use when

  • Asking for free-form text or a searchable query.
  • Collecting credentials. Email, password.
  • Anything where the answer is not knowable in advance.

Don’t use when

A vertical stack with a 4 px gap. Only three of its five children are visible by default; the rest are booleans you turn on per screen.

  1. Label. Inter Medium 12 / 16, text/secondary. Toggled by Show Label.
  2. Field. Horizontal row, 40 tall, padding 10 top and bottom, gap 8. Holds the leading icon, the text and the trailing icon.
  3. Underline. A 1 px rectangle, stroke/default. It thickens to 2 px and takes a colour when the field validates.
  4. Helper text. Inter Regular 12 / 16, text/tertiary. Hidden until something needs saying.
  5. Character counter. Inter Regular 11 / 14, right-aligned. Hidden by default.

The 40 px field row is not a typed value: it falls out of the 20 px line-height plus 10 px of padding above and below. The icons are 20 square and sit inside that row, so turning one on never changes the height.

There is one variant property, State, and it carries six values. Everything else is a boolean or a swap, which is why the set is six components and not sixty.

StateUnderlineLabelTextHelper
Defaultstroke/default, 1 pxtext/secondaryplaceholder, text/tertiaryoff
Filledstroke/default, 1 pxtext/secondaryvalue, text/primaryoff
Successfeedback/success, 2 pxtext/secondaryvalueon, feedback/success
Errorfeedback/error, 2 pxtext/secondaryvalueon, feedback/error
Disabledstroke/subtle, 1 pxtext/disabledtext/disabledoff
ReadOnlystroke/subtle, 1 pxtext/secondaryvalueoff

Two things worth reading off that table. Validation is the only thing that thickens the underline, so 2 px means “the field has an opinion about what you typed”. And Disabled and ReadOnly share an underline but not a label: read-only text stays fully legible because it is still information, while disabled text recedes because it is not currently yours to change.

Success is green, and that is the rule working, not breaking it. Green is what is already true, and “email verified” is a fact about something that already happened. It is not asking to be tapped. See Action hierarchy.

Five toggles: Show Label, Show Leading Icon, Show Trailing Icon, Show Helper Text, Show Counter. Combined with six states that is 192 combinations, which is exactly why they are not variants (D-010). Turn on what the screen needs.

Leading icon + counterDisplay nameAlex Rivera11/100
No label, trailing iconSearch contacts

One field per line. Never two side by side, even on wide screens. At the 360 dp floor a half-width field cannot hold an email address without truncating, and a field that truncates what you typed is a field you cannot proofread.

The label stays. Placeholder text is not a label: it disappears the moment someone starts typing, which is exactly when they most need to remember what the field wanted. Turn Show Label off only for a search field, where the icon carries the meaning.

Never colour alone. An error is the underline and the helper text and the trailing icon. Someone who cannot separate red from grey still gets the message, twice.

Helper text is a slot, not an afterthought. Turning it on adds 21 px to the field. Reserve that space in the layout from the start, or every validation message will shove the form down as it appears.

The parity contract. Values resolve per mode (Light / Carbon / Navy).

text/secondary → labeltext/primary → valuetext/tertiary → placeholder, helper, countertext/disabledstroke/default → resting underlinestroke/subtle → disabled, read-onlyfeedback/successfeedback/error

Spacing measured off the set: 4 between label, field, underline and helper; 8 between the icons and the text inside the field row; 10 vertical padding in the row.