material-inspired-component-library 9.1.0 → 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/README.md +2 -1
- 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 +62 -45
- package/components/button/_shared.scss +9 -9
- package/components/card/README.md +55 -25
- package/components/card/index.scss +57 -38
- package/components/checkbox/README.md +97 -28
- package/components/checkbox/index.scss +39 -29
- package/components/chip/index.scss +6 -6
- package/components/datepicker/README.md +184 -59
- package/components/datepicker/index.scss +85 -21
- package/components/dialog/README.md +151 -56
- package/components/dialog/index.scss +50 -62
- package/components/iconbutton/index.scss +8 -8
- package/components/list/index.scss +15 -11
- package/components/menu/index.scss +13 -13
- package/components/navigationbar/index.scss +7 -1
- package/components/navigationrail/index.scss +27 -22
- package/components/radio/README.md +52 -12
- package/components/radio/index.scss +59 -41
- 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 +5 -5
- package/components/switch/README.md +32 -4
- package/components/switch/index.scss +57 -52
- package/components/timepicker/README.md +131 -55
- package/components/timepicker/index.scss +47 -26
- 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/card.css +1 -1
- package/dist/checkbox.css +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/chip.css +1 -1
- package/dist/components/checkbox/index.d.ts +1 -0
- package/dist/datepicker.css +1 -1
- package/dist/datepicker.js +1 -1
- package/dist/dialog.css +1 -1
- package/dist/foundations/form/index.js +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/stepper.js +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 +5 -35
- package/package.json +2 -2
- package/{components/checkbox/_label.scss → styles/togglelabel.scss} +11 -3
|
@@ -22,8 +22,7 @@
|
|
|
22
22
|
@use '../../styles/motion';
|
|
23
23
|
@use '../../styles/shape';
|
|
24
24
|
@use '../../styles/statelayer';
|
|
25
|
-
@use '../../styles/
|
|
26
|
-
@use './label';
|
|
25
|
+
@use '../../styles/togglelabel';
|
|
27
26
|
|
|
28
27
|
@include shape.corner('full');
|
|
29
28
|
|
|
@@ -33,6 +32,7 @@
|
|
|
33
32
|
@include statelayer.token('pressed-state-layer-opacity');
|
|
34
33
|
@include statelayer.token('disabled-state-layer-opacity');
|
|
35
34
|
@include statelayer.token('focus-indicator-thickness');
|
|
35
|
+
@include statelayer.token('focus-indicator-outer-offset');
|
|
36
36
|
@include statelayer.token('ripple-opacity-factor');
|
|
37
37
|
@include statelayer.token('ripple-duration');
|
|
38
38
|
@include statelayer.property;
|
|
@@ -44,35 +44,40 @@
|
|
|
44
44
|
$checkbox: 'input[type=checkbox].micl-checkbox';
|
|
45
45
|
|
|
46
46
|
#{$checkbox} {
|
|
47
|
-
--md-comp-checkbox-motion-duration
|
|
48
|
-
--md-comp-checkbox-motion-duration-reverse
|
|
49
|
-
--md-comp-checkbox-motion-spatial
|
|
47
|
+
--_motion-duration: var(--md-comp-checkbox-motion-duration, #{motion.$md-sys-motion-expressive-slow-effects-duration});
|
|
48
|
+
--_motion-duration-reverse: var(--md-comp-checkbox-motion-duration-reverse, #{motion.$md-sys-motion-expressive-default-effects-duration});
|
|
49
|
+
--_motion-spatial: var(--md-comp-checkbox-motion-spatial, #{motion.$md-sys-motion-expressive-fast-spatial});
|
|
50
50
|
|
|
51
51
|
--_size: var(--md-comp-checkbox-container-size, 18px);
|
|
52
52
|
--_outline-width: var(--md-comp-checkbox-outline-width, 2px);
|
|
53
53
|
--_check-thickness: var(--md-comp-checkbox-check-thickness, 2px);
|
|
54
|
+
--_layer: max(var(--md-sys-state-layer-size, 40px), calc(var(--_size) + 22px));
|
|
55
|
+
--_target: max(var(--md-sys-state-target-size, 48px), calc(var(--_layer) + 8px));
|
|
54
56
|
--statelayer-color: var(--md-sys-color-on-surface);
|
|
55
57
|
|
|
56
58
|
appearance: none;
|
|
57
59
|
box-sizing: border-box;
|
|
58
60
|
position: relative;
|
|
59
|
-
inline-size: var(--
|
|
60
|
-
min-inline-size: var(--
|
|
61
|
-
block-size: var(--
|
|
62
|
-
min-block-size: var(--
|
|
61
|
+
inline-size: var(--_target);
|
|
62
|
+
min-inline-size: var(--_target);
|
|
63
|
+
block-size: var(--_target);
|
|
64
|
+
min-block-size: var(--_target);
|
|
63
65
|
margin: 0;
|
|
64
|
-
border: calc((var(--
|
|
66
|
+
border: calc((var(--_target) - var(--_layer)) / 2) solid transparent;
|
|
65
67
|
background-clip: content-box;
|
|
66
68
|
background-color: transparent;
|
|
67
69
|
-webkit-tap-highlight-color: transparent;
|
|
68
70
|
border-radius: var(--md-sys-shape-corner-full);
|
|
69
|
-
outline-offset:
|
|
71
|
+
outline-offset: calc(
|
|
72
|
+
var(--md-sys-state-focus-indicator-outer-offset, 2px)
|
|
73
|
+
- ((var(--_target) - var(--_layer)) / 2)
|
|
74
|
+
);
|
|
70
75
|
|
|
71
76
|
// The check mark: two currentColor borders rotated into a check, revealed by a
|
|
72
77
|
// combination of block-size and clip-path transitions. currentColor, so that the
|
|
73
78
|
// error and disabled states recolour it with a single color declaration.
|
|
74
79
|
&::before {
|
|
75
|
-
--_check-width: calc(var(--_size)
|
|
80
|
+
--_check-width: calc(var(--_size) * 5 / 6);
|
|
76
81
|
--_check-height: calc(0.4667 * var(--_check-width));
|
|
77
82
|
|
|
78
83
|
content: "";
|
|
@@ -82,14 +87,14 @@ $checkbox: 'input[type=checkbox].micl-checkbox';
|
|
|
82
87
|
block-size: 0;
|
|
83
88
|
inset: 0;
|
|
84
89
|
inset-block-start: calc(-0.25 * var(--_size));
|
|
85
|
-
inset-inline-start:
|
|
90
|
+
inset-inline-start: calc(var(--_check-thickness) / 2);
|
|
86
91
|
margin: auto;
|
|
87
92
|
color: var(--md-comp-checkbox-selected-icon-color, var(--md-sys-color-on-primary));
|
|
88
93
|
border-block-end: var(--_check-thickness) currentColor solid;
|
|
89
94
|
border-inline-start: var(--_check-thickness) currentColor solid;
|
|
90
95
|
transform: rotate(-45deg);
|
|
91
96
|
transform-origin: center;
|
|
92
|
-
clip-path: rect(0
|
|
97
|
+
clip-path: rect(0 var(--_check-thickness) 0 0);
|
|
93
98
|
z-index: 1;
|
|
94
99
|
transition:
|
|
95
100
|
block-size var(--md-sys-motion-duration-short3) var(--md-sys-motion-duration-short3) motion.$md-sys-motion-easing-standard-decelerate,
|
|
@@ -111,33 +116,33 @@ $checkbox: 'input[type=checkbox].micl-checkbox';
|
|
|
111
116
|
inset: 0;
|
|
112
117
|
margin: auto;
|
|
113
118
|
border: var(--_outline-width) solid var(--_outline-color);
|
|
114
|
-
border-radius: 2px;
|
|
119
|
+
border-radius: var(--md-comp-checkbox-container-shape, 2px);
|
|
115
120
|
background-color: var(--_container-color);
|
|
116
121
|
transition:
|
|
117
|
-
background-color var(--
|
|
118
|
-
border-color var(--
|
|
122
|
+
background-color var(--_motion-duration-reverse) motion.$md-sys-motion-easing-emphasized var(--_motion-duration-reverse),
|
|
123
|
+
border-color var(--_motion-duration-reverse) motion.$md-sys-motion-easing-emphasized var(--_motion-duration-reverse);
|
|
119
124
|
}
|
|
120
125
|
&:is(:checked, :indeterminate) {
|
|
121
126
|
--statelayer-color: var(--md-sys-color-primary);
|
|
122
127
|
|
|
123
128
|
&::before {
|
|
124
129
|
block-size: var(--_check-height);
|
|
125
|
-
clip-path: rect(0 calc(var(--
|
|
130
|
+
clip-path: rect(0 calc(var(--_check-width) - var(--_check-thickness)) var(--_size) 0);
|
|
126
131
|
transition:
|
|
127
|
-
block-size var(--md-sys-motion-duration-short3) var(--
|
|
128
|
-
clip-path var(--md-sys-motion-duration-long4) var(--md-sys-motion-duration-short3) var(--
|
|
132
|
+
block-size var(--md-sys-motion-duration-short3) var(--_motion-spatial),
|
|
133
|
+
clip-path var(--md-sys-motion-duration-long4) var(--md-sys-motion-duration-short3) var(--_motion-spatial);
|
|
129
134
|
}
|
|
130
135
|
&::after {
|
|
131
136
|
--_container-color: var(--md-comp-checkbox-selected-container-color, var(--md-sys-color-primary));
|
|
132
137
|
--_outline-color: var(--md-comp-checkbox-selected-container-color, var(--md-sys-color-primary));
|
|
133
138
|
|
|
134
139
|
transition:
|
|
135
|
-
background-color var(--
|
|
136
|
-
border-color var(--
|
|
140
|
+
background-color var(--_motion-duration) linear,
|
|
141
|
+
border-color var(--_motion-duration) motion.$md-sys-motion-easing-emphasized;
|
|
137
142
|
}
|
|
138
143
|
}
|
|
139
144
|
&:indeterminate::before {
|
|
140
|
-
inset-inline-start:
|
|
145
|
+
inset-inline-start: var(--_check-thickness);
|
|
141
146
|
border-inline-start-width: 0px;
|
|
142
147
|
transform: rotate(0deg);
|
|
143
148
|
}
|
|
@@ -189,7 +194,7 @@ $checkbox: 'input[type=checkbox].micl-checkbox';
|
|
|
189
194
|
cursor: pointer;
|
|
190
195
|
transition:
|
|
191
196
|
background-size 0ms,
|
|
192
|
-
--statelayer-opacity var(--
|
|
197
|
+
--statelayer-opacity var(--_motion-duration) linear;
|
|
193
198
|
|
|
194
199
|
&:hover {
|
|
195
200
|
--statelayer-opacity: var(--md-sys-state-hover-state-layer-opacity, 8%);
|
|
@@ -241,28 +246,33 @@ $checkbox: 'input[type=checkbox].micl-checkbox';
|
|
|
241
246
|
}
|
|
242
247
|
|
|
243
248
|
#{$checkbox}:not(:disabled) + label,
|
|
244
|
-
label:has(+ #{$checkbox}:not(:disabled))
|
|
249
|
+
label:has(+ #{$checkbox}:not(:disabled)),
|
|
250
|
+
label:has(#{$checkbox}:not(:disabled)) {
|
|
245
251
|
@extend %micl-toggle-label-pointer;
|
|
246
252
|
}
|
|
247
253
|
#{$checkbox} + label,
|
|
248
|
-
label:has(+ #{$checkbox})
|
|
254
|
+
label:has(+ #{$checkbox}),
|
|
255
|
+
label:has(#{$checkbox}) {
|
|
249
256
|
@extend %micl-toggle-label;
|
|
250
257
|
}
|
|
251
258
|
#{$checkbox}:disabled + label,
|
|
252
259
|
label:has(+ #{$checkbox}:disabled) {
|
|
253
260
|
@extend %micl-toggle-label-disabled;
|
|
254
261
|
}
|
|
262
|
+
label:has(#{$checkbox}:disabled) {
|
|
263
|
+
@extend %micl-toggle-label-disabled-text;
|
|
264
|
+
}
|
|
255
265
|
|
|
256
266
|
#{$checkbox}:dir(rtl) {
|
|
257
267
|
&::before {
|
|
258
|
-
clip-path: rect(0 var(--_size) var(--_size) calc(var(--_size) -
|
|
268
|
+
clip-path: rect(0 var(--_size) var(--_size) calc(var(--_size) - var(--_check-thickness)));
|
|
259
269
|
}
|
|
260
270
|
&:checked::before {
|
|
261
|
-
clip-path: rect(0 var(--_size) var(--_size)
|
|
271
|
+
clip-path: rect(0 var(--_size) var(--_size) var(--_check-thickness));
|
|
262
272
|
transform: rotate(45deg);
|
|
263
273
|
}
|
|
264
274
|
&:indeterminate::before {
|
|
265
|
-
clip-path: rect(0 var(--_size) var(--_size)
|
|
275
|
+
clip-path: rect(0 var(--_size) var(--_size) var(--_check-thickness));
|
|
266
276
|
transform: rotate(0deg);
|
|
267
277
|
}
|
|
268
278
|
}
|
|
@@ -176,9 +176,9 @@
|
|
|
176
176
|
&::before {
|
|
177
177
|
content: "";
|
|
178
178
|
position: absolute;
|
|
179
|
-
inset-block-start: calc((100% - var(--md-sys-target-size, 48px)) / 2);
|
|
179
|
+
inset-block-start: calc((100% - var(--md-sys-state-target-size, 48px)) / 2);
|
|
180
180
|
inset-inline-start: 0;
|
|
181
|
-
block-size: var(--md-sys-target-size, 48px);
|
|
181
|
+
block-size: var(--md-sys-state-target-size, 48px);
|
|
182
182
|
inline-size: 100%;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
@@ -195,10 +195,10 @@
|
|
|
195
195
|
&::before {
|
|
196
196
|
content: "";
|
|
197
197
|
position: absolute;
|
|
198
|
-
inset-block-start: calc((100% - var(--md-sys-target-size, 48px)) / 2);
|
|
199
|
-
inset-inline-start: calc((100% - var(--md-sys-target-size, 48px)) / 2);
|
|
200
|
-
block-size: var(--md-sys-target-size, 48px);
|
|
201
|
-
inline-size: var(--md-sys-target-size, 48px);
|
|
198
|
+
inset-block-start: calc((100% - var(--md-sys-state-target-size, 48px)) / 2);
|
|
199
|
+
inset-inline-start: calc((100% - var(--md-sys-state-target-size, 48px)) / 2);
|
|
200
|
+
block-size: var(--md-sys-state-target-size, 48px);
|
|
201
|
+
inline-size: var(--md-sys-state-target-size, 48px);
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
.micl-chip__avatar {
|
|
@@ -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
|
|