controls
Field
Wraps a form control with its label, a hint and an error message.
CSS onlyPlain classes; no JavaScript in any stack.
Usage
A field holds a label, a control and optionally a hint. Connect them with for, id and aria-describedby.
As it appears on your driving licence.
<div class="ca-field w-full max-w-sm">
<label class="ca-field__label" for="full-name">Full name</label>
<input class="ca-input ca-input--md" id="full-name" name="name" type="text" autocomplete="name" aria-describedby="full-name-hint" />
<p class="ca-field__hint" id="full-name-hint">As it appears on your driving licence.</p>
</div>Examples
With an error
Mark the control with aria-invalid="true" and point aria-describedby at the error message.
Enter an email address like name@example.com.
<div class="ca-field w-full max-w-sm">
<label class="ca-field__label" for="email">Email address</label>
<input class="ca-input ca-input--md" id="email" name="email" type="email" inputmode="email" autocomplete="email" value="anna@" aria-invalid="true" aria-describedby="email-error" />
<p class="ca-field__error" id="email-error">Enter an email address like name@example.com.</p>
</div>With a text area
The input classes also style a <textarea>; give it a minimum height.
Optional. Your instructor reads this before the lesson.
<div class="ca-field w-full max-w-sm">
<label class="ca-field__label" for="notes">Notes for your instructor</label>
<textarea class="ca-input ca-input--md h-auto min-h-24 py-2" id="notes" name="notes" rows="3" aria-describedby="notes-hint"></textarea>
<p class="ca-field__hint" id="notes-hint">Optional. Your instructor reads this before the lesson.</p>
</div>Guidance and accessibility
When to use
- Use a field around every form control that needs a label, a hint or an error.
- Put format help in the hint before people type, not only in the error afterwards.
- Write errors that say how to fix the value: “Enter an email address like name@example.com”, not “Invalid input”.
Accessibility
- Every control needs a visible
<label>connected withforandid. A placeholder is not a label. - Connect hints and errors with
aria-describedby, so screen readers read them with the label. - On submit, set
aria-invalid="true"on invalid controls, show the error and move focus to the first invalid control. Keep the submit button enabled.
Classes
Generated from the component contract. Parts use __, modifiers use --.
| Class | Kind | Use it for |
|---|---|---|
ca-field | Component | One-column stack of label, control, hint and error. |
ca-field__label | Part | The visible label of the control. |
ca-field__hint | Part | Help text that stays visible, such as a format. |
ca-field__error | Part | Error message, shown when the value is invalid. |
Skins
The same markup, dressed by each skin. Structure and behavior stay the same; only the look changes.
Base skin
Neutral grayscale starting point; product skins extend it and change what differs.
As it appears on your driving licence.
Calaca skin
The Calaca UI brand: hueso paper and tinta ink, cempasúchil marigold, rosa and jade.
As it appears on your driving licence.
Proof skin
Pilot skin pushed far from base: square, heavy, offset shadows, larger targets.
As it appears on your driving licence.
Crossview skin
The CrossView proofing table: cool ground, bond-paper sheets, rule-grey hairlines, one red mark.
As it appears on your driving licence.
Framework notes
Link the prebuilt stylesheet of your skin next to your brand theme. No build step.
<link rel="stylesheet" href="theme.css" />
<link rel="stylesheet" href="ca-base.css" />In Astro, Vite and other Tailwind projects, import Calaca after Tailwind and your theme in your main stylesheet.
@import "tailwindcss";
@import "./theme.css";
@import "@calaca/ui/core.css";
@import "@calaca/ui/skins/base.css";Same stylesheet as above; write the classes in className.
<button className="ca-button ca-button--primary ca-button--md" type="button">Save changes</button>