@expressivecss/expressive 0.7.0-rc.0 → 0.8.0
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/CHANGELOG.md +1311 -1
- package/README.md +14 -11
- package/dist/css/expressive.css +4215 -1668
- package/dist/css/expressive.css.map +1 -1
- package/dist/css/expressive.min.css +1 -1
- package/dist/css/expressive.min.css.map +1 -1
- package/dist/js/expressive.cjs +1231 -1253
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +1231 -1253
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +12 -12
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +1231 -1253
- package/dist/js/expressive.mjs.map +4 -4
- package/dist/types/behaviors/bottomSheets.d.ts +19 -11
- package/dist/types/behaviors/sheetDrag.d.ts +40 -0
- package/dist/types/behaviors/sideSheets.d.ts +2 -9
- package/dist/types/components/autocomplete.d.ts +15 -3
- package/dist/types/components/buttons.d.ts +5 -1
- package/dist/types/components/carousel.d.ts +87 -53
- package/dist/types/components/chips.d.ts +21 -1
- package/dist/types/components/expandingCard.d.ts +31 -0
- package/dist/types/components/index.d.ts +21 -20
- package/dist/types/components/lightbox.d.ts +1 -0
- package/dist/types/components/menu.d.ts +7 -1
- package/dist/types/components/{sidenav.d.ts → navigationDrawer.d.ts} +16 -16
- package/dist/types/components/registry.d.ts +8 -8
- package/dist/types/components/slider.d.ts +26 -85
- package/dist/types/components/snackbar.d.ts +20 -5
- package/dist/types/components/tabs.d.ts +12 -0
- package/dist/types/components/timepicker.d.ts +12 -9
- package/dist/types/core/utils.d.ts +64 -53
- package/dist/types/index.d.ts +8 -9
- package/package.json +15 -1
- package/src/sass/README.md +61 -11
- package/src/sass/abstracts/_breakpoints.scss +17 -19
- package/src/sass/abstracts/_mixins.scss +103 -21
- package/src/sass/abstracts/_variables.scss +50 -5
- package/src/sass/base/_global.scss +6 -24
- package/src/sass/base/_grid.scss +15 -12
- package/src/sass/base/_normalize.scss +34 -38
- package/src/sass/base/_typography.scss +4 -18
- package/src/sass/components/_badges.scss +2 -3
- package/src/sass/components/_banners.scss +298 -0
- package/src/sass/components/_bottom-app-bar.scss +180 -0
- package/src/sass/components/_bottom-sheet.scss +12 -4
- package/src/sass/components/_button-groups.scss +186 -0
- package/src/sass/components/_buttons.scss +245 -92
- package/src/sass/components/_cards.scss +494 -73
- package/src/sass/components/_carousel.scss +562 -68
- package/src/sass/components/_chips.scss +64 -5
- package/src/sass/components/_datepicker.scss +24 -24
- package/src/sass/components/_dialog.scss +17 -11
- package/src/sass/components/_drag-handle.scss +130 -0
- package/src/sass/components/_expanding-card.scss +260 -0
- package/src/sass/components/_fab-menu.scss +232 -0
- package/src/sass/components/_floating-sheet.scss +86 -0
- package/src/sass/components/_icon-buttons.scss +194 -0
- package/src/sass/components/_icons-material-design.scss +16 -4
- package/src/sass/components/_index.scss +22 -6
- package/src/sass/components/_list.scss +16 -13
- package/src/sass/components/_loading-indicator.scss +106 -0
- package/src/sass/components/_menu.scss +335 -61
- package/src/sass/components/_navbar.scss +71 -24
- package/src/sass/components/_navigation-bar.scss +13 -10
- package/src/sass/components/{_sidenav.scss → _navigation-drawer.scss} +123 -33
- package/src/sass/components/_navigation-rail.scss +22 -22
- package/src/sass/components/_page-footer.scss +19 -16
- package/src/sass/components/_pagination.scss +24 -6
- package/src/sass/components/_panes.scss +52 -11
- package/src/sass/components/{_preloader.scss → _progress.scss} +11 -3
- package/src/sass/components/_scrim.scss +37 -0
- package/src/sass/components/_search.scss +259 -0
- package/src/sass/components/_segmented-buttons.scss +188 -0
- package/src/sass/components/_side-sheet.scss +2 -2
- package/src/sass/components/_snackbar.scss +20 -15
- package/src/sass/components/_split-button.scss +196 -0
- package/src/sass/components/_tabs.scss +7 -8
- package/src/sass/components/_timepicker.scss +67 -58
- package/src/sass/components/_toolbar.scss +206 -80
- package/src/sass/components/forms/_checkboxes.scss +49 -12
- package/src/sass/components/forms/_fieldset.scss +4 -4
- package/src/sass/components/forms/_file-input.scss +8 -1
- package/src/sass/components/forms/_index.scss +1 -1
- package/src/sass/components/forms/_input-fields.scss +50 -44
- package/src/sass/components/forms/_radio-buttons.scss +42 -10
- package/src/sass/components/forms/_select.scss +0 -1
- package/src/sass/components/forms/{_range.scss → _slider.scss} +8 -9
- package/src/sass/components/forms/_switches.scss +6 -7
- package/src/sass/tokens/_index.scss +4 -1
- package/src/sass/tokens/_reference.scss +70 -61
- package/src/sass/tokens/_state.scss +24 -0
- package/src/sass/tokens/_theme.scss +6 -3
- package/src/sass/tokens/_vibrant.scss +76 -0
- package/src/sass/utilities/_colors.scss +14 -1
- package/src/sass/utilities/_helpers.scss +5 -5
- package/src/sass/utilities/_visibility.scss +48 -26
- package/dist/types/behaviors/waves.d.ts +0 -15
- package/dist/types/components/parallax.d.ts +0 -16
- package/dist/types/components/range.d.ts +0 -43
- package/dist/types/core/bounding.d.ts +0 -6
- package/dist/types/core/edges.d.ts +0 -6
- package/src/sass/components/_parallax.scss +0 -104
- package/src/sass/components/_pulse.scss +0 -37
- package/src/sass/components/_slider.scss +0 -129
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
@use "../abstracts" as *;
|
|
2
2
|
|
|
3
|
+
// A chip is written with the element that says what it is: <span> for a
|
|
4
|
+
// display or input chip, <button> for assist / suggestion, and
|
|
5
|
+
// <input type="checkbox"> + <label> for filter. The class styles all three
|
|
6
|
+
// elements, so everything below has to survive on any of them - hence the
|
|
7
|
+
// resets.
|
|
3
8
|
.chip {
|
|
4
9
|
--font-size: 14px;
|
|
5
10
|
--font-size-icon: 18px;
|
|
@@ -13,20 +18,66 @@
|
|
|
13
18
|
margin: 0;
|
|
14
19
|
height: 32px;
|
|
15
20
|
padding-left: var(--padding);
|
|
16
|
-
padding-right: var(--padding);
|
|
21
|
+
padding-right: var(--padding);
|
|
17
22
|
font-size: var(--font-size);
|
|
18
|
-
font-weight: 500;
|
|
23
|
+
font-weight: 500;
|
|
19
24
|
border-radius: 8px;
|
|
20
25
|
align-items: center;
|
|
21
26
|
user-select: none;
|
|
22
27
|
vertical-align: top;
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
// Button and label defaults that would otherwise show through.
|
|
30
|
+
appearance: none;
|
|
31
|
+
border: 0;
|
|
32
|
+
font-family: inherit;
|
|
33
|
+
text-align: inherit;
|
|
34
|
+
|
|
35
|
+
// Selected. `.active` is the pre-0.8.0 name and still works; `:focus` used
|
|
36
|
+
// to stand in for selection here, which meant a chip could not show focus
|
|
37
|
+
// and selection as the different things they are.
|
|
38
|
+
&.selected,
|
|
25
39
|
&.active {
|
|
26
|
-
outline: none;
|
|
27
40
|
background-color: var(--md-sys-color-secondary-container);
|
|
28
41
|
color: var(--md-sys-color-on-secondary-container);
|
|
29
42
|
}
|
|
43
|
+
|
|
44
|
+
@include focus-visible();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Interactive chips only. A display chip is a <span> and is not a control.
|
|
48
|
+
:is(button, label).chip {
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
|
|
51
|
+
&:hover {
|
|
52
|
+
background-color: color-mix(
|
|
53
|
+
in oklab,
|
|
54
|
+
var(--md-sys-color-on-surface-variant) state-opacity("hover"),
|
|
55
|
+
var(--md-sys-color-surface-container-low)
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Filter chip. The checkbox carries the state and the form value; the label is
|
|
61
|
+
// the chip. Kept focusable rather than `display: none` so it stays reachable.
|
|
62
|
+
.chip-input {
|
|
63
|
+
position: absolute;
|
|
64
|
+
width: 1px;
|
|
65
|
+
height: 1px;
|
|
66
|
+
margin: -1px;
|
|
67
|
+
padding: 0;
|
|
68
|
+
border: 0;
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
clip-path: inset(50%);
|
|
71
|
+
white-space: nowrap;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.chip-input:checked + .chip {
|
|
75
|
+
background-color: var(--md-sys-color-secondary-container);
|
|
76
|
+
color: var(--md-sys-color-on-secondary-container);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.chip-input:focus-visible + .chip {
|
|
80
|
+
@include focus-ring();
|
|
30
81
|
}
|
|
31
82
|
|
|
32
83
|
.chip.outlined {
|
|
@@ -49,6 +100,7 @@
|
|
|
49
100
|
color: var(--md-sys-color-on-surface-variant);
|
|
50
101
|
}
|
|
51
102
|
|
|
103
|
+
// The delete affordance is a real <button>, so it needs the button reset too.
|
|
52
104
|
.chip .close {
|
|
53
105
|
border-radius: 50%;
|
|
54
106
|
height: 24px;
|
|
@@ -58,10 +110,17 @@
|
|
|
58
110
|
justify-content: center;
|
|
59
111
|
align-content: center;
|
|
60
112
|
cursor: pointer;
|
|
113
|
+
appearance: none;
|
|
114
|
+
border: 0;
|
|
115
|
+
background: none;
|
|
116
|
+
color: inherit;
|
|
117
|
+
font: inherit;
|
|
118
|
+
|
|
119
|
+
@include focus-visible();
|
|
61
120
|
}
|
|
62
121
|
|
|
63
122
|
.chip .close:hover {
|
|
64
|
-
background-color: color-mix(in oklab, var(--md-sys-color-on-surface-variant)
|
|
123
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface-variant) state-opacity("hover"), transparent);
|
|
65
124
|
}
|
|
66
125
|
|
|
67
126
|
//--------------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@use "../abstracts" as *;
|
|
2
2
|
|
|
3
|
-
.datepicker-container {
|
|
3
|
+
:is(.datepicker-container, .date-picker-container) {
|
|
4
4
|
display: flex;
|
|
5
5
|
flex-direction: column;
|
|
6
6
|
max-width: 325px;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
background-color: var(--md-sys-color-surface);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
.datepicker-controls {
|
|
11
|
+
:is(.datepicker-controls, .date-picker-controls) {
|
|
12
12
|
display: flex;
|
|
13
13
|
justify-content: space-between;
|
|
14
14
|
width: 280px;
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
/* Date Display */
|
|
89
|
-
.datepicker-date-display {
|
|
89
|
+
:is(.datepicker-date-display, .date-picker-date-display) {
|
|
90
90
|
flex: 1 auto;
|
|
91
91
|
// @removed since v2.2.1-dev regarding Material M3 standards
|
|
92
92
|
// background-color: var(--md-sys-color-primary);
|
|
@@ -118,11 +118,11 @@
|
|
|
118
118
|
|
|
119
119
|
|
|
120
120
|
/* Calendar */
|
|
121
|
-
.datepicker-calendar-container {
|
|
121
|
+
:is(.datepicker-calendar-container, .date-picker-calendar-container) {
|
|
122
122
|
flex: 2.5 auto;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
.datepicker-table {
|
|
125
|
+
:is(.datepicker-table, .date-picker-table) {
|
|
126
126
|
width: 280px;
|
|
127
127
|
font-size: 1rem;
|
|
128
128
|
margin: 0 auto;
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
color: var(--md-sys-color-on-surface-variant);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
.datepicker-day {
|
|
148
|
+
:is(.datepicker-day, .date-picker-day) {
|
|
149
149
|
padding: 0;
|
|
150
150
|
color: var(--md-sys-color-on-background);
|
|
151
151
|
// border-radius: 50%;
|
|
@@ -162,17 +162,17 @@
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
// @todo
|
|
165
|
-
.datepicker-day.has-event {}
|
|
165
|
+
:is(.datepicker-day, .date-picker-day).has-event {}
|
|
166
166
|
// @todo
|
|
167
|
-
.datepicker-day.is-inrange {}
|
|
167
|
+
:is(.datepicker-day, .date-picker-day).is-inrange {}
|
|
168
168
|
// @todo
|
|
169
|
-
.datepicker-day.is-startrange {}
|
|
169
|
+
:is(.datepicker-day, .date-picker-day).is-startrange {}
|
|
170
170
|
// @todo
|
|
171
|
-
.datepicker-day.is-endrange {}
|
|
171
|
+
:is(.datepicker-day, .date-picker-day).is-endrange {}
|
|
172
172
|
|
|
173
|
-
.datepicker-day.is-daterange-start,
|
|
174
|
-
.datepicker-day.is-daterange-end,
|
|
175
|
-
.datepicker-day.is-daterange {
|
|
173
|
+
:is(.datepicker-day, .date-picker-day).is-daterange-start,
|
|
174
|
+
:is(.datepicker-day, .date-picker-day).is-daterange-end,
|
|
175
|
+
:is(.datepicker-day, .date-picker-day).is-daterange {
|
|
176
176
|
position: relative;
|
|
177
177
|
|
|
178
178
|
&:before {
|
|
@@ -186,20 +186,20 @@
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
.datepicker-day.is-daterange-start:before,
|
|
190
|
-
.datepicker-day.is-daterange-end:before {
|
|
189
|
+
:is(.datepicker-day, .date-picker-day).is-daterange-start:before,
|
|
190
|
+
:is(.datepicker-day, .date-picker-day).is-daterange-end:before {
|
|
191
191
|
width: 50%;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
.datepicker-day.is-daterange-start:before {
|
|
194
|
+
:is(.datepicker-day, .date-picker-day).is-daterange-start:before {
|
|
195
195
|
left: 50%;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
.datepicker-day.is-daterange .datepicker-day-button:before {
|
|
198
|
+
:is(.datepicker-day, .date-picker-day).is-daterange :is(.datepicker-day-button, .date-picker-day-button):before {
|
|
199
199
|
background-color: var(--md-sys-color-primary-container);
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
.datepicker-day-button {
|
|
202
|
+
:is(.datepicker-day-button, .date-picker-day-button) {
|
|
203
203
|
background-color: transparent;
|
|
204
204
|
border: none;
|
|
205
205
|
line-height: 34px;
|
|
@@ -239,7 +239,7 @@
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
/* Footer */
|
|
242
|
-
.datepicker-footer {
|
|
242
|
+
:is(.datepicker-footer, .date-picker-footer) {
|
|
243
243
|
width: 280px;
|
|
244
244
|
margin: 0 auto;
|
|
245
245
|
padding-bottom: 5px;
|
|
@@ -247,15 +247,15 @@
|
|
|
247
247
|
justify-content: space-between;
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
-
.datepicker-cancel,
|
|
251
|
-
.datepicker-clear,
|
|
252
|
-
.datepicker-today,
|
|
253
|
-
.datepicker-done {
|
|
250
|
+
:is(.datepicker-cancel, .date-picker-cancel),
|
|
251
|
+
:is(.datepicker-clear, .date-picker-clear),
|
|
252
|
+
:is(.datepicker-today, .date-picker-today),
|
|
253
|
+
:is(.datepicker-done, .date-picker-done) {
|
|
254
254
|
color: var(--md-sys-color-primary);
|
|
255
255
|
padding: 0 1rem;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
-
.datepicker-clear {
|
|
258
|
+
:is(.datepicker-clear, .date-picker-clear) {
|
|
259
259
|
color: var(--md-sys-color-error);
|
|
260
260
|
}
|
|
261
261
|
|
|
@@ -39,7 +39,7 @@ dialog {
|
|
|
39
39
|
@include z-depth("3");
|
|
40
40
|
|
|
41
41
|
&::backdrop {
|
|
42
|
-
background-color:
|
|
42
|
+
background-color: var(--md-comp-scrim-color);
|
|
43
43
|
backdrop-filter: blur(var(--md-comp-basic-dialog-scrim-blur));
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -59,7 +59,7 @@ dialog[open] {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
// Optional leading icon (M3 basic dialog).
|
|
62
|
-
dialog >
|
|
62
|
+
dialog > #{$icon}:first-child {
|
|
63
63
|
flex: 0 0 auto;
|
|
64
64
|
align-self: center;
|
|
65
65
|
margin: 24px 24px 0;
|
|
@@ -78,7 +78,7 @@ dialog > :is(h1, h2, h3, h4, h5, h6) {
|
|
|
78
78
|
@include typescale("headline-small");
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
dialog >
|
|
81
|
+
dialog > #{$icon}:first-child + :is(h1, h2, h3, h4, h5, h6) {
|
|
82
82
|
padding-top: 16px;
|
|
83
83
|
text-align: center;
|
|
84
84
|
}
|
|
@@ -98,7 +98,7 @@ dialog > p {
|
|
|
98
98
|
@include typescale("body-medium");
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
dialog >
|
|
101
|
+
dialog > #{$icon}:first-child + :is(h1, h2, h3, h4, h5, h6) + p {
|
|
102
102
|
text-align: center;
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -150,11 +150,12 @@ dialog:not(
|
|
|
150
150
|
.right-sheet,
|
|
151
151
|
.left,
|
|
152
152
|
.left-sheet,
|
|
153
|
-
.
|
|
154
|
-
.sidenav-
|
|
153
|
+
.floating-sheet,
|
|
154
|
+
:is(.sidenav, .navigation-drawer),
|
|
155
|
+
:is(.sidenav-overlay, .navigation-drawer-overlay)
|
|
155
156
|
)
|
|
156
157
|
> :is(form, nav):last-child
|
|
157
|
-
> :is(button, a.button):not(.tonal, .outlined, .elevated, .filled) {
|
|
158
|
+
> :is(button, a.button):not(.tonal, .outlined, .elevated, .filled, .icon-button) {
|
|
158
159
|
@include btn-flat;
|
|
159
160
|
}
|
|
160
161
|
|
|
@@ -215,7 +216,12 @@ dialog.max {
|
|
|
215
216
|
}
|
|
216
217
|
|
|
217
218
|
// Close is a 48dp icon button. 4dp bar inset + 12dp to the glyph = 16dp.
|
|
218
|
-
|
|
219
|
+
// `:only-child` counts elements, not text nodes, so `<button><span icon/>
|
|
220
|
+
// Save</button>` reads as icon-only and would be squeezed into the 48dp
|
|
221
|
+
// circle. CSS cannot see the text node; `.button` is the author's opt-out,
|
|
222
|
+
// and sends such an action to the general button rules instead. Same
|
|
223
|
+
// escape hatch the app bar already has.
|
|
224
|
+
> header > :is(button, a):not(.button, .icon-button):has(> #{$icon}:only-child) {
|
|
219
225
|
display: inline-flex;
|
|
220
226
|
flex: 0 0 48px;
|
|
221
227
|
align-items: center;
|
|
@@ -231,7 +237,7 @@ dialog.max {
|
|
|
231
237
|
color: var(--md-sys-color-on-surface-variant);
|
|
232
238
|
box-shadow: none;
|
|
233
239
|
|
|
234
|
-
>
|
|
240
|
+
> #{$icon} {
|
|
235
241
|
font-size: 24px;
|
|
236
242
|
width: 24px;
|
|
237
243
|
height: 24px;
|
|
@@ -239,7 +245,7 @@ dialog.max {
|
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
&:hover {
|
|
242
|
-
background-color: color-mix(in oklab, var(--md-sys-color-on-surface)
|
|
248
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) state-opacity("hover"), transparent);
|
|
243
249
|
}
|
|
244
250
|
|
|
245
251
|
&:focus-visible {
|
|
@@ -249,7 +255,7 @@ dialog.max {
|
|
|
249
255
|
}
|
|
250
256
|
|
|
251
257
|
// Confirming action in the header is a text button, not an icon.
|
|
252
|
-
> header :is(button, a.button):not(:has(>
|
|
258
|
+
> header :is(button, a.button):not(:has(> #{$icon}:only-child)) {
|
|
253
259
|
@include btn-flat;
|
|
254
260
|
width: auto;
|
|
255
261
|
min-width: 0;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
@use "../abstracts" as *;
|
|
2
|
+
|
|
3
|
+
// Drag handles.
|
|
4
|
+
//
|
|
5
|
+
// Anatomy is the HTML. A .drag-handle is the handle, and which element it is
|
|
6
|
+
// says what it is: a <span aria-hidden="true"> when it is only an affordance -
|
|
7
|
+
// the usual case - and a <button> with a name when something is genuinely wired
|
|
8
|
+
// to it. semantics.json enforces exactly that split, which is what lets the
|
|
9
|
+
// interactive states below key off `button` and be right every time.
|
|
10
|
+
//
|
|
11
|
+
// **Nothing here drags.** The handle is CSS; the dragging is the page's, and so
|
|
12
|
+
// is the keyboard path to whatever the drag achieves. A handle that answers
|
|
13
|
+
// only a pointer puts its outcome out of reach of everyone not using one, so
|
|
14
|
+
// the framework ships no reordering behaviour to hang off this and the docs say
|
|
15
|
+
// plainly that a drag-only reorder is unreachable. The decorative spelling is
|
|
16
|
+
// the default; the button spelling has to earn its name.
|
|
17
|
+
//
|
|
18
|
+
// M3 Expressive tokenised the *vertical* handle - the one sitting in the gutter
|
|
19
|
+
// between two panes, Compose's VerticalDragHandle: a 4x48dp bar in a 24dp
|
|
20
|
+
// container that swells to 12x52dp on a medium corner while it is held. That is
|
|
21
|
+
// md.comp.drag-handle and it is what this partial draws.
|
|
22
|
+
//
|
|
23
|
+
// The bottom sheet's grabber is a different component with a different token
|
|
24
|
+
// set - md.comp.sheet-bottom.docked.drag-handle, a horizontal 32x4dp bar at 40%
|
|
25
|
+
// on-surface-variant - so a .drag-handle inside a sheet takes the sheet's
|
|
26
|
+
// geometry from _bottom-sheet.scss rather than carrying a `horizontal` modifier
|
|
27
|
+
// here. One class, two hosts, and neither one's values invented.
|
|
28
|
+
//
|
|
29
|
+
// Tokens follow md.comp.drag-handle.* (DSP 34.0.21):
|
|
30
|
+
// container 24dp wide - the hit target, not the bar
|
|
31
|
+
// bar 4 x 48dp, corner.full, outline
|
|
32
|
+
// pressed 12 x 52dp, corner.medium, on-surface
|
|
33
|
+
// state layer inverse-on-surface, 8% hover / 10% focus
|
|
34
|
+
// elevation level0 at rest and pressed alike, so there is nothing to draw
|
|
35
|
+
//
|
|
36
|
+
// Two departures, both deliberate. M3 publishes a container *width* and no
|
|
37
|
+
// container height, leaving the container to take whatever height it is given;
|
|
38
|
+
// this pins it to the pressed bar so that holding the handle cannot reflow what
|
|
39
|
+
// is beside it, which a stretched container would also achieve but only where
|
|
40
|
+
// the host happens to stretch it. And Compose distinguishes a *dragged* state
|
|
41
|
+
// from a pressed one - draggedSize, draggedShape, draggedColor, checked before
|
|
42
|
+
// isPressed - which the web token set does not publish and CSS could not select
|
|
43
|
+
// anyway: there is no "is being dragged" pseudo-class, and nothing here drags.
|
|
44
|
+
// `:active` covers both, at the pressed values.
|
|
45
|
+
.drag-handle {
|
|
46
|
+
--md-comp-drag-handle-container-width: 24px;
|
|
47
|
+
--md-comp-drag-handle-width: 4px;
|
|
48
|
+
--md-comp-drag-handle-height: 48px;
|
|
49
|
+
--md-comp-drag-handle-shape: 9999px;
|
|
50
|
+
--md-comp-drag-handle-color: var(--md-sys-color-outline);
|
|
51
|
+
--md-comp-drag-handle-pressed-width: 12px;
|
|
52
|
+
--md-comp-drag-handle-pressed-height: 52px;
|
|
53
|
+
--md-comp-drag-handle-pressed-shape: 12px;
|
|
54
|
+
--md-comp-drag-handle-pressed-color: var(--md-sys-color-on-surface);
|
|
55
|
+
--md-comp-drag-handle-state-layer-color: var(--md-sys-color-inverse-on-surface);
|
|
56
|
+
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
flex: 0 0 auto;
|
|
60
|
+
align-items: center;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
// The container is the hit target, and it is sized to the *pressed* bar
|
|
63
|
+
// rather than the resting one so that swelling the bar moves nothing beside
|
|
64
|
+
// it. M3 gives the container a width and no height for the same reason.
|
|
65
|
+
inline-size: var(--md-comp-drag-handle-container-width);
|
|
66
|
+
block-size: var(--md-comp-drag-handle-pressed-height);
|
|
67
|
+
margin: 0;
|
|
68
|
+
padding: 0;
|
|
69
|
+
border: 0;
|
|
70
|
+
border-radius: var(--md-comp-drag-handle-shape);
|
|
71
|
+
background-color: transparent;
|
|
72
|
+
cursor: grab;
|
|
73
|
+
appearance: none;
|
|
74
|
+
-webkit-tap-highlight-color: transparent;
|
|
75
|
+
|
|
76
|
+
// The bar. It is a pseudo-element and not the box itself because the box is
|
|
77
|
+
// the hit target: 4dp of anything is not something a pointer can be asked to
|
|
78
|
+
// find, and the state layer needs a surface the bar's own shape does not clip.
|
|
79
|
+
&::before {
|
|
80
|
+
content: "";
|
|
81
|
+
display: block;
|
|
82
|
+
inline-size: var(--md-comp-drag-handle-width);
|
|
83
|
+
block-size: var(--md-comp-drag-handle-height);
|
|
84
|
+
border-radius: var(--md-comp-drag-handle-shape);
|
|
85
|
+
background-color: var(--md-comp-drag-handle-color);
|
|
86
|
+
transition: inline-size .15s ease, block-size .15s ease, border-radius .15s ease,
|
|
87
|
+
background-color .15s ease;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Interactive states belong to the button spelling alone. A decorative handle
|
|
92
|
+
// is not a control and must not light up under a pointer that merely crosses
|
|
93
|
+
// it - and because the rule keying this is `button`, the semantics rule holding
|
|
94
|
+
// every other element to aria-hidden is what keeps the two in step.
|
|
95
|
+
button.drag-handle {
|
|
96
|
+
&:hover {
|
|
97
|
+
background-color: color-mix(
|
|
98
|
+
in oklab,
|
|
99
|
+
var(--md-comp-drag-handle-state-layer-color) state-opacity("hover"),
|
|
100
|
+
transparent
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&:focus-visible {
|
|
105
|
+
background-color: color-mix(
|
|
106
|
+
in oklab,
|
|
107
|
+
var(--md-comp-drag-handle-state-layer-color) state-opacity("focus"),
|
|
108
|
+
transparent
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@include focus-visible;
|
|
113
|
+
|
|
114
|
+
&:active {
|
|
115
|
+
cursor: grabbing;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&:active::before {
|
|
119
|
+
inline-size: var(--md-comp-drag-handle-pressed-width);
|
|
120
|
+
block-size: var(--md-comp-drag-handle-pressed-height);
|
|
121
|
+
border-radius: var(--md-comp-drag-handle-pressed-shape);
|
|
122
|
+
background-color: var(--md-comp-drag-handle-pressed-color);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@media (prefers-reduced-motion: reduce) {
|
|
127
|
+
.drag-handle::before {
|
|
128
|
+
transition: none;
|
|
129
|
+
}
|
|
130
|
+
}
|