@expressivecss/expressive 0.7.0 → 0.9.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 +1313 -1
- package/README.md +76 -30
- package/dist/css/expressive.css +4896 -1777
- 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/fonts/LICENSE-material-symbols +93 -0
- package/dist/fonts/LICENSE-noto-sans +93 -0
- package/dist/fonts/LICENSE-roboto +93 -0
- package/dist/fonts/material-symbols-outlined.woff2 +0 -0
- package/dist/fonts/material-symbols-rounded.woff2 +0 -0
- package/dist/fonts/material-symbols-sharp.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-400.woff2 +0 -0
- package/dist/fonts/noto-sans-latin-500.woff2 +0 -0
- package/dist/fonts/roboto-latin-400.woff2 +0 -0
- package/dist/fonts/roboto-latin-500.woff2 +0 -0
- package/dist/js/expressive.cjs +1673 -1338
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +1673 -1338
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +13 -13
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +1673 -1338
- 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/appBar.d.ts +26 -0
- package/dist/types/components/autocomplete.d.ts +15 -3
- package/dist/types/components/buttonGroup.d.ts +39 -0
- package/dist/types/components/buttons.d.ts +5 -1
- package/dist/types/components/cards.d.ts +11 -13
- 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 +23 -20
- package/dist/types/components/lightbox.d.ts +1 -0
- package/dist/types/components/menu.d.ts +11 -1
- package/dist/types/components/{sidenav.d.ts → navigationDrawer.d.ts} +16 -16
- package/dist/types/components/registry.d.ts +18 -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 -10
- package/dist/types/components/tooltip.d.ts +1 -0
- package/dist/types/core/utils.d.ts +64 -53
- package/dist/types/index.d.ts +8 -9
- package/package.json +39 -3
- package/src/sass/README.md +61 -11
- package/src/sass/abstracts/_breakpoints.scss +17 -19
- package/src/sass/abstracts/_mixins.scss +155 -21
- package/src/sass/abstracts/_variables.scss +69 -5
- package/src/sass/base/_fonts.scss +63 -0
- 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 +3 -5
- 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 +358 -0
- package/src/sass/components/_buttons.scss +245 -92
- package/src/sass/components/_cards.scss +514 -78
- 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 +226 -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 +172 -0
- package/src/sass/components/_icons-material-design.scss +22 -10
- 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 +245 -45
- package/src/sass/components/_navigation-bar.scss +22 -11
- package/src/sass/components/{_sidenav.scss → _navigation-drawer.scss} +123 -33
- package/src/sass/components/_navigation-rail.scss +31 -23
- 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/_transitions.scss +8 -1
- 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 +38 -1
- package/src/sass/components/forms/{_range.scss → _slider.scss} +8 -9
- package/src/sass/components/forms/_switches.scss +6 -7
- package/src/sass/expressive.scss +5 -0
- 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
|
@@ -137,7 +137,7 @@ $_sheet: "dialog.side-sheet, dialog.right, dialog.right-sheet, dialog.left, dial
|
|
|
137
137
|
color: var(--md-sys-color-on-surface-variant);
|
|
138
138
|
box-shadow: none;
|
|
139
139
|
|
|
140
|
-
>
|
|
140
|
+
> #{$icon} {
|
|
141
141
|
font-size: 24px;
|
|
142
142
|
width: 24px;
|
|
143
143
|
height: 24px;
|
|
@@ -145,7 +145,7 @@ $_sheet: "dialog.side-sheet, dialog.right, dialog.right-sheet, dialog.left, dial
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
&:hover {
|
|
148
|
-
background-color: color-mix(in oklab, var(--md-sys-color-on-surface)
|
|
148
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) state-opacity("hover"), transparent);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
&:focus-visible {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// action label-large / inverse-primary text button
|
|
15
15
|
// close 24dp icon, inverse-on-surface
|
|
16
16
|
// inset 8dp compact, 24dp from the bottom on larger screens
|
|
17
|
-
// placement bottom of the UI; centered from the
|
|
17
|
+
// placement bottom of the UI; centered from the Medium breakpoint
|
|
18
18
|
//
|
|
19
19
|
// Snackbars must not interrupt browsing: the container is pointer-events
|
|
20
20
|
// none except on the bar, and the live region is polite. One at a time
|
|
@@ -48,7 +48,7 @@ $_bar: ".snackbar";
|
|
|
48
48
|
pointer-events: auto;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
@include bp-up("
|
|
51
|
+
@include bp-up("medium") {
|
|
52
52
|
--md-comp-snackbar-container-margin-leading: 24px;
|
|
53
53
|
--md-comp-snackbar-container-margin-trailing: 24px;
|
|
54
54
|
--md-comp-snackbar-container-margin-bottom: 24px;
|
|
@@ -78,6 +78,11 @@ $_bar: ".snackbar";
|
|
|
78
78
|
--md-comp-snackbar-icon-color: var(--md-sys-color-inverse-on-surface);
|
|
79
79
|
|
|
80
80
|
box-sizing: border-box;
|
|
81
|
+
// Swipe-to-dismiss is horizontal, so claim that axis and leave vertical
|
|
82
|
+
// panning to the page. Without this the browser takes a horizontal swipe for
|
|
83
|
+
// itself and cancels the drag mid-gesture: `preventDefault()` on a
|
|
84
|
+
// `pointermove` cannot stop it the way it stopped a `touchmove`.
|
|
85
|
+
touch-action: pan-y;
|
|
81
86
|
display: flex;
|
|
82
87
|
align-items: center;
|
|
83
88
|
gap: 8px;
|
|
@@ -95,7 +100,7 @@ $_bar: ".snackbar";
|
|
|
95
100
|
@include z-depth("3");
|
|
96
101
|
cursor: default;
|
|
97
102
|
|
|
98
|
-
@include bp-up("
|
|
103
|
+
@include bp-up("medium") {
|
|
99
104
|
width: max-content;
|
|
100
105
|
min-width: min(344px, 100%);
|
|
101
106
|
}
|
|
@@ -116,7 +121,7 @@ $_bar: ".snackbar";
|
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
// Optional leading icon (BeerCSS). M3 snackbars have no leading icon.
|
|
119
|
-
>
|
|
124
|
+
> #{$icon}:first-child {
|
|
120
125
|
flex: 0 0 auto;
|
|
121
126
|
font-size: 24px;
|
|
122
127
|
width: 24px;
|
|
@@ -126,7 +131,7 @@ $_bar: ".snackbar";
|
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
// Inline links in the supporting text use the action color.
|
|
129
|
-
a:not(.button) {
|
|
134
|
+
a:not(.button, .icon-button) {
|
|
130
135
|
color: var(--md-comp-snackbar-action-label-text-color);
|
|
131
136
|
}
|
|
132
137
|
|
|
@@ -145,8 +150,8 @@ $_bar: ".snackbar";
|
|
|
145
150
|
}
|
|
146
151
|
|
|
147
152
|
// Text action — inverse-primary, not the filled common-button default.
|
|
148
|
-
> :is(button, a.button):not(.circle),
|
|
149
|
-
> nav > :is(button, a.button):not(.circle) {
|
|
153
|
+
> :is(button, a.button):not(.circle, .icon-button),
|
|
154
|
+
> nav > :is(button, a.button):not(.circle, .icon-button) {
|
|
150
155
|
flex: 0 0 auto;
|
|
151
156
|
height: 40px;
|
|
152
157
|
min-width: 48px;
|
|
@@ -159,12 +164,12 @@ $_bar: ".snackbar";
|
|
|
159
164
|
@include typescale("label-large");
|
|
160
165
|
|
|
161
166
|
&:hover {
|
|
162
|
-
background-color: color-mix(in oklab, var(--md-sys-color-inverse-primary)
|
|
167
|
+
background-color: color-mix(in oklab, var(--md-sys-color-inverse-primary) state-opacity("hover"), transparent);
|
|
163
168
|
}
|
|
164
169
|
|
|
165
170
|
&:active,
|
|
166
171
|
&:focus {
|
|
167
|
-
background-color: color-mix(in oklab, var(--md-sys-color-inverse-primary)
|
|
172
|
+
background-color: color-mix(in oklab, var(--md-sys-color-inverse-primary) state-opacity("focus"), transparent);
|
|
168
173
|
}
|
|
169
174
|
|
|
170
175
|
&:focus-visible {
|
|
@@ -186,7 +191,7 @@ $_bar: ".snackbar";
|
|
|
186
191
|
color: var(--md-comp-snackbar-icon-color);
|
|
187
192
|
box-shadow: none;
|
|
188
193
|
|
|
189
|
-
>
|
|
194
|
+
> #{$icon} {
|
|
190
195
|
font-size: 24px;
|
|
191
196
|
width: 24px;
|
|
192
197
|
height: 24px;
|
|
@@ -194,12 +199,12 @@ $_bar: ".snackbar";
|
|
|
194
199
|
}
|
|
195
200
|
|
|
196
201
|
&:hover {
|
|
197
|
-
background-color: color-mix(in oklab, var(--md-sys-color-inverse-on-surface)
|
|
202
|
+
background-color: color-mix(in oklab, var(--md-sys-color-inverse-on-surface) state-opacity("hover"), transparent);
|
|
198
203
|
}
|
|
199
204
|
|
|
200
205
|
&:active,
|
|
201
206
|
&:focus {
|
|
202
|
-
background-color: color-mix(in oklab, var(--md-sys-color-inverse-on-surface)
|
|
207
|
+
background-color: color-mix(in oklab, var(--md-sys-color-inverse-on-surface) state-opacity("focus"), transparent);
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
&:focus-visible {
|
|
@@ -226,7 +231,7 @@ $_bar: ".snackbar";
|
|
|
226
231
|
|
|
227
232
|
// Static overlay. In-flow without this (docs previews). Not AutoInit —
|
|
228
233
|
// add and remove the class yourself, or use the constructor for timing.
|
|
229
|
-
// Default: bottom of the UI, centered from the
|
|
234
|
+
// Default: bottom of the UI, centered from the Medium breakpoint.
|
|
230
235
|
#{$_bar}.active {
|
|
231
236
|
position: fixed;
|
|
232
237
|
z-index: 10000;
|
|
@@ -238,7 +243,7 @@ $_bar: ".snackbar";
|
|
|
238
243
|
width: max-content;
|
|
239
244
|
max-width: min(672px, calc(100% - 48px));
|
|
240
245
|
|
|
241
|
-
@include bp-down("
|
|
246
|
+
@include bp-down("medium") {
|
|
242
247
|
left: 8px;
|
|
243
248
|
right: 8px;
|
|
244
249
|
bottom: max(8px, env(safe-area-inset-bottom, 0px));
|
|
@@ -251,7 +256,7 @@ $_bar: ".snackbar";
|
|
|
251
256
|
top: 24px;
|
|
252
257
|
bottom: auto;
|
|
253
258
|
|
|
254
|
-
@include bp-down("
|
|
259
|
+
@include bp-down("medium") {
|
|
255
260
|
top: 8px;
|
|
256
261
|
left: 8px;
|
|
257
262
|
right: 8px;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
@use "sass:map";
|
|
2
|
+
@use "../abstracts" as *;
|
|
3
|
+
|
|
4
|
+
// Split buttons.
|
|
5
|
+
//
|
|
6
|
+
// Anatomy is the HTML. A <div class="split-button"> holding two buttons: a
|
|
7
|
+
// leading one that performs the action, and a trailing `.menu-trigger` that
|
|
8
|
+
// opens a <menu> of related ones. They sit 2dp apart, the outside of the pair
|
|
9
|
+
// is round, and the seam between them is square-ish until something happens
|
|
10
|
+
// to it.
|
|
11
|
+
//
|
|
12
|
+
// Both halves are ordinary buttons, so every style class works on them and
|
|
13
|
+
// nothing here restates a colour. What this partial owns is the pair: the
|
|
14
|
+
// seam, the two insets that differ from a lone button's, and the larger
|
|
15
|
+
// trailing icon.
|
|
16
|
+
//
|
|
17
|
+
// No composite role is declared. The two halves are two Tab stops doing two
|
|
18
|
+
// different things - `toolbar` and its nine siblings promise an arrow-key
|
|
19
|
+
// model this is not (SEMANTICS rule 2). The menu the trailing half opens has
|
|
20
|
+
// its own keyboard contract, which Menu implements and owns.
|
|
21
|
+
//
|
|
22
|
+
// `aria-expanded` on the trailing half is Menu's to write, not the author's
|
|
23
|
+
// (SEMANTICS rule 1) - which is exactly why the expanded shape can be drawn
|
|
24
|
+
// from a selector with no script of this component's own.
|
|
25
|
+
//
|
|
26
|
+
// Tokens are md.comp.split-button.{xsmall … xlarge} (DSP 34.0.21). Five
|
|
27
|
+
// families collapse to one here the way the button's own ladder does: the
|
|
28
|
+
// size class rewrites the tokens and the two halves map them onto the button
|
|
29
|
+
// tokens once, below.
|
|
30
|
+
//
|
|
31
|
+
// size height lead-start lead-end trail-space trail-icon inner swollen
|
|
32
|
+
// xsmall 32 12 10 13 22 4 8
|
|
33
|
+
// small 40 16 12 13 22 4 12
|
|
34
|
+
// medium 56 24 24 15 26 4 12
|
|
35
|
+
// large 96 48 48 29 38 8 20
|
|
36
|
+
// xlarge 136 64 64 43 50 12 20
|
|
37
|
+
//
|
|
38
|
+
// `lead-start` is the button ladder's own `space` at every size, so it is not
|
|
39
|
+
// restated - `button-size()` sets it and the leading half keeps it. Only the
|
|
40
|
+
// inset facing the seam is the split button's, and only at the two smallest
|
|
41
|
+
// sizes does it actually differ. `between-space` is 2dp in all five families,
|
|
42
|
+
// so it is written once for the same reason.
|
|
43
|
+
|
|
44
|
+
// The two halves. The trailing one *is* the menu trigger: `.menu-trigger`
|
|
45
|
+
// with a target is the JS contract Menu claims, and a split button whose
|
|
46
|
+
// trailing half opened nothing would be a lone button with a decoration
|
|
47
|
+
// glued to it. semantics.json enforces that.
|
|
48
|
+
//
|
|
49
|
+
// `:where()`, not `:is()`: `:is()` takes the specificity of its heaviest
|
|
50
|
+
// argument, so `a.button` would make `> $_half:hover` a class heavier than
|
|
51
|
+
// `> $_trail[aria-expanded]` - and hovering an open split button would
|
|
52
|
+
// collapse the seam Material says stays round for as long as the menu is up.
|
|
53
|
+
//
|
|
54
|
+
// `.icon-button` is deliberately not a half. It is its own component with its
|
|
55
|
+
// own size ladder, insets, colours and icon sizing, all set on the element by
|
|
56
|
+
// its own rule - so the container could not size it by handing it tokens, and
|
|
57
|
+
// the seam here would fight the shape it already draws. Button groups refuse
|
|
58
|
+
// it for the same reason. The trailing half is a `.button.menu-trigger`.
|
|
59
|
+
$_lead: ":where(button:not(.icon-button), a.button):not(.menu-trigger)";
|
|
60
|
+
$_trail: ".menu-trigger:not(.icon-button)";
|
|
61
|
+
$_half: ":where(button:not(.icon-button), a.button)";
|
|
62
|
+
|
|
63
|
+
// md.comp.split-button.<size>.{leading-button.trailing-space,
|
|
64
|
+
// trailing-button.leading-space, trailing.icon-size, inner-corner,
|
|
65
|
+
// inner-pressed-corner}. The hovered and pressed inner corners are the same
|
|
66
|
+
// value in all five families, so one token carries both states.
|
|
67
|
+
$_sizes: (
|
|
68
|
+
"xsmall": (lead-end: 10px, trail-space: 13px, trail-icon: 22px, inner: 4px, swollen: 8px),
|
|
69
|
+
"small": (lead-end: 12px, trail-space: 13px, trail-icon: 22px, inner: 4px, swollen: 12px),
|
|
70
|
+
"medium": (lead-end: 24px, trail-space: 15px, trail-icon: 26px, inner: 4px, swollen: 12px),
|
|
71
|
+
"large": (lead-end: 48px, trail-space: 29px, trail-icon: 38px, inner: 8px, swollen: 20px),
|
|
72
|
+
"xlarge": (lead-end: 64px, trail-space: 43px, trail-icon: 50px, inner: 12px, swollen: 20px),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// The two ladders are keyed alike and read together, so a size added to one
|
|
76
|
+
// and not the other would emit `--token: ;` - a dropped declaration with no
|
|
77
|
+
// error and no visible cause. Fail the build instead.
|
|
78
|
+
@if map.keys($_sizes) != map.keys($button-sizes) {
|
|
79
|
+
@error "$_sizes and $button-sizes must name the same five sizes; got " +
|
|
80
|
+
map.keys($_sizes) + " against " + map.keys($button-sizes) + ".";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@mixin _split-size($name) {
|
|
84
|
+
$s: map.get($_sizes, $name);
|
|
85
|
+
|
|
86
|
+
--md-comp-split-button-leading-button-trailing-space: #{map.get($s, lead-end)};
|
|
87
|
+
--md-comp-split-button-trailing-button-space: #{map.get($s, trail-space)};
|
|
88
|
+
--md-comp-split-button-trailing-icon-size: #{map.get($s, trail-icon)};
|
|
89
|
+
--md-comp-split-button-inner-corner-corner-size: #{map.get($s, inner)};
|
|
90
|
+
--md-comp-split-button-inner-pressed-corner-corner-size: #{map.get($s, swollen)};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.split-button {
|
|
94
|
+
--md-comp-split-button-between-space: 2px;
|
|
95
|
+
--md-comp-split-button-container-shape: 9999px;
|
|
96
|
+
|
|
97
|
+
@include button-size("small");
|
|
98
|
+
@include _split-size("small");
|
|
99
|
+
|
|
100
|
+
display: inline-flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
gap: var(--md-comp-split-button-between-space);
|
|
103
|
+
|
|
104
|
+
// The size axis. Height, icon size, the leading inset and the outline width
|
|
105
|
+
// are the button ladder's, so `button-size()` sets them on the container and
|
|
106
|
+
// both halves inherit; the five values that are the split button's own are
|
|
107
|
+
// beside it. The type role cannot travel that way - `btn` states a font-size
|
|
108
|
+
// of its own - so it is set on the halves.
|
|
109
|
+
@each $name, $s in $button-sizes {
|
|
110
|
+
&.#{$name} {
|
|
111
|
+
@include button-size($name);
|
|
112
|
+
@include _split-size($name);
|
|
113
|
+
|
|
114
|
+
> #{$_half} {
|
|
115
|
+
@include typescale(map.get($s, label));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The seam goes through a variable so that hovering, pressing or opening
|
|
121
|
+
// changes one value rather than restating `border-radius`. A shorthand under
|
|
122
|
+
// `:hover` would take the round outer corners with it, which is the bug
|
|
123
|
+
// `_button-groups.scss` records.
|
|
124
|
+
> #{$_half} {
|
|
125
|
+
--_inner: var(--md-comp-split-button-inner-corner-corner-size);
|
|
126
|
+
|
|
127
|
+
// `btn` transitions background-color and box-shadow; restating the
|
|
128
|
+
// property list replaces it wholesale, so both have to be named again or
|
|
129
|
+
// an `.elevated` split button snaps its shadow where every other elevated
|
|
130
|
+
// button eases it.
|
|
131
|
+
transition: border-radius .2s ease-out, background-color .2s ease-out,
|
|
132
|
+
box-shadow .2s ease-out;
|
|
133
|
+
|
|
134
|
+
// M3 gives hovered and pressed the same swollen corner.
|
|
135
|
+
&:hover,
|
|
136
|
+
&:active {
|
|
137
|
+
--_inner: var(--md-comp-split-button-inner-pressed-corner-corner-size);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Logical, so the outside of the pair is the outside of the pair in RTL too:
|
|
142
|
+
// the flex row reverses and start follows it.
|
|
143
|
+
> #{$_lead} {
|
|
144
|
+
--md-comp-filled-button-trailing-space: var(--md-comp-split-button-leading-button-trailing-space);
|
|
145
|
+
|
|
146
|
+
border-start-start-radius: var(--md-comp-split-button-container-shape);
|
|
147
|
+
border-end-start-radius: var(--md-comp-split-button-container-shape);
|
|
148
|
+
border-start-end-radius: var(--_inner);
|
|
149
|
+
border-end-end-radius: var(--_inner);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
> #{$_trail} {
|
|
153
|
+
// Symmetric, and narrower than a lone button's - the trailing half is a
|
|
154
|
+
// glyph in a box, not a label. The width falls out of the two insets and
|
|
155
|
+
// the icon: 48dp at the two smallest sizes, square at the three largest.
|
|
156
|
+
--md-comp-filled-button-leading-space: var(--md-comp-split-button-trailing-button-space);
|
|
157
|
+
--md-comp-filled-button-trailing-space: var(--md-comp-split-button-trailing-button-space);
|
|
158
|
+
// `_buttons.scss` sizes a button's icon from this token, so rewriting it
|
|
159
|
+
// here is the whole of the override. M3 draws the trailing glyph larger
|
|
160
|
+
// than the button ladder's icon at every size (22 against 20, up to 50
|
|
161
|
+
// against 40).
|
|
162
|
+
--md-comp-filled-button-icon-size: var(--md-comp-split-button-trailing-icon-size);
|
|
163
|
+
|
|
164
|
+
border-start-end-radius: var(--md-comp-split-button-container-shape);
|
|
165
|
+
border-end-end-radius: var(--md-comp-split-button-container-shape);
|
|
166
|
+
border-start-start-radius: var(--_inner);
|
|
167
|
+
border-end-start-radius: var(--_inner);
|
|
168
|
+
|
|
169
|
+
// Activation. md.comp.split-button.<size>.trailing.inner-selected-corner
|
|
170
|
+
// is 50%, and Compose resolves a percentage corner against the shape's
|
|
171
|
+
// *smaller* dimension - 20dp on the 48x40 half at `small`, which is what
|
|
172
|
+
// `9999px` clamps to. The two agree at every size, and the outer corners
|
|
173
|
+
// are the same 50% written the same way. So the pair reads as two
|
|
174
|
+
// separated round buttons for as long as the menu is open. Menu writes the
|
|
175
|
+
// attribute; nothing here is scripted.
|
|
176
|
+
&[aria-expanded="true"] {
|
|
177
|
+
--_inner: var(--md-comp-split-button-container-shape);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
> #{$icon} {
|
|
181
|
+
transition: transform .2s ease-out;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
&[aria-expanded="true"] > #{$icon} {
|
|
185
|
+
transform: rotate(180deg);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// The corner morph and the spin are the only motion this component has.
|
|
191
|
+
@media (prefers-reduced-motion: reduce) {
|
|
192
|
+
.split-button > #{$_half},
|
|
193
|
+
.split-button > #{$_trail} > #{$icon} {
|
|
194
|
+
transition: none;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -83,10 +83,9 @@ $_tab: "> a, > .tab > a";
|
|
|
83
83
|
cursor: pointer;
|
|
84
84
|
appearance: none;
|
|
85
85
|
@include typescale("title-small");
|
|
86
|
-
font-family: $font-stack;
|
|
87
86
|
transition: color .2s ease, background-color .2s ease;
|
|
88
87
|
|
|
89
|
-
>
|
|
88
|
+
> #{$icon} {
|
|
90
89
|
flex: 0 0 auto;
|
|
91
90
|
font-size: var(--md-comp-primary-tab-icon-size);
|
|
92
91
|
width: var(--md-comp-primary-tab-icon-size);
|
|
@@ -97,13 +96,13 @@ $_tab: "> a, > .tab > a";
|
|
|
97
96
|
|
|
98
97
|
&:hover {
|
|
99
98
|
color: var(--md-sys-color-on-surface);
|
|
100
|
-
background-color: color-mix(in oklab, var(--md-sys-color-on-surface)
|
|
99
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) state-opacity("hover"), transparent);
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
&:focus-visible,
|
|
104
103
|
&:focus {
|
|
105
104
|
color: var(--md-sys-color-on-surface);
|
|
106
|
-
background-color: color-mix(in oklab, var(--md-sys-color-on-surface)
|
|
105
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) state-opacity("focus"), transparent);
|
|
107
106
|
outline: none;
|
|
108
107
|
}
|
|
109
108
|
|
|
@@ -113,12 +112,12 @@ $_tab: "> a, > .tab > a";
|
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
&.active:hover {
|
|
116
|
-
background-color: color-mix(in oklab, var(--md-sys-color-primary)
|
|
115
|
+
background-color: color-mix(in oklab, var(--md-sys-color-primary) state-opacity("hover"), transparent);
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
&.active:focus-visible,
|
|
120
119
|
&.active:focus {
|
|
121
|
-
background-color: color-mix(in oklab, var(--md-sys-color-primary)
|
|
120
|
+
background-color: color-mix(in oklab, var(--md-sys-color-primary) state-opacity("focus"), transparent);
|
|
122
121
|
}
|
|
123
122
|
|
|
124
123
|
// Disabled — on the <a>. The wrapping `.tab.disabled` case is
|
|
@@ -135,7 +134,7 @@ $_tab: "> a, > .tab > a";
|
|
|
135
134
|
// Stacked icon + label is 64dp (primary).
|
|
136
135
|
&:not(.horizontal) {
|
|
137
136
|
#{$_tab} {
|
|
138
|
-
&:has(>
|
|
137
|
+
&:has(> #{$icon}) {
|
|
139
138
|
min-height: var(--md-comp-primary-tab-with-icon-container-height);
|
|
140
139
|
padding-block: 8px;
|
|
141
140
|
}
|
|
@@ -210,7 +209,7 @@ $_tab: "> a, > .tab > a";
|
|
|
210
209
|
}
|
|
211
210
|
}
|
|
212
211
|
|
|
213
|
-
@include bp-down("
|
|
212
|
+
@include bp-down("expanded") {
|
|
214
213
|
.tabs {
|
|
215
214
|
> :is(a, .tab) {
|
|
216
215
|
flex: 1 1 0;
|