Date Range Field
Segmented date range input.
Usage
value is { start, end }, and you render two Inputs — one type="start" and one type="end". type is required; there is no single
input that holds a range.
Put the visual separator between them yourself and mark it aria-hidden — a dash read aloud between two dates adds nothing.
You must name the Root
Bits gives the range Root role="group" with no accessible name. Without your help the field announces as an anonymous
group.
Verified in the rendered DOM: Bits points each Input's aria-labelledby at your Label, but the Inputs carry no role — so
nothing exposed to assistive technology ends up labelled. On the single-value Date Field the Input is the group and Bits does label
it, so this gap is specific to ranges.
Pass aria-labelledby pointing at your Label's id, or aria-label. Both reach the root element, and both directions are
asserted in the tests so this cannot regress quietly.
Props
DateRangeField.Root — value and placeholder are bindable.
| Prop | Type | Default |
|---|---|---|
value The date value range. Bindable. A `DateValue`, not a JS `Date`. | { start: DateValue | undefined; end: DateValue | undefined } | — |
onValueChange Called when the value changes. | (value: FieldValue) => void | — |
placeholder Which date the empty segments are formatted from. Bindable. | DateValue | — |
minValue Earliest accepted value. | DateValue | — |
maxValue Latest accepted value. | DateValue | — |
granularity Smallest unit the user can edit, which decides which segments appear. `day` gives a plain date; `minute` adds time segments. | 'day' | 'hour' | 'minute' | 'second' | 'day' |
locale BCP-47 locale. It decides the SEGMENT ORDER — month/day/year versus day/month/year — so getting it wrong does not just relabel the field, it rearranges it. Pass the user's locale. | string | 'en' |
name Name for form submission; Bits renders a hidden input. | string | — |
required | boolean | false |
disabled | boolean | false |
readonly | boolean | false |
validate Return a message to mark the value invalid. Bits then sets `data-invalid` and wires `aria-invalid` on the segments. | (value: never) => string | string[] | void | — |
class Extra classes merged onto the root. | string | — |
children | Snippet | — |
Input takes a required type of "start" or "end". Label and Segment take class plus their native attributes.