DATE PICKER: Calendar overlay for a single date or a range
MODES: Single | Range (with presets) | Bounded (min/max)
The product does not use input[type="date"] — the native control renders and behaves
differently in every browser, and its calendar can't be styled. This is the widget the product
actually uses. Requires date_picker_controller.js.
Default mode. The field shows a readable date and keeps the machine-readable
yyyy-mm-dd in data-value. Today carries a ring rather than a fill,
so it stays visible when another day is selected. Escape closes and returns focus to the field.
<div data-controller="date-picker">…<div class="tw-date-picker">field + .tw-date-picker-panel</div></div>
Range mode: data-date-picker-mode-value="range". The first click
starts the range, the second closes it, and clicking before the start restarts rather than
producing a backwards range. Presets are why most range pickers exist — “Last 7 days” is one
click instead of two calendar hunts.
data-date-picker-mode-value="range" + .tw-date-picker-presets with data-days or data-start/data-end
Out-of-bounds days are disabled, not hidden — a family looking for a closed
date needs to see that it exists and is unavailable, not wonder whether the calendar is broken.
Set with data-date-picker-min-value / -max-value.
Open days run from 10 to 28 August.
data-date-picker-min-value="2026-08-10" data-date-picker-max-value="2026-08-28"