Previews

No matching results.

Pages

No matching results.

x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8">
<!-- Introductory callout -->
<div class="tw-callout">
<p class="tw:mb-1 tw:text-sm tw:font-mono">
<strong>DATE PICKER:</strong> Calendar overlay for a single date or a range<br>
<strong>MODES:</strong> Single | Range (with presets) | Bounded (min/max)
</p>
<p class="tw:mb-0 tw:text-sm">
The product does not use <code>input[type="date"]</code> — 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 <code>date_picker_controller.js</code>.
</p>
</div>
<!-- Single date -->
<div class="tw:border-t tw:pt-6">
<h2 class="tw-h4 tw:mb-4">Single Date</h2>
<div class="tw-callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Default mode.</strong> The field shows a readable date and keeps the machine-readable
<code>yyyy-mm-dd</code> in <code>data-value</code>. 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.
</p>
</div>
<div class="tw:max-w-xs" data-controller="date-picker" data-action="keydown->date-picker#keydown">
<label for="dpSingle" class="tw-form-label">Interview date</label>
<div class="tw-date-picker">
<div class="tw-input-group tw-has-icon-end">
<input type="text" id="dpSingle" class="tw-form-control" placeholder="dd/mm/yyyy or pick a date"
autocomplete="off" role="combobox" aria-expanded="false"
data-date-picker-target="input" data-action="click->date-picker#toggle input->date-picker#typed">
<i class="tw-input-group-icon tw-input-group-icon-end tw-input-group-icon-clickable fa-regular fa-calendar"
data-action="click->date-picker#toggle"></i>
</div>
<div class="tw-date-picker-panel" data-date-picker-target="panel" role="dialog" aria-label="Choose a date">
<div class="tw-date-picker-header">
<button type="button" class="tw-date-picker-nav" aria-label="Previous month" data-action="click->date-picker#prevMonth">
<i class="fa-solid fa-chevron-left"></i>
</button>
<span class="tw-date-picker-title" data-date-picker-target="title" aria-live="polite"></span>
<button type="button" class="tw-date-picker-nav" aria-label="Next month" data-action="click->date-picker#nextMonth">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="tw-date-picker-grid" role="grid" data-date-picker-target="grid"></div>
<div class="tw-date-picker-footer">
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#today">Today</button>
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#clear">Clear</button>
</div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div data-controller="date-picker"><div class="tw-date-picker">field + .tw-date-picker-panel</div></div></code>
</div>
</div>
<!-- Range -->
<div class="tw:border-t tw:pt-6">
<h2 class="tw-h4 tw:mb-4">Date Range (With Presets)</h2>
<div class="tw-callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Range mode:</strong> <code>data-date-picker-mode-value="range"</code>. 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.
</p>
</div>
<div class="tw:max-w-sm"
data-controller="date-picker"
data-date-picker-mode-value="range"
data-action="keydown->date-picker#keydown">
<label for="dpRange" class="tw-form-label">Submitted between</label>
<div class="tw-date-picker">
<div class="tw-input-group tw-has-icon-end">
<input type="text" id="dpRange" class="tw-form-control" placeholder="Choose a date range"
readonly autocomplete="off" role="combobox" aria-expanded="false"
data-date-picker-target="input" data-action="click->date-picker#toggle">
<i class="tw-input-group-icon tw-input-group-icon-end tw-input-group-icon-clickable fa-regular fa-calendar"
data-action="click->date-picker#toggle"></i>
</div>
<input type="hidden" data-date-picker-target="startInput">
<input type="hidden" data-date-picker-target="endInput">
<div class="tw-date-picker-panel" data-date-picker-target="panel" role="dialog" aria-label="Choose a date range">
<div class="tw-date-picker-body">
<div class="tw-date-picker-presets">
<button type="button" class="tw-date-picker-preset" data-days="7" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">Last 7 days</button>
<button type="button" class="tw-date-picker-preset" data-days="30" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">Last 30 days</button>
<button type="button" class="tw-date-picker-preset" data-days="90" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">Last 90 days</button>
<button type="button" class="tw-date-picker-preset" data-start="2026-09-01" data-end="2027-08-31" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">2026/27 year</button>
</div>
<div class="tw:flex-1">
<div class="tw-date-picker-header">
<button type="button" class="tw-date-picker-nav" aria-label="Previous month" data-action="click->date-picker#prevMonth">
<i class="fa-solid fa-chevron-left"></i>
</button>
<span class="tw-date-picker-title" data-date-picker-target="title" aria-live="polite"></span>
<button type="button" class="tw-date-picker-nav" aria-label="Next month" data-action="click->date-picker#nextMonth">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="tw-date-picker-grid" role="grid" data-date-picker-target="grid"></div>
</div>
</div>
<div class="tw-date-picker-footer">
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#today">Today</button>
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#clear">Clear</button>
</div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code>data-date-picker-mode-value="range" + .tw-date-picker-presets with data-days or data-start/data-end</code>
</div>
</div>
<!-- Bounded -->
<div class="tw:border-t tw:pt-6">
<h2 class="tw-h4 tw:mb-4">Bounded Range (Min / Max)</h2>
<div class="tw-callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Out-of-bounds days are disabled, not hidden</strong> — 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 <code>data-date-picker-min-value</code> / <code>-max-value</code>.
</p>
</div>
<div class="tw:max-w-xs"
data-controller="date-picker"
data-date-picker-min-value="2026-08-10"
data-date-picker-max-value="2026-08-28"
data-action="keydown->date-picker#keydown">
<label for="dpBounded" class="tw-form-label">Open day slot</label>
<p id="dpBoundedHelp" class="tw-form-text">Open days run from 10 to 28 August.</p>
<div class="tw-date-picker">
<div class="tw-input-group tw-has-icon-end">
<input type="text" id="dpBounded" class="tw-form-control" placeholder="Choose a date"
readonly autocomplete="off" role="combobox" aria-expanded="false"
aria-describedby="dpBoundedHelp"
data-date-picker-target="input" data-action="click->date-picker#toggle">
<i class="tw-input-group-icon tw-input-group-icon-end tw-input-group-icon-clickable fa-regular fa-calendar"
data-action="click->date-picker#toggle"></i>
</div>
<div class="tw-date-picker-panel" data-date-picker-target="panel" role="dialog" aria-label="Choose an open day">
<div class="tw-date-picker-header">
<button type="button" class="tw-date-picker-nav" aria-label="Previous month" data-action="click->date-picker#prevMonth">
<i class="fa-solid fa-chevron-left"></i>
</button>
<span class="tw-date-picker-title" data-date-picker-target="title" aria-live="polite"></span>
<button type="button" class="tw-date-picker-nav" aria-label="Next month" data-action="click->date-picker#nextMonth">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="tw-date-picker-grid" role="grid" data-date-picker-target="grid"></div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code>data-date-picker-min-value="2026-08-10" data-date-picker-max-value="2026-08-28"</code>
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8">
<!-- Introductory callout -->
<div class="tw-callout">
<p class="tw:mb-1 tw:text-sm tw:font-mono">
<strong>DATE PICKER:</strong> Calendar overlay for a single date or a range<br>
<strong>MODES:</strong> Single | Range (with presets) | Bounded (min/max)
</p>
<p class="tw:mb-0 tw:text-sm">
The product does not use <code>input[type="date"]</code> — 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 <code>date_picker_controller.js</code>.
</p>
</div>
<!-- Single date -->
<div class="tw:border-t tw:pt-6">
<h2 class="tw-h4 tw:mb-4">Single Date</h2>
<div class="tw-callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Default mode.</strong> The field shows a readable date and keeps the machine-readable
<code>yyyy-mm-dd</code> in <code>data-value</code>. 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.
</p>
</div>
<div class="tw:max-w-xs" data-controller="date-picker" data-action="keydown->date-picker#keydown">
<label for="dpSingle" class="tw-form-label">Interview date</label>
<div class="tw-date-picker">
<div class="tw-input-group tw-has-icon-end">
<input type="text" id="dpSingle" class="tw-form-control" placeholder="dd/mm/yyyy or pick a date"
autocomplete="off" role="combobox" aria-expanded="false"
data-date-picker-target="input" data-action="click->date-picker#toggle input->date-picker#typed">
<i class="tw-input-group-icon tw-input-group-icon-end tw-input-group-icon-clickable fa-regular fa-calendar"
data-action="click->date-picker#toggle"></i>
</div>
<div class="tw-date-picker-panel" data-date-picker-target="panel" role="dialog" aria-label="Choose a date">
<div class="tw-date-picker-header">
<button type="button" class="tw-date-picker-nav" aria-label="Previous month" data-action="click->date-picker#prevMonth">
<i class="fa-solid fa-chevron-left"></i>
</button>
<span class="tw-date-picker-title" data-date-picker-target="title" aria-live="polite"></span>
<button type="button" class="tw-date-picker-nav" aria-label="Next month" data-action="click->date-picker#nextMonth">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="tw-date-picker-grid" role="grid" data-date-picker-target="grid"></div>
<div class="tw-date-picker-footer">
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#today">Today</button>
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#clear">Clear</button>
</div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div data-controller="date-picker"><div class="tw-date-picker">field + .tw-date-picker-panel</div></div></code>
</div>
</div>
<!-- Range -->
<div class="tw:border-t tw:pt-6">
<h2 class="tw-h4 tw:mb-4">Date Range (With Presets)</h2>
<div class="tw-callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Range mode:</strong> <code>data-date-picker-mode-value="range"</code>. 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.
</p>
</div>
<div class="tw:max-w-sm"
data-controller="date-picker"
data-date-picker-mode-value="range"
data-action="keydown->date-picker#keydown">
<label for="dpRange" class="tw-form-label">Submitted between</label>
<div class="tw-date-picker">
<div class="tw-input-group tw-has-icon-end">
<input type="text" id="dpRange" class="tw-form-control" placeholder="Choose a date range"
readonly autocomplete="off" role="combobox" aria-expanded="false"
data-date-picker-target="input" data-action="click->date-picker#toggle">
<i class="tw-input-group-icon tw-input-group-icon-end tw-input-group-icon-clickable fa-regular fa-calendar"
data-action="click->date-picker#toggle"></i>
</div>
<input type="hidden" data-date-picker-target="startInput">
<input type="hidden" data-date-picker-target="endInput">
<div class="tw-date-picker-panel" data-date-picker-target="panel" role="dialog" aria-label="Choose a date range">
<div class="tw-date-picker-body">
<div class="tw-date-picker-presets">
<button type="button" class="tw-date-picker-preset" data-days="7" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">Last 7 days</button>
<button type="button" class="tw-date-picker-preset" data-days="30" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">Last 30 days</button>
<button type="button" class="tw-date-picker-preset" data-days="90" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">Last 90 days</button>
<button type="button" class="tw-date-picker-preset" data-start="2026-09-01" data-end="2027-08-31" data-date-picker-target="preset" data-action="click->date-picker#applyPreset">2026/27 year</button>
</div>
<div class="tw:flex-1">
<div class="tw-date-picker-header">
<button type="button" class="tw-date-picker-nav" aria-label="Previous month" data-action="click->date-picker#prevMonth">
<i class="fa-solid fa-chevron-left"></i>
</button>
<span class="tw-date-picker-title" data-date-picker-target="title" aria-live="polite"></span>
<button type="button" class="tw-date-picker-nav" aria-label="Next month" data-action="click->date-picker#nextMonth">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="tw-date-picker-grid" role="grid" data-date-picker-target="grid"></div>
</div>
</div>
<div class="tw-date-picker-footer">
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#today">Today</button>
<button type="button" class="tw-btn tw-btn-tertiary tw-btn-sm" data-action="click->date-picker#clear">Clear</button>
</div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code>data-date-picker-mode-value="range" + .tw-date-picker-presets with data-days or data-start/data-end</code>
</div>
</div>
<!-- Bounded -->
<div class="tw:border-t tw:pt-6">
<h2 class="tw-h4 tw:mb-4">Bounded Range (Min / Max)</h2>
<div class="tw-callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Out-of-bounds days are disabled, not hidden</strong> — 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 <code>data-date-picker-min-value</code> / <code>-max-value</code>.
</p>
</div>
<div class="tw:max-w-xs"
data-controller="date-picker"
data-date-picker-min-value="2026-08-10"
data-date-picker-max-value="2026-08-28"
data-action="keydown->date-picker#keydown">
<label for="dpBounded" class="tw-form-label">Open day slot</label>
<p id="dpBoundedHelp" class="tw-form-text">Open days run from 10 to 28 August.</p>
<div class="tw-date-picker">
<div class="tw-input-group tw-has-icon-end">
<input type="text" id="dpBounded" class="tw-form-control" placeholder="Choose a date"
readonly autocomplete="off" role="combobox" aria-expanded="false"
aria-describedby="dpBoundedHelp"
data-date-picker-target="input" data-action="click->date-picker#toggle">
<i class="tw-input-group-icon tw-input-group-icon-end tw-input-group-icon-clickable fa-regular fa-calendar"
data-action="click->date-picker#toggle"></i>
</div>
<div class="tw-date-picker-panel" data-date-picker-target="panel" role="dialog" aria-label="Choose an open day">
<div class="tw-date-picker-header">
<button type="button" class="tw-date-picker-nav" aria-label="Previous month" data-action="click->date-picker#prevMonth">
<i class="fa-solid fa-chevron-left"></i>
</button>
<span class="tw-date-picker-title" data-date-picker-target="title" aria-live="polite"></span>
<button type="button" class="tw-date-picker-nav" aria-label="Next month" data-action="click->date-picker#nextMonth">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
<div class="tw-date-picker-grid" role="grid" data-date-picker-target="grid"></div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code>data-date-picker-min-value="2026-08-10" data-date-picker-max-value="2026-08-28"</code>
</div>
</div>
</div>