Skip to main content
Cayuse Design System Lato · 4pt grid · WCAG 2.1 AA

Patterns

Inputs & Forms

How the input components combine into a form: labelling, required fields, help text, and the states a field moves through. This is the pattern that governs every form in the suite.

Figma source: Inputs ★ ↗

Anatomy of a field

Every field is the same four parts, in the same order. Only the control changes.

The four parts
The federally negotiated rate for this institution. Enter a rate between 0 and 100.
html
<div class="cds-field">
  <!-- 1. Label — always present, always persistent -->
  <label class="cds-field__label" for="rate">
    Indirect cost rate<span class="cds-field__required" aria-hidden="true">*</span>
  </label>

  <!-- 2. Descriptive caption — optional, above the control -->
  <span class="cds-field__caption" id="rate-help">
    The federally negotiated rate for this institution.
  </span>

  <!-- 3. The control -->
  <input class="cds-input" id="rate" type="text"
         aria-describedby="rate-help rate-err" aria-invalid="true">

  <!-- 4. Error message — replaces nothing, appears below -->
  <span class="cds-field__error" id="rate-err">Enter a rate between 0 and 100.</span>
</div>
PartTokenRules
Label--input-label, Label style 14/16 BoldAlways present. 8px above the control — the grid’s label rule.
Required marker--input-requiredA red asterisk, aria-hidden, with the real required attribute carrying the meaning.
Descriptive caption--input-caption, Captions 12/14Optional. Persistent. Bound with aria-describedby.
Error message--input-error-caption, Captions 12/14 BoldAppears below the control. Never replaces the help text.

Labels

The Figma Label property offers three values — Basic, Required and None — and the third needs care.

ValueWhenAccessibility requirement
BasicThe default. A visible label above the control.<label for> bound to the control’s id.
RequiredThe field must be completed to submit.Visible asterisk plus the required attribute. Never the asterisk alone.
NoneOnly where an adjacent element already labels the control — a search field beside a Search button, or a repeated field in a table row where the column header is the label.There must still be an accessible name: a visually hidden <label>, or aria-labelledby pointing at the element that labels it.
“Label: None” means no <em>visible</em> label, never no label

A control with no accessible name is announced as “edit, blank” — the user is told there is a field, and nothing about what goes in it. It is one of the most common and most damaging accessibility failures in form-heavy software, and this suite is form-heavy.

If you set Label to None, you owe the field a hidden label or an aria-labelledby. There is no third option.

Writing labels

Instead ofWriteWhy
PIPrincipal investigatorExpand abbreviations on first use; the label is not the database column.
DateProject start dateSay which date. Forms have several.
Amount ($)Direct costsPut the unit in the field or the help text, not the label.
Enter your project titleProject titleThe label names the thing; it does not instruct.

Required and optional

When to use it

  • Mark required fields with an asterisk and the required attribute.
  • Explain the asterisk once at the top of the form — “Fields marked * are required”.
  • Where most fields are optional, mark the optional ones instead and say so.
  • Only require what genuinely cannot be omitted.

When not to use it

  • Do not mark required fields with colour alone.
  • Do not use the asterisk without also setting required — screen-reader users hear nothing.
  • Do not mark every field required and then let submission proceed anyway.
  • Do not switch marking conventions between forms in the same product.

The Figma description for the Inputs pattern makes the dependency explicit: “Required fields must be completed for the user to complete said section of forms.” That is a section-level rule, which is why the Form Section List shows a required state per section rather than per field.

Field types

The pattern’s Field Type property enumerates nine variants. Several are a Text Input with different validation rather than distinct components — which is worth knowing, because it tells you where the behaviour lives.

