controls
Input
A single-line text control for names, email addresses, numbers and searches.
CSS onlyPlain classes; no JavaScript in any stack.
Usage
An input needs the component class and one size, inside a field with a label.
<div class="ca-field w-full max-w-sm">
<label class="ca-field__label" for="postcode">Postcode</label>
<input class="ca-input ca-input--md" id="postcode" name="postcode" type="text" autocomplete="postal-code" />
</div>Examples
Sizes
Sizes match the button sizes, so an input and a button line up in a row.
<div class="grid w-full max-w-sm gap-3">
<input class="ca-input ca-input--sm" type="search" aria-label="Search, small" placeholder="Search lessons" />
<input class="ca-input ca-input--md" type="search" aria-label="Search, medium" placeholder="Search lessons" />
<input class="ca-input ca-input--lg" type="search" aria-label="Search, large" placeholder="Search lessons" />
</div>Input types
Use the right type, inputmode and autocomplete, so phones show the right keyboard and browsers can fill values in.
<div class="grid w-full max-w-sm gap-4">
<div class="ca-field">
<label class="ca-field__label" for="phone">Phone number</label>
<input class="ca-input ca-input--md" id="phone" name="phone" type="tel" inputmode="tel" autocomplete="tel" />
</div>
<div class="ca-field">
<label class="ca-field__label" for="lessons">Number of lessons</label>
<input class="ca-input ca-input--md" id="lessons" name="lessons" type="number" inputmode="numeric" min="1" max="40" value="10" />
</div>
</div>Dates and times
Use the native type="date", "time" and "datetime-local". Phones show their own pickers; min, max and step limit the choice.
<div class="grid w-full max-w-sm gap-4">
<div class="ca-field">
<label class="ca-field__label" for="lesson-date">Lesson date</label>
<input class="ca-input ca-input--md" id="lesson-date" name="date" type="date" min="2026-11-10" value="2026-11-24" />
</div>
<div class="ca-field">
<label class="ca-field__label" for="lesson-time">Start time</label>
<input class="ca-input ca-input--md" id="lesson-time" name="time" type="time" min="07:00" max="21:00" step="900" value="09:00" />
</div>
<div class="ca-field">
<label class="ca-field__label" for="exam-moment">Exam</label>
<input class="ca-input ca-input--md" id="exam-moment" name="exam" type="datetime-local" value="2026-12-03T10:30" />
</div>
</div>Disabled
A disabled input cannot be changed or focused. For a value people should still read and copy, prefer readonly.
<div class="ca-field w-full max-w-sm">
<label class="ca-field__label" for="student-number">Student number</label>
<input class="ca-input ca-input--md" id="student-number" name="student-number" type="text" value="S-20481" disabled />
</div>Guidance and accessibility
When to use
- Use an input for short, free text. For one choice out of a few, use radio buttons or a select instead.
- Match the width to the expected value: a postcode field does not need the full row.
Accessibility
- Give every input a visible label. When a design has no room for one, use
aria-label, as in the sizes example, but prefer a visible label. - Inputs stay at 16 pixels on small screens, so iOS does not zoom in on focus.
- Never block pasting, including in password and one-time code fields.
- Dates and times use the native fields: the keyboard, screen readers and
phone pickers work as people expect, in the visitor’s own date format. The
skin’s
color-schemekeeps the picker dark in dark mode. - The core keeps a visible focus ring and styles
aria-invalid="true"in every skin.
Classes
Generated from the component contract. Parts use __, modifiers use --.
| Class | Kind | Use it for |
|---|---|---|
ca-input | Component | Full-width text control with the focus ring and invalid state. |
ca-input--sm | Size | Compact size for toolbars and tables. |
ca-input--md | Size | Default size. |
ca-input--lg | Size | Prominent size for search and sign-up forms. |
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.
Calaca skin
The Calaca UI brand: hueso paper and tinta ink, cempasúchil marigold, rosa and jade.
Proof skin
Pilot skin pushed far from base: square, heavy, offset shadows, larger targets.
Crossview skin
The CrossView proofing table: cool ground, bond-paper sheets, rule-grey hairlines, one red mark.
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>