Date Picker
A Popover with a Calendar inside. There is no
Ui::DatePickerComponent:
you put the two together yourself.
Installation
Shadwire follows shadcn/ui's open code model: the component's source is copied into your application and becomes yours. Install it with the CLI:
The date-picker registry item installs these files:
-
app/components/ui_component.rb -
app/javascript/controllers/ui_date_picker_controller.js -
vendor/shadwire/shadwire.css
This component uses Stimulus, so the application needs importmap-rails and stimulus-rails with automatic controller loading.
Haven't installed the CLI yet? gem install shadwire, then shadwire init.
Usage
ui_calendar holds the value:
it writes the chosen date into a hidden input (name:)
and fires ui-calendar:change.
The ui-date-picker controller listens for that event,
shows the formatted date on the trigger and closes the popover. It only handles display:
without it the picker still works, but the trigger never shows what was chosen.
The popover needs w-auto! p-0!, because its default
w-72 and padding leave too little room for the calendar.
In Tailwind v4 the ! goes at the end of the class.
Composition
Examples
The eight arrangements shadcn/ui documents, translated into ViewComponent + Stimulus.
Default
A button that opens the calendar in a popover and then shows the chosen date.
With a label
The same trigger inside a Field, tied to the label by id.
Range
Two dates in one trigger. The popover closes after the second date is picked, not the first.
Date of birth
Month and year selects in the caption, and max: today, since nobody is born in the future.
With a text field
Type a date or pick one in the calendar. What you type is parsed, and the field then shows the date formatted. ↓ opens the popover.
Date and time
The picker sets the day and a native input type="time" sets the time.
Natural language
Understands "today", "tomorrow", "in 2 weeks" and "next friday". The list of phrases is in the controller, so you can add your own.
Your post goes out on .
RTL
dir: :rtl mirrors the grid, the arrows and the ←/→ keys; month_names:/day_names: translate the caption.
API reference
What the calendar accepts is documented under Calendar.
The table below only covers the controller that connects the two: the
data-* attributes on the element that wraps the popover and the field.
| Attribute | Default | Description |
|---|---|---|
format-value |
long |
full, long, medium, short or iso. |
locale-value |
— | BCP 47 (pt-BR, ar-EG). Empty follows the browser's language. |
separator-value |
– |
What separates the two ends of a range in the label. |
date-order-value |
dmy |
How to read 01/06/2026 as you type. mdy for the US order. |
close-on-select-value |
true |
Closes the popover on selection. With mode: :range, only once the second date lands. |
natural-language-value |
false |
Accepts relative phrases (“tomorrow”, “in 2 weeks”, “next friday”) in the text field. |
target="label" |
— | The element whose text becomes the chosen date; it gets data-empty while empty. |
target="input" |
— | An editable text field: what you type is parsed, and ↓ opens the popover. |
target="preview" |
— | An optional echo of the parsed date, for a supporting line below the field. |