Field typeBuilt fromNotes from the file
Basic Text Input FieldText InputThe base case.
ComboboxCombobox, Data Pill“Components used: Search Assisted Entry, Data Pill.”
Date Input FieldText Input + Date Picker“Text Inputs, Date Picker (on click). See documentation on Date & Time.”
Time Input FieldText Input“See documentation on Date & Time.”
Number Input FieldText InputNumeric validation; right-align in tables.
Currency Input FieldText Input“See documentation on Currency.”
Resizable Text AreaText AreaVertical resize only.
CheckboxesCheckboxWrapped in a fieldset with a legend.
Radio ButtonsRadioWrapped in a fieldset with a legend.
Two referenced documents do not exist in this file

The annotations point to “documentation on Date & Time” and “documentation on Currency” for the formatting rules those field types depend on. Neither is a page in the Cayuse DS Figma file, so the rules they describe — date format, time zone handling, currency symbol placement, rounding, negative values — are not written down anywhere this site can reach.

These are exactly the rules that go wrong quietly and expensively in research administration software. Worth locating those documents, or writing them, and linking them here.

Validation

Validation is the part of the pattern with the most ways to go wrong. The rules below hold for every field type.

When to validate

MomentDoDo not
While typingNothing, unless clearing an error the user is actively fixing.Flag an incomplete entry as wrong. The user is not finished.
On blurValidate the field the user just left.Move focus away from where the user went.
On submitValidate everything, summarise, and move focus to the first problem.Rely on the browser’s native prompt.
Error summary plus inline errors
Enter the principal investigator’s name.
The federally negotiated rate for this institution. Enter a rate between 0 and 100.

When to use it

  • Show an error summary at the top listing every problem, each linking to its field.
  • Show the error inline at the field as well — the summary tells the user what is wrong, the inline message tells them where.
  • Say what to do, not what went wrong: “Enter a rate between 0 and 100”, not “Invalid input”.
  • Clear the error the moment the value becomes valid.
  • Keep everything the user already typed.

When not to use it

  • Do not validate on keystroke.
  • Do not use colour alone — the border thickens to 2px and a text message appears.
  • Do not use the browser’s native validation prompt.
  • Do not put the error where the help text was; both should be visible together.
  • Do not disable submit to indicate an invalid form — see Button.
Errors in collapsed or hidden sections

Forms in this suite are split across Tabs and sections. If a hidden field fails validation, the user presses Submit and nothing appears to happen — the error is real but off-screen.

The fix has three parts: mark the section or tab as containing errors, include those fields in the error summary, and reveal the section when the user follows the summary link.

Field states

The pattern’s State property carries eight values — four more than the individual components, because they describe selection and view-only conditions the base components do not model.

StateMeaningWhere it applies
DefaultResting.All
FocusKeyboard or pointer focus.All
DisabledTemporarily unavailable — may become available.All
ErrorFailed validation.All
ResultsA filtered list is showing.Combobox
Single Selected / Multiple SelectedOne or several values chosen.Combobox, Select
View-OnlyPermanently not editable for this user.All
View-only and disabled are different, and the difference matters

Disabled means “not right now” — a dependency is unmet, and the field may become available. View-only means “not for you” — the value is displayed because the user needs to see it, and no interaction will ever change that.

Rendering view-only content as a disabled input is a common mistake with a real cost: disabled controls are removed from the tab order, so a screen-reader user navigating by form field never encounters the value at all. Read-only data should be rendered as text with its label, or as an input with readonly — which stays focusable and announced — not as disabled.

Form layout

When to use it

  • One column. Multi-column forms are misread and skipped, especially when the columns are unrelated.
  • Group related fields, 16px apart, with 24px or more between groups.
  • Order fields the way the user holds the information, not the way the database stores it.
  • Size fields to their content — a postcode field should look like a postcode field.
  • Put the submit action at the end of the form, aligned with its start.

When not to use it

  • Do not place two unrelated fields side by side to save vertical space.
  • Do not use placeholder text instead of labels.
  • Do not scatter required and optional fields randomly; group the required ones where you can.
  • Do not reset the form on error.