StableComponent · since 0.1.0
Single-line text entry. Also styles <textarea> and <select>.
Pick this part
Pick c-input for
- One line of free text: a name, an email address, a search query, a number.
- Multi-line text on a
<textarea>, or a choice from many options on a<select>.
Pick another part for
- Choosing among 2 to 6 visible options:
c-radiobuttons read faster than a select. - A yes/no choice:
c-checkbox, orc-togglewhen it applies straight away. - Showing a value that cannot change: plain text, not a read-only input.
Build it
- Start with
<input>and addclass="c-input". - Add
data-state="error"when the value is invalid. Setaria-invalid="true"andaria-describedbypointing at thec-form-field__errormessage. - Add
data-state="success"when the value was validated successfully. - Add
data-state="disabled"when the field cannot be edited. Also set thedisabledattribute.
Show markup 4 lines
<div class="c-form-field">
<label class="c-form-field__label" for="search">Search projects</label>
<input class="c-input" id="search" type="search" placeholder="Name or ID">
</div>
Check your build
Each piece that doesn't fit was run through mcss-lite validate when this page was built. The output below is real.
Fits
Give every input a visible label that stays visible while typing.
Show markup 4 lines
<div class="c-form-field">
<label class="c-form-field__label" for="email">Email address</label>
<input class="c-input" id="email" type="email" autocomplete="email">
</div>
validate: 0 issues
Doesn't fit
Don't use the placeholder as the label: it disappears as soon as someone types.
<input class="c-input" type="email" placeholder="Email address">
validate
- warning This <input> has no label. Add <label for="its-id"> (c-form-field__label). The placeholder "Email address" disappears as soon as someone types, so it can't be the label.
[label-missing]
Fits
Pair the error state with aria-invalid and link the message with aria-describedby.
Enter a start date after 1 January 2020.
Show markup 5 lines
<div class="c-form-field">
<label class="c-form-field__label" for="start">Start date</label>
<input class="c-input" id="start" data-state="error" aria-invalid="true" aria-describedby="start-error">
<p class="c-form-field__error" id="start-error">Enter a start date after 1 January 2020.</p>
</div>
validate: 0 issues
Doesn't fit
Don't show an error with a red border alone.
<input class="c-input" data-state="error">
validate
- warning data-state="error" also needs aria-invalid="true" and aria-describedby pointing at the error message.
[state-pair] - warning This <input> has no label. Add <label for="its-id"> (c-form-field__label).
[label-missing]
Spec sheet
Apply to <input> <textarea> <select>
| State | Meaning | Pair it with |
|---|---|---|
data-state="error" | The value is invalid. Adds a heavier bottom edge so the state does not rely on color. | Set aria-invalid="true" and aria-describedby pointing at the c-form-field__error message. |
data-state="success" | The value was validated successfully. | – |
data-state="disabled" | The field cannot be edited. Rendered ghosted with a dashed keyline. | Also set the disabled attribute. |
Show tokens 8
| Token | Value (light / dark) |
|---|---|
--input-background | #ffffff / #14294d |
--input-border | #1a1d20 / #a9bacb |
--input-border-focus | #005a9c / #2576cc |
--input-text | #1a1d20 / #e6edf4 |
--input-placeholder | #495057 / #a9bacb |
--input-radius | 0.25rem |
--color-focus-ring | #1a1d20 / #f2cd37 |
--color-focus-ring-error | #c91a09 / #f4a9b0 |
Accessibility
- Every input needs a programmatic label: <label for> on
c-form-field__label. - Error text must be linked with aria-describedby, not only shown in red.
| Key | What it does |
|---|---|
| Tab | Moves focus into and out of the field. |
Wording
- Error messages say what went wrong and how to fix it: "Enter a date after 1 January 2020", not "Invalid date".
- Show errors when the person leaves the field or submits, not while they type the first value. Once a field is in error, clear the message as soon as it is fixed.
- Mark the few optional fields with "(optional)" in the label; don't add asterisks to required ones.