Date Time Field
A segmented input for typing a date and a time one part at a time.
Installation
Included in poetry-ui — available as
poetry_date_time_field
the moment you've installed Poetry,
with no per-component step. To own the source and edit it, copy it into your app:
bin/rails g poetry:add date-time-field
Default
<%= poetry_date_time_field(name: "event[starts_at]", label: "Starts", value: "2026-07-13T13:05", class: "w-72") %>
With seconds
<%# seconds: adds the seconds segment; the wire value becomes
YYYY-MM-DDTHH:MM:SS. hour_cycle: pins 24-hour editing regardless of
the page locale (omit it and the locale decides). %>
<%= poetry_date_time_field(name: "job[run_at]", label: "Run at", value: "2026-07-13T09:30:15", seconds: true, hour_cycle: "h23", class: "w-72") %>
API
Poetry::Ui::DateTimeField::Component — options are
constructor keywords (the poetry_* helper forwards them);
slots are composed inside the block. Generated from the gem's source documentation.
| Option | Type | Details | Description |
|---|---|---|---|
| hour_cycle: | String | Pins the hour cycle (h12/h23/h11/h24) instead of the locale's. | |
| seconds: | Boolean | defaults to false |
Adds the seconds segment; the wire format becomes YYYY-MM-DDTHH:MM:SS. |
Styling
Every part carries a stable data-slot attribute — target
[data-slot=…] from your own CSS to restyle it. State rides
data attributes on the parts below. This contract is verified against rendered DOM in CI.
| Part | Description |
|---|---|
| [data-slot=date-time-field] | Root - the controller and the enhanced/disabled surface ride here (segments inside share the date-field-* vocabulary) |
| [data-slot=date-time-field-group] | The bordered segment row - hidden until enhancement, then the editing surface (cn-input chrome, focus-within ring) |
| [data-slot=date-time-field-input] | The native <input type=datetime-local> - THE form value in both modes; tabindex -1 + aria-hidden once segments exist |
State attributes
| Part | Attribute | Condition | Values |
|---|---|---|---|
| date-time-field | data-enhanced | the controller connected and built segments (no JS = the native input, visible and styled) | — |
| date-time-field | data-disabled | disabled: is set | — |
| date-time-field | data-invalid | invalid: is set (the group wears the destructive ring) | — |
| date-time-field-group | data-disabled | disabled: is set (chrome dims, pointer events off) | — |
| date-time-field-group | data-invalid | invalid: is set (destructive border + ring) | — |
Wiring
The Stimulus surface each element carries — declared in the component, verified against rendered DOM in CI. Bare actions fire on the element's default event.
| Element | Controller | Wiring |
|---|---|---|
| root | poetry--core--date-field | registers · value locale (if) · value placeholder · value labels · value placeholders |
| root | poetry--core--date-field | value seconds (if seconds) · value hour_cycle (if) |
| group | poetry--core--date-field | focusGap on click · settle on focusout · target group |
| input | poetry--core--date-field | target input |