material-inspired-component-library 9.1.1 → 9.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/appbar/index.scss +1 -1
- package/components/badge/README.md +43 -12
- package/components/badge/index.scss +15 -21
- package/components/bottomsheet/README.md +53 -22
- package/components/bottomsheet/index.scss +61 -44
- package/components/button/_shared.scss +6 -6
- package/components/card/README.md +1 -1
- package/components/checkbox/index.scss +10 -10
- package/components/datepicker/README.md +184 -59
- package/components/datepicker/index.scss +84 -20
- package/components/dialog/README.md +151 -56
- package/components/dialog/index.scss +50 -62
- package/components/iconbutton/index.scss +5 -5
- package/components/list/index.scss +6 -6
- package/components/menu/index.scss +13 -13
- package/components/navigationbar/index.scss +7 -1
- package/components/navigationrail/index.scss +27 -22
- package/components/radio/index.scss +8 -8
- package/components/select/index.scss +3 -3
- package/components/sidesheet/README.md +90 -37
- package/components/sidesheet/index.scss +51 -41
- package/components/slider/README.md +35 -9
- package/components/slider/index.scss +182 -153
- package/components/snackbar/README.md +43 -25
- package/components/snackbar/index.scss +22 -27
- package/components/stepper/index.scss +4 -4
- package/components/switch/index.scss +13 -13
- package/components/timepicker/README.md +131 -55
- package/components/timepicker/index.scss +46 -25
- package/dist/appbar.css +1 -1
- package/dist/badge.css +1 -1
- package/dist/bottomsheet.css +1 -1
- package/dist/bottomsheet.js +1 -1
- package/dist/button.css +1 -1
- package/dist/checkbox.css +1 -1
- package/dist/chip.css +1 -1
- package/dist/datepicker.css +1 -1
- package/dist/datepicker.js +1 -1
- package/dist/dialog.css +1 -1
- package/dist/iconbutton.css +1 -1
- package/dist/layout.css +1 -1
- package/dist/list.css +1 -1
- package/dist/menu.css +1 -1
- package/dist/micl.css +1 -1
- package/dist/micl.js +1 -1
- package/dist/navigationbar.css +1 -1
- package/dist/navigationrail.css +1 -1
- package/dist/radio.css +1 -1
- package/dist/select.css +1 -1
- package/dist/sidesheet.css +1 -1
- package/dist/slider.css +1 -1
- package/dist/slider.js +1 -1
- package/dist/snackbar.css +1 -1
- package/dist/snackbar.js +1 -1
- package/dist/stepper.css +1 -1
- package/dist/switch.css +1 -1
- package/dist/timepicker.css +1 -1
- package/dist/timepicker.js +1 -1
- package/foundations/layout/_tokens.scss +55 -0
- package/foundations/layout/index.scss +2 -35
- package/package.json +1 -1
|
@@ -1,32 +1,60 @@
|
|
|
1
1
|
# Date picker
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
This component implements the [Material Design 3 Expressive Date picker](https://m3.material.io/components/date-pickers/overview) specification. It allows users to select a date using either a text input or a calendar interface.
|
|
3
4
|
|
|
4
5
|
## Basic Usage
|
|
5
6
|
|
|
6
7
|
### HTML
|
|
7
|
-
The Date
|
|
8
|
+
The Date picker component is an extension of the [**Dialog** component](../dialog/README.md). To create a basic date picker, use a `<dialog>` element with both the `micl-dialog` and `micl-datepicker` classes.
|
|
8
9
|
|
|
9
10
|
```HTML
|
|
10
|
-
<dialog
|
|
11
|
+
<dialog
|
|
12
|
+
id="mydatepicker"
|
|
13
|
+
class="micl-dialog micl-datepicker"
|
|
14
|
+
closedby="closerequest"
|
|
15
|
+
aria-labelledby="mysupport"
|
|
16
|
+
>
|
|
11
17
|
<form method="dialog">
|
|
12
18
|
<div class="micl-dialog__headline">
|
|
13
|
-
<h2
|
|
14
|
-
<span class="micl-dialog__supporting-text">Select date</span>
|
|
15
|
-
<button type="button" id="btn"
|
|
19
|
+
<h2>Enter date</h2>
|
|
20
|
+
<span id="mysupport" class="micl-dialog__supporting-text">Select date</span>
|
|
21
|
+
<button type="button" id="btn"
|
|
22
|
+
class="micl-datepicker__inputmode micl-iconbutton-standard-s micl-button--toggle material-symbols-outlined"
|
|
23
|
+
commandfor="btn"
|
|
24
|
+
command="--micl-toggle"
|
|
25
|
+
aria-pressed="false"
|
|
26
|
+
aria-label="Switch between calendar and text input"
|
|
27
|
+
data-miclicon="edit"
|
|
28
|
+
data-micliconselected="calendar_today"
|
|
29
|
+
></button>
|
|
16
30
|
<hr class="micl-divider">
|
|
31
|
+
|
|
17
32
|
<div class="micl-datepicker__month-selector">
|
|
18
|
-
<button type="button"
|
|
33
|
+
<button type="button"
|
|
34
|
+
class="micl-datepicker__previous micl-iconbutton-standard-xs material-symbols-outlined"
|
|
35
|
+
aria-label="Previous month"
|
|
36
|
+
>chevron_backward</button>
|
|
19
37
|
<button type="button" class="micl-datepicker__month micl-button-text-xs">
|
|
20
38
|
<span class="micl-button__icon material-symbols-outlined" aria-hidden="true">arrow_drop_down</span>
|
|
21
39
|
</button>
|
|
22
|
-
<button type="button"
|
|
40
|
+
<button type="button"
|
|
41
|
+
class="micl-datepicker__next micl-iconbutton-standard-xs material-symbols-outlined"
|
|
42
|
+
aria-label="Next month"
|
|
43
|
+
>chevron_forward</button>
|
|
23
44
|
</div>
|
|
45
|
+
|
|
24
46
|
<div class="micl-datepicker__year-selector">
|
|
25
|
-
<button type="button"
|
|
47
|
+
<button type="button"
|
|
48
|
+
class="micl-datepicker__previous micl-iconbutton-standard-xs material-symbols-outlined"
|
|
49
|
+
aria-label="Previous year"
|
|
50
|
+
>chevron_backward</button>
|
|
26
51
|
<button type="button" class="micl-datepicker__year micl-button-text-xs">
|
|
27
52
|
<span class="micl-button__icon material-symbols-outlined" aria-hidden="true">arrow_drop_down</span>
|
|
28
53
|
</button>
|
|
29
|
-
<button type="button"
|
|
54
|
+
<button type="button"
|
|
55
|
+
class="micl-datepicker__next micl-iconbutton-standard-xs material-symbols-outlined"
|
|
56
|
+
aria-label="Next year"
|
|
57
|
+
>chevron_forward</button>
|
|
30
58
|
</div>
|
|
31
59
|
</div>
|
|
32
60
|
|
|
@@ -37,7 +65,8 @@ The Date Picker component is an extension of the [**Dialog** component](../dialo
|
|
|
37
65
|
<div class="micl-datepicker__input micl-textfield-outlined">
|
|
38
66
|
<label for="mydate">Date</label>
|
|
39
67
|
<input type="text" id="mydate">
|
|
40
|
-
|
|
68
|
+
<span class="micl-textfield__supporting-text"></span>
|
|
69
|
+
</div>
|
|
41
70
|
</div>
|
|
42
71
|
|
|
43
72
|
<div class="micl-dialog__actions">
|
|
@@ -49,7 +78,8 @@ The Date Picker component is an extension of the [**Dialog** component](../dialo
|
|
|
49
78
|
```
|
|
50
79
|
|
|
51
80
|
### CSS
|
|
52
|
-
|
|
81
|
+
|
|
82
|
+
Import the required component styles into your project:
|
|
53
83
|
|
|
54
84
|
```CSS
|
|
55
85
|
@use "material-inspired-component-library/dist/dialog";
|
|
@@ -60,77 +90,118 @@ Import both the date picker and the dialog styles into your project:
|
|
|
60
90
|
@use "material-inspired-component-library/dist/datepicker";
|
|
61
91
|
```
|
|
62
92
|
|
|
63
|
-
|
|
93
|
+
Alternatively, import all MICL styles at once:
|
|
94
|
+
|
|
64
95
|
```CSS
|
|
65
96
|
@use "material-inspired-component-library/styles";
|
|
66
97
|
```
|
|
67
98
|
|
|
68
99
|
### JavaScript
|
|
100
|
+
|
|
69
101
|
This component requires JavaScript to function:
|
|
70
102
|
|
|
71
103
|
```JavaScript
|
|
72
104
|
import micl from "material-inspired-component-library/dist/micl";
|
|
73
105
|
```
|
|
74
|
-
When loading individual JavaScript files, also load `dist/textfield` — it wires the input field that opens the picker.
|
|
75
106
|
|
|
76
|
-
|
|
107
|
+
Importing the script initializes all Date picker components on the page, including those dynamically added to the DOM later.
|
|
108
|
+
|
|
109
|
+
If you are loading individual JavaScript files, be sure to also load `dist/textfield` — it wires the input field that triggers the picker.
|
|
77
110
|
|
|
78
111
|
### Live Demo
|
|
79
|
-
A live example of the [Date picker component](https://henkpb.github.io/micl/datepicker.html) is available to interact with.
|
|
80
112
|
|
|
81
|
-
|
|
82
|
-
|
|
113
|
+
A live interactive demo of the [Date picker component](https://henkpb.github.io/micl/datepicker.html) is available.
|
|
114
|
+
|
|
115
|
+
## Anatomy
|
|
83
116
|
|
|
84
|
-
### Date Picker Structure
|
|
85
117
|
For the picker to function, the `micl-dialog__content` area **must** contain the `<div class="micl-datepicker__calendars">` container. This holds the month-based calendars.
|
|
86
118
|
|
|
87
119
|
Additionally, the content area may contain:
|
|
88
120
|
|
|
89
|
-
|
|
121
|
+
* A container for selecting a year: `<div class="micl-datepicker__years">`
|
|
122
|
+
* A container for selecting a month: `<div class="micl-datepicker__months">`
|
|
123
|
+
* A [Text field component](../textfield/README.md) with the `micl-datepicker__input` class for manual date entry.
|
|
90
124
|
|
|
91
|
-
-
|
|
125
|
+
The `micl-dialog__headline` area may contain:
|
|
92
126
|
|
|
93
|
-
|
|
127
|
+
* **Title**: A heading element (e.g., `<h2>`) displaying the selected date. Because its content is dynamically replaced whenever the selection changes, ensure the dialog's `aria-labelledby` attribute points to the supporting label instead.
|
|
128
|
+
* **Supporting label**: A text element with the class `micl-dialog__supporting-text`.
|
|
129
|
+
* **Month selector**: A container with a [Button component](../button/README.md) flanked by two [Icon button components](../iconbutton/README.md):
|
|
130
|
+
* `micl-datepicker__month`: Opens the month selection container.
|
|
131
|
+
* `micl-datepicker__previous`: Navigates to the previous month.
|
|
132
|
+
* `micl-datepicker__next`: Navigates to the next month.
|
|
94
133
|
|
|
95
|
-
The `micl-dialog__headline` area may contain:
|
|
96
134
|
|
|
97
|
-
|
|
135
|
+
* **Year selector**: A container with a [Button component](../button/README.md) flanked by two [Icon button components](../iconbutton/README.md):
|
|
136
|
+
* `micl-datepicker__year`: Opens the year selection container.
|
|
137
|
+
* `micl-datepicker__previous`: Navigates to the previous year.
|
|
138
|
+
* `micl-datepicker__next`: Navigates to the next year.
|
|
98
139
|
|
|
99
|
-
|
|
140
|
+
Any structural item not required for your specific implementation may be omitted.
|
|
100
141
|
|
|
101
|
-
|
|
102
|
-
- `micl-datepicker__month`: Opens the month selection container.
|
|
103
|
-
- `micl-datepicker__previous`: Navigates to the previous month.
|
|
104
|
-
- `micl-datepicker__next`: Navigates to the next month.
|
|
142
|
+
## Variants
|
|
105
143
|
|
|
106
|
-
|
|
107
|
-
- `micl-datepicker__year`: Opens the year selection container.
|
|
108
|
-
- `micl-datepicker__previous`: Navigates to the previous year.
|
|
109
|
-
- `micl-datepicker__next`: Navigates to the next year.
|
|
144
|
+
Because the Date picker relies on the Dialog component, it utilizes the same utility classes for content structure. Refer to the [Dialog component documentation](../dialog/README.md) for structural details.
|
|
110
145
|
|
|
111
|
-
|
|
146
|
+
### Selectable Dates
|
|
147
|
+
|
|
148
|
+
The `min` and `max` attributes of the invoking input field limit the selection. Dates outside this range are rendered in a disabled state; they cannot be selected, navigated to, or typed in. Additionally, calendar navigation arrows will stop at the first and last months containing a selectable date.
|
|
149
|
+
|
|
150
|
+
Days from neighbouring months that pad the first and last weeks of the calendar are displayed in the same disabled state. These elements carry the `micl-datepicker__outside` class, allowing you to hide them completely via CSS if preferred.
|
|
151
|
+
|
|
152
|
+
### Input Mode Switching
|
|
112
153
|
|
|
113
|
-
#### Input Mode Switching
|
|
114
154
|
To allow users to toggle between the calendar view and the manual date input, add an icon button to the `micl-dialog__headline` area:
|
|
115
155
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
156
|
+
* Class: `micl-datepicker__inputmode`
|
|
157
|
+
* Data Attribute: `data-miclicon="edit"` (defines the default icon).
|
|
158
|
+
* Data Attribute: `data-micliconselected="calendar_today"` (defines the toggled icon).
|
|
159
|
+
|
|
160
|
+
Since this is an icon-only button, it requires an `aria-label`. You must also include `aria-pressed="false"`. The self-targeting `--micl-toggle` command will automatically keep this attribute in sync with the active mode.
|
|
161
|
+
|
|
162
|
+
The text field accepts dates in the user's localized format and formats the entry while it is typed. Add a `micl-textfield__supporting-text` element, and the component will automatically populate it with the localized format string (e.g., `DD.MM.YYYY`, `MM/DD/YYYY`) to serve as a hint:
|
|
163
|
+
|
|
164
|
+
```HTML
|
|
165
|
+
<div class="micl-datepicker__input micl-textfield-outlined">
|
|
166
|
+
<label for="mydate">Date</label>
|
|
167
|
+
<input type="text" id="mydate">
|
|
168
|
+
<span class="micl-textfield__supporting-text"></span>
|
|
169
|
+
</div>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
An entry that is not a valid date, or one that falls outside the allowed `min` and `max` range, leaves the text field in an error state and does not change the selection. The invalid entry is preserved for correction. If the user confirms anyway, the picker commits the last valid selection.
|
|
173
|
+
|
|
174
|
+
## Integration
|
|
119
175
|
|
|
120
|
-
### Integration
|
|
121
176
|
You can trigger the Date picker component from standard input fields or buttons.
|
|
122
177
|
|
|
123
|
-
|
|
178
|
+
### Connecting to an Input Field
|
|
179
|
+
|
|
124
180
|
To replace the browser's native date picker, add the `data-datepicker` attribute to an `<input>` element. The value of this attribute must match the `id` of your Date picker dialog.
|
|
125
181
|
|
|
126
182
|
```HTML
|
|
127
183
|
<input type="date" data-datepicker="mydatepicker" value="2025-12-02">
|
|
128
184
|
```
|
|
129
185
|
|
|
130
|
-
|
|
131
|
-
|
|
186
|
+
* **Behavior**: Clicking the input opens the picker, initialized with the input's current value.
|
|
187
|
+
* **Reusability**: Multiple input fields can target the same Date picker component ID. The picker automatically updates to reflect the date of the specific input field currently engaged by the user.
|
|
132
188
|
|
|
133
|
-
|
|
189
|
+
When the invoking input is wrapped in a [Text field component](../textfield/README.md), add an empty `micl-textfield__supporting-text` element to spell out the date format below the field. The component fills this element with the locale's date format, matching the one it uses in its own input view:
|
|
190
|
+
|
|
191
|
+
```HTML
|
|
192
|
+
<div class="micl-textfield-outlined">
|
|
193
|
+
<label for="mytextfield">Start date</label>
|
|
194
|
+
<input type="date" id="mytextfield" data-datepicker="mydatepicker" value="2025-12-02">
|
|
195
|
+
<span class="micl-textfield__supporting-text"></span>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
*(Note: If you provide custom text content within this element, the component will not overwrite it.)*
|
|
201
|
+
|
|
202
|
+
#### Docked Positioning
|
|
203
|
+
|
|
204
|
+
By default, the Date picker opens in the center of the screen. To anchor it to the input field, use the `micl-dialog--docked` class and CSS Anchor positioning. A docked date picker still opens as a modal dialog — unlike a standard docked [Dialog](../dialog/README.md), it cannot be a popover (for the reason detailed in the important note below).
|
|
134
205
|
|
|
135
206
|
```HTML
|
|
136
207
|
<dialog id="mydatepicker" class="micl-dialog micl-dialog--docked micl-datepicker" style="position-anchor:--myanchor">
|
|
@@ -139,47 +210,68 @@ To replace the browser's native date picker, add the `data-datepicker` attribute
|
|
|
139
210
|
<label for="mytextfield">Start date</label>
|
|
140
211
|
<input type="date" id="mytextfield" data-datepicker="mydatepicker">
|
|
141
212
|
</div>
|
|
213
|
+
|
|
142
214
|
```
|
|
143
215
|
|
|
144
|
-
|
|
145
|
-
|
|
216
|
+
### Connecting to a Button
|
|
217
|
+
|
|
218
|
+
You can trigger the picker from a button using the standard `command` attribute.
|
|
146
219
|
|
|
147
220
|
```HTML
|
|
148
|
-
<button
|
|
221
|
+
<button
|
|
222
|
+
type="button"
|
|
223
|
+
class="micl-button-text-m"
|
|
224
|
+
command="show-modal"
|
|
225
|
+
commandfor="mydatepicker"
|
|
226
|
+
value="2026-01-23"
|
|
227
|
+
>23.01.2026</button>
|
|
149
228
|
```
|
|
150
229
|
|
|
151
|
-
|
|
152
|
-
|
|
230
|
+
* **Behavior**: The Date picker reads from and writes to the button's `value` attribute.
|
|
231
|
+
* **Formatting**: The component automatically updates the button's text content with the selected date, formatted according to the user's locale.
|
|
232
|
+
|
|
233
|
+
> [!IMPORTANT]
|
|
234
|
+
> Because a date picker requires explicit user confirmation, it must function as a modal dialog. Opening it as a popover (`popovertarget`) is **not supported**. A `<dialog popover>` is not closed by `<form method="dialog">` and does not fire the standard `close` event required by the component to write the selected date back to the invoker.
|
|
153
235
|
|
|
154
236
|
## Date Range Selection
|
|
237
|
+
|
|
155
238
|
Add the `micl-datepicker--range` class to the dialog to let users select a range of dates instead of a single date:
|
|
156
239
|
|
|
157
240
|
```HTML
|
|
158
|
-
<dialog
|
|
241
|
+
<dialog class="micl-dialog micl-datepicker micl-datepicker--range" closedby="closerequest">
|
|
159
242
|
```
|
|
160
243
|
|
|
161
|
-
The first selected date becomes the start of the range and the second
|
|
244
|
+
The first selected date becomes the start of the range, and the second selection defines the end. Selecting a date *before* the current start date moves the start, and any selection made after a completed range resets the picker to start a new range. Confirming before an end date is chosen commits a single-day range.
|
|
162
245
|
|
|
163
246
|
### Connecting a Pair of Input Fields
|
|
164
|
-
|
|
247
|
+
|
|
248
|
+
Connect two date input fields — both referencing the picker in their `data-datepicker` attributes — and identify the end-date field using the `data-miclrangeto` attribute on the start-date field:
|
|
165
249
|
|
|
166
250
|
```HTML
|
|
167
251
|
<input type="date" id="from" data-datepicker="myrangepicker" data-miclrangeto="to">
|
|
168
252
|
<input type="date" id="to" data-datepicker="myrangepicker">
|
|
169
253
|
```
|
|
170
254
|
|
|
171
|
-
|
|
172
|
-
|
|
255
|
+
* **Behavior**: Clicking either field opens the picker with the range loaded from both fields. If the start date is after the end date, the values are automatically swapped. Confirming the selection updates both fields and fires their respective `change` events.
|
|
256
|
+
* **Limits**: The earliest allowed date is derived from the `min` attribute of the start field; the latest allowed date is derived from the `max` attribute of the end field.
|
|
173
257
|
|
|
174
258
|
### Connecting to a Button
|
|
175
|
-
|
|
259
|
+
|
|
260
|
+
A single button invoker holds the range in its `value` attribute as an ISO 8601 time interval. The component updates the button's text content with the localized range string:
|
|
176
261
|
|
|
177
262
|
```HTML
|
|
178
|
-
<button
|
|
263
|
+
<button
|
|
264
|
+
type="button"
|
|
265
|
+
class="micl-button-text-m"
|
|
266
|
+
command="show-modal"
|
|
267
|
+
commandfor="myrangepicker"
|
|
268
|
+
value="2026-01-23/2026-02-06"
|
|
269
|
+
>23.01.2026 – 06.02.2026</button>
|
|
179
270
|
```
|
|
180
271
|
|
|
181
272
|
### Text Input Mode
|
|
182
|
-
|
|
273
|
+
|
|
274
|
+
In range mode, the manual input area contains two [Text field components](../textfield/README.md) instead of one:
|
|
183
275
|
|
|
184
276
|
```HTML
|
|
185
277
|
<div class="micl-datepicker__input">
|
|
@@ -194,13 +286,36 @@ In range mode, the manual input area holds two [Text field components](../textfi
|
|
|
194
286
|
</div>
|
|
195
287
|
```
|
|
196
288
|
|
|
197
|
-
Entering a start date that
|
|
289
|
+
Entering a start date that occurs after the end date will swap the two inputs. These fields cannot be fully cleared; to discard the end of a range, the user must return to the calendar view and start a new range by clicking any date.
|
|
290
|
+
|
|
291
|
+
## Accessibility
|
|
292
|
+
|
|
293
|
+
* **Dialog labeling:** Always label the dialog. Point `aria-labelledby` at the supporting label, not at the headline. The headline holds the current selection and is rewritten on every change (the component marks it `aria-live="polite"` so assistive technologies announce new selections).
|
|
294
|
+
* **Grid structure:** The calendar is exposed as a `grid` of `row`s, with the weekday labels acting as `columnheader`s. Every date is a `gridcell` carrying its full, localized date as an `aria-label`. Selected dates are `aria-selected`, today's date is `aria-current="date"`, and dates outside the allowed range are `aria-disabled`.
|
|
295
|
+
* **Keyboard navigation:** The calendar utilizes a single tab stop and moves focus between dates with the arrow keys. Dates from neighboring months and those outside the allowed range are safely skipped.
|
|
296
|
+
|
|
297
|
+
| Key | Action |
|
|
298
|
+
| --- | --- |
|
|
299
|
+
| <kbd>←</kbd> <kbd>→</kbd> | Move to the previous or next day (mirrored in a right-to-left context) |
|
|
300
|
+
| <kbd>↑</kbd> <kbd>↓</kbd> | Move to the same weekday of the previous or next week |
|
|
301
|
+
| <kbd>Home</kbd> <kbd>End</kbd> | Move to the first or last day of the week |
|
|
302
|
+
| <kbd>Enter</kbd> <kbd>Space</kbd> | Select the focused date |
|
|
303
|
+
| <kbd>PageUp</kbd> <kbd>PageDown</kbd> | Show the next or previous month |
|
|
304
|
+
| <kbd>Shift</kbd> + <kbd>PageUp</kbd> / <kbd>PageDown</kbd> | Show the next or previous year |
|
|
305
|
+
| <kbd>Shift</kbd> + <kbd>M</kbd> / <kbd>Y</kbd> | Open the month or year selection |
|
|
306
|
+
| <kbd>Esc</kbd> | Close the picker without changing the invoker |
|
|
307
|
+
|
|
308
|
+
Moving beyond the first or last date of the month smoothly scrolls the calendar to the adjacent month while keeping focus on the active date.
|
|
309
|
+
|
|
310
|
+
* **Icon-only buttons:** The month/year arrows and the input mode toggle carry no text. Ensure each has a descriptive `aria-label`. The input mode toggle communicates the active mode through the `aria-pressed` attribute.
|
|
311
|
+
* **Motion preferences:** The component respects OS-level accessibility settings. The calendar will only slide between months and nudge at limits if the user has *not* enabled reduced motion.
|
|
198
312
|
|
|
199
313
|
## Theming
|
|
200
|
-
|
|
314
|
+
|
|
315
|
+
Each date picker can be themed with CSS custom properties that follow the Material Design 3 component-token naming convention. The container color, shape, and elevation are inherited directly from the [Dialog component](../dialog/README.md).
|
|
201
316
|
|
|
202
317
|
| Custom property | Meaning | Default |
|
|
203
|
-
|
|
318
|
+
| --- | --- | --- |
|
|
204
319
|
| `--md-comp-date-picker-modal-container-width` | The width of the modal date picker | `360px` |
|
|
205
320
|
| `--md-comp-date-input-modal-container-width` | The width of the modal date picker in text input mode | `328px` |
|
|
206
321
|
| `--md-comp-date-picker-docked-container-width` | The width of the docked date picker | `360px` |
|
|
@@ -214,8 +329,18 @@ Each date picker can be themed with CSS custom properties that follow the Materi
|
|
|
214
329
|
| `--md-comp-date-picker-selection-year-unselected-label-text-color` | The text color of the selectable years | `--md-sys-color-on-surface-variant` |
|
|
215
330
|
| `--md-comp-date-picker-selection-year-selected-container-color` | The background color of the selected year | `--md-sys-color-primary` |
|
|
216
331
|
| `--md-comp-date-picker-selection-year-selected-label-text-color` | The text color of the selected year | `--md-sys-color-on-primary` |
|
|
332
|
+
| `--md-comp-date-picker-selection-month-selected-container-color` | The background color of the selected month | `--md-sys-color-surface-variant` |
|
|
333
|
+
| `--md-comp-date-picker-selection-month-selected-label-text-color` | The text color of the selected month | `--md-sys-color-on-surface` |
|
|
334
|
+
| `--md-comp-date-picker-focus-indicator-color` | The color of the focus indicator around a date, month or year | `--md-sys-color-secondary` |
|
|
217
335
|
| `--md-comp-date-picker-range-selection-active-indicator-container-color` | The background color of the band connecting the endpoints of a range | `--md-sys-color-secondary-container` |
|
|
218
336
|
| `--md-comp-date-picker-selection-date-in-range-label-text-color` | The text color of the dates inside a range | `--md-sys-color-on-secondary-container` |
|
|
337
|
+
| `--md-comp-date-picker-motion-spatial` | The easing function of the slide between two months | `--md-sys-motion-expressive-fast-effects` |
|
|
338
|
+
| `--md-comp-date-picker-motion-spatial-duration` | The duration of the slide between two months | `--md-sys-motion-expressive-default-spatial-duration` |
|
|
339
|
+
| `--md-comp-date-picker-motion-duration` | The duration of the fade between the calendar, month, year and input views | `--md-sys-motion-expressive-default-effects-duration` |
|
|
340
|
+
| `--md-comp-date-picker-motion-duration-reverse` | The duration of the fade of the view that is leaving | `--md-sys-motion-expressive-fast-effects-duration` |
|
|
341
|
+
| `--md-comp-date-picker-button-motion-duration` | The duration of the state layer fade of a date or year | `--md-sys-motion-expressive-fast-spatial-duration` |
|
|
342
|
+
|
|
343
|
+
*(Note: All motion is disabled if the user has requested reduced motion at the OS level.)*
|
|
219
344
|
|
|
220
345
|
**Example: Changing the width of the modal date picker**
|
|
221
346
|
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
@include statelayer.token('focus-state-layer-opacity');
|
|
32
32
|
@include statelayer.token('pressed-state-layer-opacity');
|
|
33
33
|
@include statelayer.token('disabled-state-layer-opacity');
|
|
34
|
+
@include statelayer.token('focus-indicator-thickness');
|
|
34
35
|
@include statelayer.property;
|
|
35
36
|
|
|
36
37
|
@include typography.scale('headline-large');
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
%view-transition-base {
|
|
42
43
|
block-size: fit-content;
|
|
43
44
|
opacity: 1;
|
|
44
|
-
transition-duration: var(--
|
|
45
|
+
transition-duration: var(--_datepicker-motion-spatial-duration);
|
|
45
46
|
|
|
46
47
|
&.micl-datepicker__view-hidden {
|
|
47
48
|
block-size: 0;
|
|
@@ -65,12 +66,12 @@
|
|
|
65
66
|
background-repeat: no-repeat;
|
|
66
67
|
background-size: 100%;
|
|
67
68
|
background-clip: content-box;
|
|
68
|
-
transition: --statelayer-opacity var(--
|
|
69
|
+
transition: --statelayer-opacity var(--_datepicker-button-motion-duration) linear;
|
|
69
70
|
|
|
70
71
|
&:hover {
|
|
71
72
|
--statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity);
|
|
72
73
|
}
|
|
73
|
-
&:focus-visible {
|
|
74
|
+
&:is(:focus-visible, :has(input:focus-visible)) {
|
|
74
75
|
--statelayer-opacity: var(--md-sys-state-focus-state-layer-opacity);
|
|
75
76
|
}
|
|
76
77
|
&:active {
|
|
@@ -78,12 +79,17 @@
|
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
%focus-indicator {
|
|
83
|
+
outline: var(--md-sys-state-focus-indicator-thickness, 3px) solid var(--md-comp-date-picker-focus-indicator-color, var(--md-sys-color-secondary));
|
|
84
|
+
outline-offset: -1px;
|
|
85
|
+
}
|
|
86
|
+
|
|
81
87
|
dialog.micl-dialog.micl-datepicker {
|
|
82
|
-
--md-comp-date-picker-motion-spatial
|
|
83
|
-
--md-comp-date-picker-motion-spatial-duration
|
|
84
|
-
--md-comp-date-picker-motion-duration
|
|
85
|
-
--md-comp-date-picker-motion-duration-reverse
|
|
86
|
-
--md-comp-date-picker-button-motion-duration
|
|
88
|
+
--_datepicker-motion-spatial: var(--md-comp-date-picker-motion-spatial, #{motion.$md-sys-motion-expressive-fast-effects});
|
|
89
|
+
--_datepicker-motion-spatial-duration: var(--md-comp-date-picker-motion-spatial-duration, #{motion.$md-sys-motion-expressive-default-spatial-duration});
|
|
90
|
+
--_datepicker-motion-duration: var(--md-comp-date-picker-motion-duration, #{motion.$md-sys-motion-expressive-default-effects-duration});
|
|
91
|
+
--_datepicker-motion-duration-reverse: var(--md-comp-date-picker-motion-duration-reverse, #{motion.$md-sys-motion-expressive-fast-effects-duration});
|
|
92
|
+
--_datepicker-button-motion-duration: var(--md-comp-date-picker-button-motion-duration, #{motion.$md-sys-motion-expressive-fast-spatial-duration});
|
|
87
93
|
|
|
88
94
|
// Internal alias: the target size is referenced from many descendants.
|
|
89
95
|
--_target: var(--md-sys-state-target-size, 48px);
|
|
@@ -153,7 +159,7 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
153
159
|
min-block-size: 330px;
|
|
154
160
|
padding-inline: 0;
|
|
155
161
|
overflow: hidden auto;
|
|
156
|
-
transition: min-block-size var(--
|
|
162
|
+
transition: min-block-size var(--_datepicker-motion-spatial-duration) var(--_datepicker-motion-spatial);
|
|
157
163
|
}
|
|
158
164
|
|
|
159
165
|
.micl-dialog__actions {
|
|
@@ -179,6 +185,13 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
179
185
|
margin-block: -2px;
|
|
180
186
|
}
|
|
181
187
|
}
|
|
188
|
+
|
|
189
|
+
@media (prefers-reduced-motion: reduce) {
|
|
190
|
+
--_datepicker-motion-spatial-duration: 0ms;
|
|
191
|
+
--_datepicker-motion-duration: 0ms;
|
|
192
|
+
--_datepicker-motion-duration-reverse: 0ms;
|
|
193
|
+
--_datepicker-button-motion-duration: 0ms;
|
|
194
|
+
}
|
|
182
195
|
}
|
|
183
196
|
|
|
184
197
|
.micl-datepicker__inputmode {
|
|
@@ -275,10 +288,10 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
275
288
|
overflow: hidden;
|
|
276
289
|
transform: translateX(0);
|
|
277
290
|
transition:
|
|
278
|
-
transform var(--
|
|
279
|
-
opacity var(--
|
|
280
|
-
block-size var(--
|
|
281
|
-
display var(--
|
|
291
|
+
transform var(--_datepicker-motion-spatial-duration) var(--_datepicker-motion-spatial),
|
|
292
|
+
opacity var(--_datepicker-motion-duration-reverse) linear,
|
|
293
|
+
block-size var(--_datepicker-motion-duration-reverse) linear allow-discrete,
|
|
294
|
+
display var(--_datepicker-motion-duration-reverse) linear allow-discrete;
|
|
282
295
|
|
|
283
296
|
&.micl-datepicker__view-hidden {
|
|
284
297
|
block-size: 0%;
|
|
@@ -293,6 +306,38 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
293
306
|
&.micl-moveleft {
|
|
294
307
|
transform: translateX(-50%);
|
|
295
308
|
}
|
|
309
|
+
// The flex row is laid out from the inline start, so the off-screen half of
|
|
310
|
+
// the strip sits on the opposite side in a right-to-left context.
|
|
311
|
+
&:dir(rtl) {
|
|
312
|
+
&.micl-startright,
|
|
313
|
+
&.micl-moveleft {
|
|
314
|
+
transform: translateX(50%);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
&.micl-datepicker__nudge-min,
|
|
318
|
+
&.micl-datepicker__nudge-max {
|
|
319
|
+
animation: micl-datepicker-nudge var(--_datepicker-motion-duration) ease-in-out;
|
|
320
|
+
}
|
|
321
|
+
&.micl-datepicker__nudge-min {
|
|
322
|
+
--_nudge: 8px;
|
|
323
|
+
}
|
|
324
|
+
&.micl-datepicker__nudge-max {
|
|
325
|
+
--_nudge: -8px;
|
|
326
|
+
}
|
|
327
|
+
&:dir(rtl) {
|
|
328
|
+
&.micl-datepicker__nudge-min {
|
|
329
|
+
--_nudge: -8px;
|
|
330
|
+
}
|
|
331
|
+
&.micl-datepicker__nudge-max {
|
|
332
|
+
--_nudge: 8px;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
@keyframes micl-datepicker-nudge {
|
|
338
|
+
50% {
|
|
339
|
+
translate: var(--_nudge, 0) 0;
|
|
340
|
+
}
|
|
296
341
|
}
|
|
297
342
|
.micl-datepicker__calendar {
|
|
298
343
|
flex-shrink: 0;
|
|
@@ -304,12 +349,16 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
304
349
|
|
|
305
350
|
box-sizing: border-box;
|
|
306
351
|
display: grid;
|
|
307
|
-
grid-template-columns: repeat(7, var(--_target));
|
|
308
352
|
grid-template-rows: 40px repeat(6, var(--_target));
|
|
309
353
|
block-size: 100%;
|
|
310
354
|
inline-size: 100%;
|
|
311
355
|
padding-inline: 12px;
|
|
312
356
|
|
|
357
|
+
> * {
|
|
358
|
+
display: grid;
|
|
359
|
+
grid-template-columns: repeat(7, var(--_target));
|
|
360
|
+
}
|
|
361
|
+
|
|
313
362
|
span, time {
|
|
314
363
|
box-sizing: border-box;
|
|
315
364
|
display: inline-flex;
|
|
@@ -368,12 +417,16 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
368
417
|
&:is(.micl-datepicker__today, .micl-datepicker__selected):is(:hover, :focus-visible, :active) {
|
|
369
418
|
--statelayer-color: currentColor;
|
|
370
419
|
}
|
|
371
|
-
&.micl-
|
|
420
|
+
&.micl-datepicker__disabled {
|
|
372
421
|
color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity));
|
|
422
|
+
pointer-events: none;
|
|
373
423
|
}
|
|
374
|
-
&:not(.micl-
|
|
424
|
+
&:not(.micl-datepicker__disabled) {
|
|
375
425
|
cursor: pointer;
|
|
376
426
|
}
|
|
427
|
+
&:focus-visible {
|
|
428
|
+
@extend %focus-indicator;
|
|
429
|
+
}
|
|
377
430
|
}
|
|
378
431
|
}
|
|
379
432
|
|
|
@@ -403,15 +456,23 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
403
456
|
|
|
404
457
|
span {
|
|
405
458
|
visibility: hidden;
|
|
406
|
-
color:
|
|
459
|
+
color: inherit;
|
|
407
460
|
}
|
|
408
461
|
&:has(input:checked) {
|
|
409
|
-
|
|
462
|
+
color: var(--md-comp-date-picker-selection-month-selected-label-text-color, var(--md-sys-color-on-surface));
|
|
463
|
+
background-color: var(--md-comp-date-picker-selection-month-selected-container-color, var(--md-sys-color-surface-variant));
|
|
410
464
|
|
|
411
465
|
span {
|
|
412
466
|
visibility: visible;
|
|
413
467
|
}
|
|
414
468
|
}
|
|
469
|
+
&:has(input:disabled) {
|
|
470
|
+
color: rgb(from var(--md-sys-color-on-surface) r g b / var(--md-sys-state-disabled-state-layer-opacity));
|
|
471
|
+
pointer-events: none;
|
|
472
|
+
}
|
|
473
|
+
&:has(input:focus-visible) {
|
|
474
|
+
@extend %focus-indicator;
|
|
475
|
+
}
|
|
415
476
|
}
|
|
416
477
|
}
|
|
417
478
|
.micl-datepicker__years {
|
|
@@ -444,10 +505,13 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
444
505
|
background-color: var(--md-comp-date-picker-selection-year-selected-container-color, var(--md-sys-color-primary));
|
|
445
506
|
|
|
446
507
|
// The state layer of the selected year follows its label color.
|
|
447
|
-
&:is(:hover, :focus-visible
|
|
508
|
+
&:is(:hover, :active, :has(input:focus-visible)) {
|
|
448
509
|
--statelayer-color: currentColor;
|
|
449
510
|
}
|
|
450
511
|
}
|
|
512
|
+
&:has(input:focus-visible) {
|
|
513
|
+
@extend %focus-indicator;
|
|
514
|
+
}
|
|
451
515
|
}
|
|
452
516
|
}
|
|
453
517
|
:is(.micl-datepicker__months, .micl-datepicker__years) input[type=radio] {
|
|
@@ -475,6 +539,6 @@ dialog.micl-dialog.micl-datepicker {
|
|
|
475
539
|
}
|
|
476
540
|
}
|
|
477
541
|
|
|
478
|
-
.micl-
|
|
542
|
+
.micl-datepicker__no-transition {
|
|
479
543
|
transition: none !important;
|
|
480
544
|
}
|