@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
|
@@ -1,39 +1,75 @@
|
|
|
1
|
+
@use "sass:map";
|
|
1
2
|
@use "../abstracts" as *;
|
|
2
3
|
|
|
3
4
|
// Common buttons and FABs.
|
|
4
5
|
//
|
|
5
6
|
// Anatomy is the HTML. A <button> (or <a class="button">) is a filled
|
|
6
7
|
// common button. Put an <i> first or last for a leading/trailing icon.
|
|
7
|
-
// Icon-only is a 40dp icon button.
|
|
8
|
-
// (tonal, outlined, elevated, text)
|
|
8
|
+
// Icon-only is a 40dp icon button. Two independent modifier axes dress it:
|
|
9
|
+
// a style (filled, tonal, outlined, elevated, text) and a size (xsmall …
|
|
10
|
+
// xlarge).
|
|
9
11
|
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
12
|
+
// Nine classes, not twenty-five. The size rules set tokens and the style
|
|
13
|
+
// rules set colours, so every combination falls out of the cascade and no
|
|
14
|
+
// rule names both. `tests/buttons.test.js` fails if one starts to.
|
|
15
|
+
//
|
|
16
|
+
// Tokens follow M3 Expressive, md.comp.button.* (DSP 34.0.21):
|
|
17
|
+
// the size ladder in abstracts, corner.full at every size
|
|
13
18
|
// state layer 8% hover / 10% focus+press
|
|
14
19
|
// FAB 56dp (extra/large icon-only), primary-container, 16dp corners
|
|
20
|
+
// FAB sizes 40dp small / 56dp default / 80dp medium / 96dp large,
|
|
21
|
+
// 24 / 24 / 26 / 36dp icon, 12 / 16 / 20 / 28dp corners
|
|
22
|
+
|
|
23
|
+
// The size axis is `$button-sizes` in abstracts, and `button-size()` sets its
|
|
24
|
+
// tokens. Both moved there when button groups grew a size ladder of their own:
|
|
25
|
+
// a group sizes its items from the group, so it needs the same table, and a
|
|
26
|
+
// partial may not @use another partial.
|
|
15
27
|
|
|
16
|
-
:root {
|
|
28
|
+
:root, :host {
|
|
17
29
|
--md-comp-filled-button-container-color: var(--md-sys-color-primary);
|
|
18
30
|
--md-comp-filled-button-label-text-color: var(--md-sys-color-on-primary);
|
|
19
|
-
--md-comp-filled-button-container-
|
|
20
|
-
|
|
21
|
-
--md-comp-filled-button-leading-space: 24px;
|
|
22
|
-
--md-comp-filled-button-trailing-space: 24px;
|
|
23
|
-
--md-comp-filled-button-with-icon-leading-space: 16px;
|
|
24
|
-
--md-comp-filled-button-icon-size: 18px;
|
|
25
|
-
--md-comp-filled-button-icon-label-space: 8px;
|
|
31
|
+
--md-comp-filled-button-container-shape: 9999px;
|
|
32
|
+
@include button-size("small");
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
// Widget chrome that happens to be a <button> — not a common button.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
//
|
|
37
|
+
// `.chip` earns its place here now that assist and suggestion chips are real
|
|
38
|
+
// buttons. The base rules were harmless (`.chip` and `:where(…):not(…)` are
|
|
39
|
+
// both one class, and chips is forwarded after buttons, so the chip won), but
|
|
40
|
+
// the state rules are not: `:where(…):not(…):hover` is *two* — a class from
|
|
41
|
+
// the `:not()` and the pseudo-class — so hovering, focusing or pressing a chip
|
|
42
|
+
// repainted it with the filled-button background while it kept the chip's own
|
|
43
|
+
// text colour.
|
|
44
|
+
//
|
|
45
|
+
// `.icon-button` is here because it is its own component (M3 gives it its own
|
|
46
|
+
// token families, size ladder and colours), not a common button in a round
|
|
47
|
+
// shape. Without the exclusion it would inherit 40dp geometry and a filled
|
|
48
|
+
// primary container before its own partial ever ran.
|
|
49
|
+
//
|
|
50
|
+
// Every entry stays a single class so the `:not()` keeps its one-class
|
|
51
|
+
// specificity; `.chip .close` would make it two and shift every button rule.
|
|
52
|
+
// The delete button needs no entry: `.chip .close` is already two classes, so
|
|
53
|
+
// it ties the state rules and wins on order.
|
|
54
|
+
$_not-btn: ".datepicker-day-button, .date-picker-day-button, .month-prev, .month-next, .chip, .icon-button";
|
|
55
|
+
|
|
56
|
+
// `label.button` is here for the file input: the control has to be a <label>
|
|
57
|
+
// so that clicking it reaches the <input type="file"> it wraps, but it is a
|
|
58
|
+
// button to look at and to use. Without it the label fell through to the
|
|
59
|
+
// floating-label rule in forms/_input-fields and rendered as invisible,
|
|
60
|
+
// unclickable field furniture.
|
|
61
|
+
// `.btn` is the pre-1.0 name and is deliberately NOT in this list. A
|
|
62
|
+
// <button class="btn"> is styled because it is a <button>; an <a class="btn">
|
|
63
|
+
// is not, and making it so means adding `.btn` to the twenty-odd `:not()`
|
|
64
|
+
// lists that let hosts (footer, drawer, app bar, rail, list, snackbar) step
|
|
65
|
+
// aside for a button - an invariant with no test behind it, for markup that
|
|
66
|
+
// has a working spelling. `a.button` is that spelling, and the docs say so.
|
|
67
|
+
$_btn: "button:not(#{$_not-btn}), a.button, label.button";
|
|
32
68
|
|
|
33
69
|
:where(#{$_btn}) {
|
|
34
70
|
@include btn;
|
|
35
71
|
|
|
36
|
-
>
|
|
72
|
+
> #{$icon} {
|
|
37
73
|
flex: 0 0 auto;
|
|
38
74
|
font-size: var(--md-comp-filled-button-icon-size);
|
|
39
75
|
width: var(--md-comp-filled-button-icon-size);
|
|
@@ -42,34 +78,31 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
42
78
|
overflow: hidden;
|
|
43
79
|
}
|
|
44
80
|
|
|
45
|
-
// :only-child ignores text nodes, so "<i>add</i>Create" would look like
|
|
46
|
-
// an icon button. Wrap the label in a <span> (BeerCSS) for the 16dp
|
|
47
|
-
// leading inset; otherwise the icon still sits on the flex gap.
|
|
48
|
-
&:has(> i + span) {
|
|
49
|
-
padding-inline-start: var(--md-comp-filled-button-with-icon-leading-space);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
&:has(> span + i) {
|
|
53
|
-
padding-inline-end: var(--md-comp-filled-button-with-icon-leading-space);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
81
|
// Icon button — opt in with .circle. Do not infer from :only-child.
|
|
82
|
+
//
|
|
83
|
+
// Shape only. The glyph is the size rule's, like every other button's: a
|
|
84
|
+
// `.circle` is a common button wearing a round shape, and `.icon-button` is
|
|
85
|
+
// the component that carries the icon *button* ladder. It used to pin 24px
|
|
86
|
+
// here - `md.comp.icon-button.small.icon-size`, right for the 40dp default
|
|
87
|
+
// and wrong for every other rung, most visibly a 24px glyph adrift in an
|
|
88
|
+
// `xlarge` 136dp disc. The FAB overrides both, further down.
|
|
57
89
|
&.circle {
|
|
58
90
|
width: var(--md-comp-filled-button-container-height);
|
|
59
91
|
padding: 0;
|
|
60
92
|
border-radius: 50%;
|
|
61
|
-
|
|
62
|
-
> i {
|
|
63
|
-
font-size: 24px;
|
|
64
|
-
width: 24px;
|
|
65
|
-
height: 24px;
|
|
66
|
-
line-height: 24px;
|
|
67
|
-
}
|
|
68
93
|
}
|
|
69
94
|
}
|
|
70
95
|
|
|
71
|
-
//
|
|
72
|
-
|
|
96
|
+
// The style axis. Filled is the default, so it is both the styleless case and
|
|
97
|
+
// a class of its own - the two are one rule, because a second `@include
|
|
98
|
+
// btn-filled` would duplicate every state layer in it.
|
|
99
|
+
//
|
|
100
|
+
// They are separate selectors rather than `:is(.filled, :not(…))` on purpose:
|
|
101
|
+
// `:is()` takes the specificity of its heaviest argument, which would lift the
|
|
102
|
+
// default case to one class and let it outrank rules that legitimately beat it
|
|
103
|
+
// today. A selector list keeps each half its own weight.
|
|
104
|
+
:where(#{$_btn}):not(.tonal, .outlined, .elevated, .text),
|
|
105
|
+
:where(#{$_btn}).filled {
|
|
73
106
|
@include btn-filled;
|
|
74
107
|
}
|
|
75
108
|
|
|
@@ -89,48 +122,90 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
89
122
|
@include btn-flat;
|
|
90
123
|
}
|
|
91
124
|
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
font-size: var(--md-sys-typescale-label-medium-font-size);
|
|
125
|
+
// The size classes. Every one of them sets tokens and a type role and nothing
|
|
126
|
+
// else - the geometry is already written once, in `btn`, against those tokens.
|
|
127
|
+
// A size that declared `height` itself would have to be restated by anything
|
|
128
|
+
// that overrides it, which is how the per-combination rules start.
|
|
129
|
+
@each $name, $s in $button-sizes {
|
|
130
|
+
:where(#{$_btn}).#{$name} {
|
|
131
|
+
@include button-size($name);
|
|
132
|
+
@include typescale(map.get($s, label));
|
|
133
|
+
}
|
|
102
134
|
}
|
|
103
135
|
|
|
104
|
-
|
|
136
|
+
// `.extra` is the pre-1.0 name for the 56dp button, which is now `.medium`.
|
|
137
|
+
// It aliases the geometry and not the type role, because it never carried
|
|
138
|
+
// one: a rail's FAB is `a.button.extra`, its label is label-large, and
|
|
139
|
+
// `.medium`'s title-medium would grow it. Size, not size-and-label.
|
|
140
|
+
//
|
|
141
|
+
// It is also the FAB's marker class - `circle extra` is a FAB, and the rules
|
|
142
|
+
// below reset this geometry entirely.
|
|
105
143
|
:where(#{$_btn}).extra {
|
|
106
|
-
|
|
107
|
-
--md-comp-filled-button-container-shape: 28px;
|
|
108
|
-
--md-comp-filled-button-leading-space: 24px;
|
|
109
|
-
--md-comp-filled-button-trailing-space: 24px;
|
|
110
|
-
--md-comp-filled-button-with-icon-leading-space: 16px;
|
|
111
|
-
--md-comp-filled-button-icon-size: 24px;
|
|
112
|
-
height: 56px;
|
|
144
|
+
@include button-size("medium");
|
|
113
145
|
}
|
|
114
146
|
|
|
147
|
+
// Every size is corner.full already, so this only bites when a consumer has
|
|
148
|
+
// themed the shape token to something squarer and wants one button back.
|
|
115
149
|
:where(#{$_btn}).rounded {
|
|
116
150
|
border-radius: 9999px;
|
|
117
151
|
}
|
|
118
152
|
|
|
119
|
-
// Extended FAB:
|
|
153
|
+
// Extended FAB: an icon plus a label, on its own size and colour axes.
|
|
154
|
+
//
|
|
155
|
+
// Tokens (M3 md.comp.extended-fab.*, DSP 34.0.21). The sizeless case is the
|
|
156
|
+
// base family; the three named sizes are `md.comp.extended-fab.{size}.*`:
|
|
157
|
+
//
|
|
158
|
+
// size height shape icon lead gap trail label
|
|
159
|
+
// (none) 56 16 24 16 8 20 label-large
|
|
160
|
+
// small 56 16 24 16 8 16 title-medium
|
|
161
|
+
// medium 80 20 28 26 12 26 title-large
|
|
162
|
+
// large 96 28 36 28 16 28 headline-small
|
|
163
|
+
//
|
|
164
|
+
// Leading and trailing space are equal at every named size, so the map states
|
|
165
|
+
// one `space`; only the base family keeps M3's older 16/20 asymmetry.
|
|
166
|
+
//
|
|
167
|
+
// The colour axis is M3's three container roles, and it runs through two
|
|
168
|
+
// tokens rather than a background per variant: the state layers mix the label
|
|
169
|
+
// colour into the container colour, so a role that only sets the two tokens
|
|
170
|
+
// gets its own hover and focus for free.
|
|
171
|
+
//
|
|
172
|
+
// `font-size` is restated because the size classes are the same one class
|
|
173
|
+
// this rule is: `.small` sets label-large from the common-button ladder and
|
|
174
|
+
// would otherwise decide the label of an `extend small`.
|
|
175
|
+
$_extend-sizes: (
|
|
176
|
+
"small": (height: 56px, shape: 16px, icon: 24px, space: 16px, gap: 8px, label: "title-medium"),
|
|
177
|
+
"medium": (height: 80px, shape: 20px, icon: 28px, space: 26px, gap: 12px, label: "title-large"),
|
|
178
|
+
"large": (height: 96px, shape: 28px, icon: 36px, space: 28px, gap: 16px, label: "headline-small"),
|
|
179
|
+
);
|
|
180
|
+
|
|
120
181
|
:where(#{$_btn}).extend {
|
|
121
|
-
height: 56px;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
182
|
+
--md-comp-extended-fab-container-height: 56px;
|
|
183
|
+
--md-comp-extended-fab-container-shape: 16px;
|
|
184
|
+
--md-comp-extended-fab-icon-size: 24px;
|
|
185
|
+
--md-comp-extended-fab-leading-space: 16px;
|
|
186
|
+
--md-comp-extended-fab-icon-label-space: 8px;
|
|
187
|
+
--md-comp-extended-fab-trailing-space: 20px;
|
|
188
|
+
--md-comp-extended-fab-container-color: var(--md-sys-color-primary-container);
|
|
189
|
+
--md-comp-extended-fab-label-text-color: var(
|
|
190
|
+
--md-sys-color-on-primary-container
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
gap: var(--md-comp-extended-fab-icon-label-space);
|
|
194
|
+
height: var(--md-comp-extended-fab-container-height);
|
|
195
|
+
padding-inline: var(--md-comp-extended-fab-leading-space)
|
|
196
|
+
var(--md-comp-extended-fab-trailing-space);
|
|
197
|
+
border-radius: var(--md-comp-extended-fab-container-shape);
|
|
198
|
+
font-size: var(--md-sys-typescale-label-large-font-size);
|
|
199
|
+
color: var(--md-comp-extended-fab-label-text-color);
|
|
200
|
+
background-color: var(--md-comp-extended-fab-container-color);
|
|
126
201
|
@include z-depth("3");
|
|
127
202
|
|
|
128
203
|
&:hover {
|
|
129
204
|
@include z-depth("4");
|
|
130
205
|
background-color: color-mix(
|
|
131
206
|
in oklab,
|
|
132
|
-
var(--md-
|
|
133
|
-
var(--md-
|
|
207
|
+
var(--md-comp-extended-fab-label-text-color) state-opacity("hover"),
|
|
208
|
+
var(--md-comp-extended-fab-container-color)
|
|
134
209
|
);
|
|
135
210
|
}
|
|
136
211
|
|
|
@@ -138,33 +213,74 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
138
213
|
&:focus {
|
|
139
214
|
background-color: color-mix(
|
|
140
215
|
in oklab,
|
|
141
|
-
var(--md-
|
|
142
|
-
var(--md-
|
|
216
|
+
var(--md-comp-extended-fab-label-text-color) state-opacity("focus"),
|
|
217
|
+
var(--md-comp-extended-fab-container-color)
|
|
143
218
|
);
|
|
144
219
|
}
|
|
145
220
|
|
|
146
221
|
@include focus-visible;
|
|
147
222
|
|
|
148
|
-
>
|
|
149
|
-
font-size:
|
|
150
|
-
width:
|
|
151
|
-
height:
|
|
152
|
-
line-height:
|
|
223
|
+
> #{$icon} {
|
|
224
|
+
font-size: var(--md-comp-extended-fab-icon-size);
|
|
225
|
+
width: var(--md-comp-extended-fab-icon-size);
|
|
226
|
+
height: var(--md-comp-extended-fab-icon-size);
|
|
227
|
+
line-height: var(--md-comp-extended-fab-icon-size);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// The size axis. Every size sets the same six tokens and its type role -
|
|
231
|
+
// the geometry is written once, above, against those tokens.
|
|
232
|
+
@each $name, $s in $_extend-sizes {
|
|
233
|
+
&.#{$name} {
|
|
234
|
+
--md-comp-extended-fab-container-height: #{map.get($s, height)};
|
|
235
|
+
--md-comp-extended-fab-container-shape: #{map.get($s, shape)};
|
|
236
|
+
--md-comp-extended-fab-icon-size: #{map.get($s, icon)};
|
|
237
|
+
--md-comp-extended-fab-leading-space: #{map.get($s, space)};
|
|
238
|
+
--md-comp-extended-fab-icon-label-space: #{map.get($s, gap)};
|
|
239
|
+
--md-comp-extended-fab-trailing-space: #{map.get($s, space)};
|
|
240
|
+
@include typescale(map.get($s, label));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// The colour axis. `.primary-container` is the default and is named anyway,
|
|
245
|
+
// so all three roles are a class a page can be written with.
|
|
246
|
+
@each $role in ("primary", "secondary", "tertiary") {
|
|
247
|
+
&.#{$role}-container {
|
|
248
|
+
--md-comp-extended-fab-container-color: var(
|
|
249
|
+
--md-sys-color-#{$role}-container
|
|
250
|
+
);
|
|
251
|
+
--md-comp-extended-fab-label-text-color: var(
|
|
252
|
+
--md-sys-color-on-#{$role}-container
|
|
253
|
+
);
|
|
254
|
+
}
|
|
153
255
|
}
|
|
154
256
|
}
|
|
155
257
|
|
|
156
258
|
// FAB. Icon-only .extra / .large is the 56dp regular FAB. Add .small for
|
|
157
|
-
// the 40dp small FAB. The speed-dial host is .
|
|
259
|
+
// the 40dp small FAB. The speed-dial host is .fab.
|
|
260
|
+
//
|
|
261
|
+
// Tokens (M3 md.comp.fab.*):
|
|
262
|
+
// --md-comp-fab-container-height 56dp
|
|
263
|
+
// --md-comp-fab-container-width 56dp
|
|
264
|
+
// --md-comp-fab-container-shape 16dp, corner.large - rounded, not a pill
|
|
265
|
+
// --md-comp-fab-icon-size 24dp
|
|
266
|
+
// .small, .medium and .extra.large reset those four; nothing else varies
|
|
267
|
+
// by size.
|
|
158
268
|
:where(#{$_btn}).extra.circle,
|
|
159
269
|
:where(#{$_btn}).large.circle {
|
|
270
|
+
--md-comp-fab-container-height: 56px;
|
|
271
|
+
--md-comp-fab-container-width: 56px;
|
|
272
|
+
--md-comp-fab-container-shape: 16px;
|
|
273
|
+
--md-comp-fab-icon-size: 24px;
|
|
274
|
+
|
|
160
275
|
display: inline-flex;
|
|
276
|
+
flex: none;
|
|
161
277
|
align-items: center;
|
|
162
278
|
justify-content: center;
|
|
163
|
-
width:
|
|
164
|
-
height:
|
|
279
|
+
width: var(--md-comp-fab-container-width);
|
|
280
|
+
height: var(--md-comp-fab-container-height);
|
|
165
281
|
padding: 0;
|
|
166
282
|
border: none;
|
|
167
|
-
border-radius:
|
|
283
|
+
border-radius: var(--md-comp-fab-container-shape);
|
|
168
284
|
color: var(--md-sys-color-on-primary-container);
|
|
169
285
|
background-color: var(--md-sys-color-primary-container);
|
|
170
286
|
text-decoration: none;
|
|
@@ -174,11 +290,11 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
174
290
|
@include z-depth("3");
|
|
175
291
|
@include focus-visible;
|
|
176
292
|
|
|
177
|
-
>
|
|
178
|
-
font-size:
|
|
179
|
-
width:
|
|
180
|
-
height:
|
|
181
|
-
line-height:
|
|
293
|
+
> #{$icon} {
|
|
294
|
+
font-size: var(--md-comp-fab-icon-size);
|
|
295
|
+
width: var(--md-comp-fab-icon-size);
|
|
296
|
+
height: var(--md-comp-fab-icon-size);
|
|
297
|
+
line-height: var(--md-comp-fab-icon-size);
|
|
182
298
|
color: inherit;
|
|
183
299
|
}
|
|
184
300
|
|
|
@@ -186,7 +302,7 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
186
302
|
@include z-depth("4");
|
|
187
303
|
background-color: color-mix(
|
|
188
304
|
in oklab,
|
|
189
|
-
var(--md-sys-color-on-primary-container)
|
|
305
|
+
var(--md-sys-color-on-primary-container) state-opacity("hover"),
|
|
190
306
|
var(--md-sys-color-primary-container)
|
|
191
307
|
);
|
|
192
308
|
}
|
|
@@ -195,19 +311,25 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
195
311
|
&:focus {
|
|
196
312
|
background-color: color-mix(
|
|
197
313
|
in oklab,
|
|
198
|
-
var(--md-sys-color-on-primary-container)
|
|
314
|
+
var(--md-sys-color-on-primary-container) state-opacity("focus"),
|
|
199
315
|
var(--md-sys-color-primary-container)
|
|
200
316
|
);
|
|
201
317
|
}
|
|
202
318
|
|
|
319
|
+
// Small FAB: 40dp container, corner.medium, icon stays 24dp.
|
|
203
320
|
&.small {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
321
|
+
--md-comp-fab-container-height: 40px;
|
|
322
|
+
--md-comp-fab-container-width: 40px;
|
|
323
|
+
--md-comp-fab-container-shape: 12px;
|
|
324
|
+
}
|
|
207
325
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
326
|
+
// Medium FAB: 80dp container, 26dp icon. The corner continues the size
|
|
327
|
+
// ladder - 12dp small, 16dp default, 20dp here (corner.large-increased).
|
|
328
|
+
&.medium {
|
|
329
|
+
--md-comp-fab-container-height: 80px;
|
|
330
|
+
--md-comp-fab-container-width: 80px;
|
|
331
|
+
--md-comp-fab-container-shape: 20px;
|
|
332
|
+
--md-comp-fab-icon-size: 26px;
|
|
211
333
|
}
|
|
212
334
|
|
|
213
335
|
&.halfway-fab {
|
|
@@ -222,15 +344,34 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
222
344
|
}
|
|
223
345
|
}
|
|
224
346
|
|
|
347
|
+
// Large FAB: 96dp container, corner.extra-large, 36dp icon.
|
|
348
|
+
//
|
|
349
|
+
// `.large` is *also* the alias for the default FAB - `circle large` is
|
|
350
|
+
// `circle extra` - so the size only applies next to `.extra`, and the markup
|
|
351
|
+
// is `circle extra large`. Nesting it as `&.large` inside the block above
|
|
352
|
+
// would compile `.large.circle.large` as well, and every aliased 56dp FAB on
|
|
353
|
+
// a page would silently grow to 96dp.
|
|
354
|
+
:where(#{$_btn}).extra.circle.large {
|
|
355
|
+
--md-comp-fab-container-height: 96px;
|
|
356
|
+
--md-comp-fab-container-width: 96px;
|
|
357
|
+
--md-comp-fab-container-shape: 28px;
|
|
358
|
+
--md-comp-fab-icon-size: 36px;
|
|
359
|
+
}
|
|
360
|
+
|
|
225
361
|
:where(#{$_btn}):disabled,
|
|
226
362
|
:where(#{$_btn})[disabled],
|
|
227
363
|
:where(#{$_btn}).disabled {
|
|
228
364
|
@include btn-disabled;
|
|
229
365
|
}
|
|
230
366
|
|
|
367
|
+
// The FAB host. M3 names this component "FAB"; `.fixed-action-btn` is the
|
|
368
|
+
// Materialize name and stays as an alias. Interpolate inside :is() - a bare
|
|
369
|
+
// comma list breaks out of its context (see $_bar in _navbar).
|
|
370
|
+
$_fab: ":is(.fab, .fixed-action-btn)";
|
|
371
|
+
|
|
231
372
|
// Speed dial. .active (and :hover when the pointer can hover) opens the
|
|
232
373
|
// menu. Motion is CSS. .click-to-toggle is the markup switch for click
|
|
233
|
-
// mode. .fixed-action-btn
|
|
374
|
+
// mode. `.fab` is the public class; .fixed-action-btn is the old alias.
|
|
234
375
|
//
|
|
235
376
|
// Tokens:
|
|
236
377
|
// --md-comp-fab-offset 16px from the corner
|
|
@@ -241,7 +382,7 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
241
382
|
// --md-comp-fab-easing soft ease-in-out
|
|
242
383
|
// --md-comp-fab-travel center-to-center step into the main disc
|
|
243
384
|
// --md-comp-fab-hidden-transform toward / into the main button
|
|
244
|
-
|
|
385
|
+
#{$_fab} {
|
|
245
386
|
--md-comp-fab-offset: 16px;
|
|
246
387
|
--md-comp-fab-z: 997;
|
|
247
388
|
--md-comp-fab-menu-gap: 16px;
|
|
@@ -409,7 +550,7 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
409
550
|
width: 100%;
|
|
410
551
|
height: 56px;
|
|
411
552
|
|
|
412
|
-
> :is(a, button) >
|
|
553
|
+
> :is(a, button) > #{$icon} {
|
|
413
554
|
opacity: 0;
|
|
414
555
|
}
|
|
415
556
|
|
|
@@ -437,6 +578,18 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
437
578
|
background: transparent;
|
|
438
579
|
box-shadow: none;
|
|
439
580
|
color: var(--md-sys-color-on-primary-container);
|
|
581
|
+
|
|
582
|
+
&:hover {
|
|
583
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-primary-container) state-opacity("hover"), transparent);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
&:focus-visible {
|
|
587
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-primary-container) state-opacity("focus"), transparent);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
&:active {
|
|
591
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-primary-container) state-opacity("pressed"), transparent);
|
|
592
|
+
}
|
|
440
593
|
}
|
|
441
594
|
}
|
|
442
595
|
}
|
|
@@ -454,7 +607,7 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
454
607
|
}
|
|
455
608
|
|
|
456
609
|
@media (hover: hover) {
|
|
457
|
-
|
|
610
|
+
#{$_fab}:not(.click-to-toggle):hover :is(ul, menu) {
|
|
458
611
|
visibility: visible;
|
|
459
612
|
transition-delay: 0s;
|
|
460
613
|
|
|
@@ -467,7 +620,7 @@ $_btn: "button:not(#{$_not-btn}), a.button";
|
|
|
467
620
|
}
|
|
468
621
|
|
|
469
622
|
@media (prefers-reduced-motion: reduce) {
|
|
470
|
-
|
|
623
|
+
#{$_fab} {
|
|
471
624
|
--md-comp-fab-duration: 0s;
|
|
472
625
|
--md-comp-fab-stagger: 0s;
|
|
473
626
|
}
|