+ Companion of TimeField for time ranges
+ ({`{ start, end }`}). Two endpoint inputs share
+ one Label and the same Segment component; soma's
+ TimeRangeField provider creates a separate TimeField context per
+ endpoint so segment editing routes to the correct boundary.
+ Visual chrome is reused 1:1 from time-field.css —
+ the eidos root overlays data-time-field on top of
+ data-time-range-field so the entire size / variant /
+ color cascade applies inside the range without recipe
+ duplication. This recipe only adds the
+ 1fr · auto · 1fr grid layout + em-dash separator.
+
{eidosSnippet}
+ 4 parts: Provider, Label, Input (start/end), Segment.
+ +| Prop | Type | Default | Description |
|---|---|---|---|
| value bindable | TimeRange | null | — | {`{ start, end }`} time pair. |
| placeholder | TimeValue | — | Used to seed segments before any value is set. |
| granularity | 'hour' | 'minute' | 'second' | 'minute' | Smallest segment. |
| hourCycle | 12 | 24 | locale | 12h vs 24h presentation. |
| hideTimeZone | boolean | false | Suppress timezone segment for ZonedDateTime values. |
| minValue · maxValue | TimeValue | — | Validation range applied to BOTH endpoints. |
| disabled · readonly · required | boolean | false | OR-merged with enclosing Field.Provider. |
| locale · dir | BCP47 · 'ltr' | 'rtl' | soma prefs | — |
| size eidos | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Visual size cascade (reuses TimeField tokens). |
| variant eidos | ControlVariant | 'surface' | Input chrome treatment. |
| color eidos | ColorRole | 'primary' | Focus + selection accent. |
| Prop | Type | Default | Description |
|---|---|---|---|
| type | 'start' | 'end' | required | Which endpoint this input represents. |
| name | string | — | Hidden form input name (per endpoint). |
| aria-label | string | — | Override accessible name. |
+ Label sits above the two inputs (grid row 1, full
+ width). Segment is re-exported from
+ TimeField — each endpoint's Input
+ scopes its own TimeField context so segment editing routes to
+ the right endpoint without ambiguity.
+
Source: src/uix/morfo/components/time-range-field.ts.
| Field | Value |
|---|---|
| name | "{timeRangeFieldMorfo.name}" |
| kebab | "{timeRangeFieldMorfo.kebab}" |
| parts.length | {timeRangeFieldMorfo.parts.length} |
| events.length | {events.length} |
| Part | Marker | Element | Role | Archetype | States | Optional |
|---|---|---|---|---|---|---|
| {part.kebab} | +[{part.marker}] |
+ <{part.defaultElement}> | +{part.role ?? '—'} | +{part.archetype ?? '—'} | +{part.states.length ? part.states.join(' | ') : '—'} | +{part.optional ? 'yes' : 'no'} | +
Events fire on segment commit (per endpoint).
+ +| Name | Family | Verb | Sequence | Intent |
|---|---|---|---|---|
| {action.name} | +{sem.family} | +{sem.verb ?? '—'} | +{sem.sequence ?? 'pre'} | +{intentStr} | +
+ Layout-only at src/uix/eidos/components/time-range-field/time-range-field.css.
+ Chrome on each endpoint Input comes from time-field.css because the
+ eidos root overlays data-time-field="" on top of
+ data-time-range-field — the entire size / variant / color cascade
+ applies inside the range without duplicating any rules.
+
| Selector | Source | What it paints |
|---|---|---|
| [data-time-range-field][data-time-field] | eidos | Grid wrapper (1fr · auto · 1fr). |
| [data-time-range-field-label] | morfo | Label spanning full row. |
| [data-time-range-field-input][data-endpoint='start' | 'end'] | morfo | Endpoint container — grid columns 1 / 3. |
| [data-time-range-field]::before | eidos | Em-dash separator in middle column. |
| [data-time-field-input], [data-time-field-segment] | eidos | Inherited from time-field.css — each endpoint paints like a standalone TimeField. |
+ Same ARIA contract as TimeField, applied per endpoint. Each
+ segment is a role="spinbutton" with
+ aria-valuemin / aria-valuemax /
+ aria-valuenow driven by the resolved value;
+ Tab moves across segments AND across the start↔end boundary.
+
| Key | Action |
|---|---|
| ArrowUp / ArrowDown | Increment / decrement the focused segment. |
| ArrowLeft / ArrowRight | Move focus to previous / next segment (crosses start↔end). |
| Home / End | First / last editable segment of the focused endpoint. |
| Digit | Type to fill the segment; auto-advances on overflow. |
| Backspace | Clear digit-by-digit. |
| Tab | Advance focus across endpoint segments. |