controls
Date range
Two native date fields for a period, such as a holiday or a report.
Native behaviorUses built-in HTML behavior, so you write no script.
Usage
A fieldset with a start and an end field, marked with data-ca-range. The end cannot be before the start.
<fieldset class="ca-date-range w-full max-w-md">
<legend class="ca-field__label">Holiday, no lessons</legend>
<div class="ca-date-range__fields">
<label class="ca-date-range__field">
From
<input class="ca-input ca-input--md" type="date" name="from" data-ca-range="start" min="2026-11-10" value="2026-12-21" />
</label>
<span class="ca-date-range__separator" aria-hidden="true">–</span>
<label class="ca-date-range__field">
Until
<input class="ca-input ca-input--md" type="date" name="until" data-ca-range="end" value="2027-01-03" />
</label>
</div>
</fieldset>Examples
With a hint
Connect a hint to the whole range with aria-describedby on the fieldset.
<fieldset class="ca-date-range w-full max-w-md" aria-describedby="report-hint">
<legend class="ca-field__label">Report period</legend>
<p class="ca-field__hint" id="report-hint">Up to one year. The end moves along when you pick a later start.</p>
<div class="ca-date-range__fields">
<label class="ca-date-range__field">
From
<input class="ca-input ca-input--md" type="date" name="report-from" data-ca-range="start" value="2026-01-01" />
</label>
<span class="ca-date-range__separator" aria-hidden="true">–</span>
<label class="ca-date-range__field">
Until
<input class="ca-input ca-input--md" type="date" name="report-until" data-ca-range="end" value="2026-06-30" />
</label>
</div>
</fieldset>Guidance and accessibility
When to use
- Use a date range for a period with a start and an end, such as a holiday or the dates of a report.
- For one date, use a single date input.
Accessibility
- Both fields are native date inputs with their own visible label, so phones show their pickers and screen readers read “From” and “Until”.
- The
<legend>names the period and is read with each field. ca-date-range.jssetsminon the end andmaxon the start, so pickers only offer valid dates; a start after the end moves the end along.- Check the range on the server too.
Classes
Generated from the component contract. Parts use __, modifiers use --.
| Class | Kind | Use it for |
|---|---|---|
ca-date-range | Component | The <fieldset> around the two fields. |
ca-date-range__fields | Part | The row with both fields; it stacks when narrow. |
ca-date-range__field | Part | A <label> with its date input. |
ca-date-range__separator | Part | The dash between the fields; decoration. |
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>Load the date range script once per page; it keeps every range's end on or after its start. In Astro or Next.js, import @calaca/ui/behavior/date-range once in the layout.
<script type="module" src="ca-date-range.js"></script>