🍙 Onigiri

The Crunchyroll design system, rendered live from its own tokens and components. It cannot drift from what ships.

Docs draft

Input

When to use it

useSingle-line text entry: email, username, list names.
avoidPasswords — the show toggle and meter are its own anatomy. password-input
avoidSearch — the header bar at display scale with its own affordances. search-input

Anatomy

floating label — Starts in-field at body-lg in color.text.entry — white on dark, exactly the old Forms page — and floats to caption in color.text.secondary. It IS the placeholder; there is no separate placeholder prop.

value — type.body-lg.

trailing control slot — Optional (clear, show); boolean + swap in Figma, ReactNode in code.

underline — 2px; the only state-bearing boundary.

States

empty — No value entered yet.

focus — Holds keyboard focus and shows the focus ring.

filled — Holds an entered value.

error — Signals a failed or invalid value.

read only — Value shown but not editable.

disabled — Not interactive; rendered with the lifted disabled tokens so it stays perceivable.

Guidelines

mustThe error message never replaces the label; it renders in FormField's message row. — The old pattern swapped the label for the message, destroying which field was erroring. Deliberate deviation, ruled at rebuild.
mustFocus underline uses color.accent.text, never raw brand orange. — Orange is 2.7:1 on cream — below the 3:1 UI floor for the only focus indicator.

API

PropTypeDescription
labelstringFloating label and accessible name.
trailingReactNodeTrailing adornment rendered inside the field.
...restInputHTMLAttributes minus placeholderaria-invalid drives the error state; readOnly and disabled are native.

Design specifications

widthfills its container; Figma shows 400
valuetype.body-lg in color.text.entry — entered text reads white on dark, one step brighter than reading text (Robin's ruling)
label-floatedtype.caption
label-colorcolor.text.secondary
underline-restcolor.border.strong
underline-focuscolor.accent.text
underline-errorcolor.text.negative
underline-quietcolor.border.subtle (read-only, disabled)
value-read-onlycolor.text.secondary
value-disabledcolor.text.disabled

Accessibility

Tab — Native focus; the underline color change plus caret are the indicators.

color.border.strong on color.bg.primary — Contracted at ≥ 3:1 by the build gate.

color.accent.text on color.bg.primary — Contracted at ≥ 4.5:1 by the build gate.

Label wraps the native input, so the floating label is the accessible name. Error pairs aria-invalid with a FormField message and aria-describedby.