@expressivecss/expressive 0.2.0 → 0.4.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/README.md +8 -8
- package/dist/css/expressive.css +1915 -1566
- 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 +1338 -1528
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +1338 -1528
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +10 -20
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +1338 -1529
- package/dist/js/expressive.mjs.map +4 -4
- package/dist/types/components/autocomplete.d.ts +2 -9
- package/dist/types/components/buttons.d.ts +19 -43
- package/dist/types/components/cards.d.ts +3 -6
- package/dist/types/components/carousel.d.ts +42 -48
- package/dist/types/components/characterCounter.d.ts +3 -5
- package/dist/types/components/chips.d.ts +4 -4
- package/dist/types/components/collapsible.d.ts +28 -23
- package/dist/types/components/datepicker.d.ts +2 -8
- package/dist/types/components/dropdown.d.ts +11 -2
- package/dist/types/components/index.d.ts +0 -1
- package/dist/types/components/lightbox.d.ts +2 -2
- package/dist/types/components/parallax.d.ts +7 -37
- package/dist/types/components/pushpin.d.ts +2 -2
- package/dist/types/components/range.d.ts +2 -2
- package/dist/types/components/registry.d.ts +0 -4
- package/dist/types/components/scrollspy.d.ts +26 -50
- package/dist/types/components/select.d.ts +20 -6
- package/dist/types/components/sidenav.d.ts +40 -55
- package/dist/types/components/slider.d.ts +2 -2
- package/dist/types/components/tabs.d.ts +2 -2
- package/dist/types/components/tapTarget.d.ts +25 -26
- package/dist/types/components/timepicker.d.ts +2 -4
- package/dist/types/components/tooltip.d.ts +2 -2
- package/dist/types/core/component.d.ts +4 -4
- package/dist/types/index.d.ts +1 -1
- package/package.json +2 -2
- package/src/sass/README.md +3 -6
- package/src/sass/abstracts/_breakpoints.scss +0 -16
- package/src/sass/abstracts/_variables.scss +0 -21
- package/src/sass/base/_grid.scss +0 -19
- package/src/sass/components/_badges.scss +6 -5
- package/src/sass/components/_breadcrumb.scss +93 -16
- package/src/sass/components/_buttons.scss +212 -145
- package/src/sass/components/_cards.scss +50 -123
- package/src/sass/components/_carousel.scss +128 -63
- package/src/sass/components/_chips.scss +1 -1
- package/src/sass/components/_collapsible.scss +158 -60
- package/src/sass/components/_collection.scss +146 -80
- package/src/sass/components/_datepicker.scss +1 -15
- package/src/sass/components/_dropdown.scss +110 -14
- package/src/sass/components/_icons-material-design.scss +77 -4
- package/src/sass/components/_index.scss +1 -0
- package/src/sass/components/_lightbox.scss +4 -0
- package/src/sass/components/_modal.scss +13 -31
- package/src/sass/components/_navbar.scss +24 -6
- package/src/sass/components/_page-footer.scss +134 -15
- package/src/sass/components/_pagination.scss +131 -25
- package/src/sass/components/_parallax.scss +96 -21
- package/src/sass/components/_preloader.scss +145 -300
- package/src/sass/components/_scrollspy.scss +18 -0
- package/src/sass/components/_sidenav.scss +230 -119
- package/src/sass/components/_slider.scss +8 -0
- package/src/sass/components/_table_of_contents.scss +30 -14
- package/src/sass/components/_tabs.scss +54 -35
- package/src/sass/components/_tapTarget.scss +128 -45
- package/src/sass/components/_toast.scss +10 -11
- package/src/sass/components/_toolbar.scss +2 -2
- package/src/sass/components/_tooltip.scss +4 -9
- package/src/sass/components/_transitions.scss +0 -5
- package/src/sass/components/forms/_index.scss +0 -5
- package/src/sass/components/forms/_input-fields.scss +49 -52
- package/src/sass/components/forms/_select.scss +175 -60
- package/src/sass/components/forms/_switches.scss +21 -8
- package/src/sass/utilities/_helpers.scss +1 -3
- package/src/sass/utilities/_typescale.scss +0 -5
- package/src/sass/utilities/_visibility.scss +2 -2
- package/dist/types/components/modal.d.ts +0 -45
|
@@ -5,26 +5,27 @@
|
|
|
5
5
|
// Anatomy is the HTML. A <menu id> is the surface; each <li> is an item,
|
|
6
6
|
// an <hr> is a divider, and an <i> inside the item is the leading icon.
|
|
7
7
|
// The trigger is still .dropdown-trigger[data-target] — that is the JS
|
|
8
|
-
// contract.
|
|
9
|
-
// still generate it).
|
|
8
|
+
// contract.
|
|
10
9
|
//
|
|
11
10
|
// Tokens follow https://m3.material.io/components/menus/specs
|
|
12
|
-
//
|
|
13
|
-
//
|
|
11
|
+
// plus the 1rem surface / stadium items used by fields and select.
|
|
12
|
+
// container surface, 1rem corners, elevation 2, 112–280dp
|
|
13
|
+
// item 48dp, 2rem corners, label-large / on-surface, 12dp inset
|
|
14
14
|
// leading icon 24dp, on-surface-variant
|
|
15
15
|
// divider 1dp outline-variant
|
|
16
16
|
// state layer 8% hover / 10% selected
|
|
17
17
|
|
|
18
|
+
$_menu-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M10 6l6 6-6 6'/%3E%3C/svg%3E");
|
|
19
|
+
|
|
18
20
|
[popover] {
|
|
19
21
|
outline: none;
|
|
20
22
|
padding: 0;
|
|
21
23
|
border: none;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
.dropdown-content,
|
|
25
26
|
menu[id] {
|
|
26
27
|
--md-comp-menu-container-color: var(--md-sys-color-surface);
|
|
27
|
-
--md-comp-menu-container-shape:
|
|
28
|
+
--md-comp-menu-container-shape: 1rem;
|
|
28
29
|
--md-comp-menu-item-container-height: 48px;
|
|
29
30
|
|
|
30
31
|
box-sizing: border-box;
|
|
@@ -47,6 +48,7 @@ menu[id] {
|
|
|
47
48
|
@include z-depth("2");
|
|
48
49
|
|
|
49
50
|
> li {
|
|
51
|
+
box-sizing: border-box;
|
|
50
52
|
margin: 0;
|
|
51
53
|
padding: 0;
|
|
52
54
|
width: 100%;
|
|
@@ -70,6 +72,11 @@ menu[id] {
|
|
|
70
72
|
color: var(--md-sys-color-on-surface);
|
|
71
73
|
text-decoration: none;
|
|
72
74
|
cursor: pointer;
|
|
75
|
+
|
|
76
|
+
&:hover,
|
|
77
|
+
&:focus {
|
|
78
|
+
background: none;
|
|
79
|
+
}
|
|
73
80
|
@include typescale("label-large");
|
|
74
81
|
font-family: $font-stack;
|
|
75
82
|
}
|
|
@@ -86,6 +93,12 @@ menu[id] {
|
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
|
|
96
|
+
> li:not(.disabled, .divider, .optgroup) {
|
|
97
|
+
width: calc(100% - 16px);
|
|
98
|
+
margin-inline: 8px;
|
|
99
|
+
border-radius: 2rem;
|
|
100
|
+
}
|
|
101
|
+
|
|
89
102
|
> li:not(.disabled, .divider):hover,
|
|
90
103
|
> li.active {
|
|
91
104
|
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) 8%, transparent);
|
|
@@ -108,22 +121,105 @@ menu[id] {
|
|
|
108
121
|
background-color: var(--md-sys-color-outline-variant);
|
|
109
122
|
cursor: default;
|
|
110
123
|
}
|
|
124
|
+
|
|
125
|
+
// Nested flyouts sit outside the list box; do not clip them.
|
|
126
|
+
&:has(> li > menu) {
|
|
127
|
+
overflow: visible;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
li:has(> menu) {
|
|
131
|
+
position: relative;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
li:has(> menu) > :is(a, button, span)::after {
|
|
135
|
+
content: "";
|
|
136
|
+
flex: 0 0 24px;
|
|
137
|
+
width: 24px;
|
|
138
|
+
height: 24px;
|
|
139
|
+
margin-inline-start: auto;
|
|
140
|
+
background-color: var(--md-sys-color-on-surface-variant);
|
|
141
|
+
mask: $_menu-chevron center / 24px no-repeat;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Nested menu. Optional, desktop-first. No second Dropdown instance —
|
|
146
|
+
// a <menu> inside an <li> is a flyout. Hover / :focus-within on fine
|
|
147
|
+
// pointers; .open is the tap / keyboard switch.
|
|
148
|
+
menu[id] li > menu {
|
|
149
|
+
--md-comp-menu-container-color: var(--md-sys-color-surface);
|
|
150
|
+
--md-comp-menu-container-shape: 1rem;
|
|
151
|
+
--md-comp-menu-item-container-height: 48px;
|
|
152
|
+
|
|
153
|
+
box-sizing: border-box;
|
|
154
|
+
display: none;
|
|
155
|
+
position: absolute;
|
|
156
|
+
inset-block-start: 0;
|
|
157
|
+
inset-inline-start: 100%;
|
|
158
|
+
z-index: 1;
|
|
159
|
+
min-width: 112px;
|
|
160
|
+
margin: 0;
|
|
161
|
+
padding: 8px 0;
|
|
162
|
+
list-style: none;
|
|
163
|
+
overflow: visible;
|
|
164
|
+
opacity: 1;
|
|
165
|
+
transform: none;
|
|
166
|
+
background-color: var(--md-comp-menu-container-color);
|
|
167
|
+
border-radius: var(--md-comp-menu-container-shape);
|
|
168
|
+
color: var(--md-sys-color-on-surface);
|
|
169
|
+
@include z-depth("2");
|
|
170
|
+
|
|
171
|
+
> li {
|
|
172
|
+
box-sizing: border-box;
|
|
173
|
+
min-height: var(--md-comp-menu-item-container-height);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
> li:not(.disabled, .divider, .optgroup) {
|
|
177
|
+
width: calc(100% - 16px);
|
|
178
|
+
margin-inline: 8px;
|
|
179
|
+
border-radius: 2rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
> li:not(.disabled, .divider):hover,
|
|
183
|
+
> li.active {
|
|
184
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) 8%, transparent);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
> li > :is(a, button, span) {
|
|
188
|
+
display: flex;
|
|
189
|
+
align-items: center;
|
|
190
|
+
gap: 12px;
|
|
191
|
+
box-sizing: border-box;
|
|
192
|
+
width: 100%;
|
|
193
|
+
min-height: var(--md-comp-menu-item-container-height);
|
|
194
|
+
padding: 0 12px;
|
|
195
|
+
color: var(--md-sys-color-on-surface);
|
|
196
|
+
text-decoration: none;
|
|
197
|
+
@include typescale("label-large");
|
|
198
|
+
font-family: $font-stack;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@media (hover: hover) and (pointer: fine) {
|
|
203
|
+
menu[id] li:is(:hover, :focus-within) > menu {
|
|
204
|
+
display: block;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
menu[id] li.open > menu {
|
|
209
|
+
display: block;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
menu[id] li.submenu-start > menu {
|
|
213
|
+
inset-inline-start: auto;
|
|
214
|
+
inset-inline-end: 100%;
|
|
111
215
|
}
|
|
112
216
|
|
|
113
217
|
body.keyboard-focused {
|
|
114
|
-
.dropdown-content > li:focus,
|
|
115
218
|
menu[id] > li:focus {
|
|
116
219
|
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) 10%, transparent);
|
|
117
220
|
}
|
|
118
221
|
}
|
|
119
222
|
|
|
120
|
-
.input-field.col .dropdown-content [type="checkbox"] + label {
|
|
121
|
-
top: 1px;
|
|
122
|
-
left: 0;
|
|
123
|
-
height: 18px;
|
|
124
|
-
transform: none;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
223
|
.dropdown-trigger {
|
|
128
224
|
cursor: pointer;
|
|
129
225
|
}
|
|
@@ -1,8 +1,81 @@
|
|
|
1
1
|
@use "../abstracts" as *;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
// Material Symbols. The framework does not ship the font files — outlined,
|
|
4
|
+
// rounded, and sharp are three separate variable fonts, and pulling all
|
|
5
|
+
// three into the main sheet would dwarf the rest of the CSS. Load the
|
|
6
|
+
// families you use (see the Icons docs). Outlined with every axis:
|
|
7
|
+
//
|
|
8
|
+
// fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200
|
|
9
|
+
//
|
|
10
|
+
// Style (outlined / rounded / sharp) is the font family, not a variation
|
|
11
|
+
// axis. Switch it with the `icon-style` attribute (same idea as `theme`)
|
|
12
|
+
// or by setting --md-icon-font. Fill, weight, grade, and optical size
|
|
13
|
+
// are axes and inherit as custom properties.
|
|
14
|
+
|
|
15
|
+
:root {
|
|
16
|
+
--md-icon-font-outlined: "Material Symbols Outlined";
|
|
17
|
+
--md-icon-font-rounded: "Material Symbols Rounded";
|
|
18
|
+
--md-icon-font-sharp: "Material Symbols Sharp";
|
|
19
|
+
--md-icon-font: var(--md-icon-font-outlined);
|
|
20
|
+
--md-icon-fill: 0;
|
|
21
|
+
--md-icon-weight: 400;
|
|
22
|
+
--md-icon-grade: 0;
|
|
23
|
+
--md-icon-optical-size: 24;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[icon-style="outlined"] { --md-icon-font: var(--md-icon-font-outlined); }
|
|
27
|
+
[icon-style="rounded"] { --md-icon-font: var(--md-icon-font-rounded); }
|
|
28
|
+
[icon-style="sharp"] { --md-icon-font: var(--md-icon-font-sharp); }
|
|
29
|
+
|
|
30
|
+
$_icon: ".material-symbols, .material-symbols-outlined, .material-symbols-rounded, .material-symbols-sharp, .material-icons";
|
|
31
|
+
|
|
32
|
+
#{$_icon} {
|
|
33
|
+
display: inline-block;
|
|
34
|
+
font-family: var(--md-icon-font);
|
|
35
|
+
font-weight: normal;
|
|
36
|
+
font-style: normal;
|
|
37
|
+
font-size: 24px;
|
|
38
|
+
line-height: 1;
|
|
39
|
+
letter-spacing: normal;
|
|
40
|
+
text-transform: none;
|
|
41
|
+
white-space: nowrap;
|
|
42
|
+
word-wrap: normal;
|
|
43
|
+
direction: ltr;
|
|
44
|
+
user-select: none;
|
|
6
45
|
text-rendering: optimizeLegibility;
|
|
7
|
-
font-feature-settings:
|
|
46
|
+
font-feature-settings: "liga";
|
|
47
|
+
-webkit-font-smoothing: antialiased;
|
|
48
|
+
font-variation-settings:
|
|
49
|
+
"FILL" var(--md-icon-fill),
|
|
50
|
+
"wght" var(--md-icon-weight),
|
|
51
|
+
"GRAD" var(--md-icon-grade),
|
|
52
|
+
"opsz" var(--md-icon-optical-size);
|
|
53
|
+
|
|
54
|
+
// Nest so each class in $_icon gets the suffix. `#{$_icon}.tiny` would
|
|
55
|
+
// only attach `.tiny` to the last item and leave every other icon
|
|
56
|
+
// matching the bare `.material-symbols` selector — including `.large`.
|
|
57
|
+
&.tiny {
|
|
58
|
+
font-size: 1rem;
|
|
59
|
+
--md-icon-optical-size: 20;
|
|
60
|
+
}
|
|
61
|
+
&.small {
|
|
62
|
+
font-size: 2rem;
|
|
63
|
+
--md-icon-optical-size: 24;
|
|
64
|
+
}
|
|
65
|
+
&.medium {
|
|
66
|
+
font-size: 4rem;
|
|
67
|
+
--md-icon-optical-size: 40;
|
|
68
|
+
}
|
|
69
|
+
&.large {
|
|
70
|
+
font-size: 6rem;
|
|
71
|
+
--md-icon-optical-size: 48;
|
|
72
|
+
}
|
|
8
73
|
}
|
|
74
|
+
|
|
75
|
+
// One-off family overrides. These only change --md-icon-font so the
|
|
76
|
+
// inherited fill / weight / grade / opsz still apply.
|
|
77
|
+
.material-symbols-outlined { --md-icon-font: var(--md-icon-font-outlined); }
|
|
78
|
+
.material-symbols-rounded { --md-icon-font: var(--md-icon-font-rounded); }
|
|
79
|
+
.material-symbols-sharp { --md-icon-font: var(--md-icon-font-sharp); }
|
|
80
|
+
|
|
81
|
+
.icon-filled { --md-icon-fill: 1; }
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Anatomy is the HTML. A <dialog> is a basic dialog. A heading is the
|
|
6
6
|
// headline, a <p> (or a wrapping <div>) is supporting text, and the last
|
|
7
|
-
// child <form method="dialog"> or <nav> is the action row.
|
|
8
|
-
// .modal-header / .modal-content / .modal-footer stay as aliases.
|
|
7
|
+
// child <form method="dialog"> or <nav> is the action row.
|
|
9
8
|
//
|
|
10
9
|
// Tokens follow https://m3.material.io/components/dialogs/specs
|
|
11
10
|
// container surface, 28dp corners, 280–560dp, elevation 3
|
|
@@ -16,8 +15,7 @@
|
|
|
16
15
|
// scrim 32% + 12px blur
|
|
17
16
|
// padding 24dp
|
|
18
17
|
|
|
19
|
-
dialog
|
|
20
|
-
.modal {
|
|
18
|
+
dialog {
|
|
21
19
|
--md-comp-basic-dialog-container-color: var(--md-sys-color-surface);
|
|
22
20
|
--md-comp-basic-dialog-container-shape: 28px;
|
|
23
21
|
--md-comp-basic-dialog-container-min-width: 280px;
|
|
@@ -51,8 +49,7 @@ html:has(dialog:modal) {
|
|
|
51
49
|
overflow: hidden;
|
|
52
50
|
}
|
|
53
51
|
|
|
54
|
-
dialog[open]
|
|
55
|
-
.modal[open] {
|
|
52
|
+
dialog[open] {
|
|
56
53
|
display: flex;
|
|
57
54
|
flex-direction: column;
|
|
58
55
|
overflow: hidden;
|
|
@@ -71,8 +68,7 @@ dialog > i:first-child {
|
|
|
71
68
|
color: var(--md-sys-color-secondary);
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
dialog > :is(h1, h2, h3, h4, h5, h6)
|
|
75
|
-
.modal-header {
|
|
71
|
+
dialog > :is(h1, h2, h3, h4, h5, h6) {
|
|
76
72
|
flex: 0 0 auto;
|
|
77
73
|
margin: 0;
|
|
78
74
|
padding: 24px 24px 16px;
|
|
@@ -90,8 +86,7 @@ dialog > i:first-child + :is(h1, h2, h3, h4, h5, h6) {
|
|
|
90
86
|
}
|
|
91
87
|
|
|
92
88
|
dialog > p,
|
|
93
|
-
dialog > div
|
|
94
|
-
.modal-content {
|
|
89
|
+
dialog > div {
|
|
95
90
|
flex: 1 1 auto;
|
|
96
91
|
min-height: 0;
|
|
97
92
|
overflow: auto;
|
|
@@ -106,14 +101,12 @@ dialog > div,
|
|
|
106
101
|
color: color-mix(in oklab, currentColor 72%, transparent);
|
|
107
102
|
}
|
|
108
103
|
|
|
109
|
-
dialog > :is(h1, h2, h3, h4, h5, h6) + p
|
|
110
|
-
.modal-header + .modal-content {
|
|
104
|
+
dialog > :is(h1, h2, h3, h4, h5, h6) + p {
|
|
111
105
|
padding-top: 0;
|
|
112
106
|
}
|
|
113
107
|
|
|
114
108
|
// Action row. form[method=dialog] is the native close mechanism.
|
|
115
|
-
dialog > :is(form, nav):last-child
|
|
116
|
-
.modal-footer {
|
|
109
|
+
dialog > :is(form, nav):last-child {
|
|
117
110
|
display: flex;
|
|
118
111
|
flex-wrap: wrap;
|
|
119
112
|
justify-content: flex-end;
|
|
@@ -126,16 +119,11 @@ dialog > :is(form, nav):last-child,
|
|
|
126
119
|
background: none;
|
|
127
120
|
}
|
|
128
121
|
|
|
129
|
-
.modal-close {
|
|
130
|
-
cursor: pointer;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
122
|
// Full-screen (M3). Takes the viewport; no corners.
|
|
134
123
|
// UA `dialog:modal` sets max-width: calc(100% - 2em - 6px). Without
|
|
135
124
|
// clearing it, width: 100% is capped and a strip of scrim shows on the
|
|
136
125
|
// right. Bottom sheet already overrides this.
|
|
137
|
-
dialog.max
|
|
138
|
-
.modal.max {
|
|
126
|
+
dialog.max {
|
|
139
127
|
width: 100%;
|
|
140
128
|
max-width: none;
|
|
141
129
|
height: 100%;
|
|
@@ -149,8 +137,7 @@ dialog.max,
|
|
|
149
137
|
// the edge against the viewport is square. `left` / `right` also float
|
|
150
138
|
// via the helper utilities (`!important`), so sheets reset that.
|
|
151
139
|
dialog.bottom,
|
|
152
|
-
dialog.bottom-sheet
|
|
153
|
-
.modal.bottom-sheet {
|
|
140
|
+
dialog.bottom-sheet {
|
|
154
141
|
width: 100%;
|
|
155
142
|
min-width: 0;
|
|
156
143
|
max-width: none;
|
|
@@ -161,8 +148,7 @@ dialog.bottom-sheet,
|
|
|
161
148
|
}
|
|
162
149
|
|
|
163
150
|
dialog.top,
|
|
164
|
-
dialog.top-sheet
|
|
165
|
-
.modal.top-sheet {
|
|
151
|
+
dialog.top-sheet {
|
|
166
152
|
width: 100%;
|
|
167
153
|
min-width: 0;
|
|
168
154
|
max-width: none;
|
|
@@ -174,10 +160,8 @@ dialog.top-sheet,
|
|
|
174
160
|
|
|
175
161
|
dialog.left,
|
|
176
162
|
dialog.left-sheet,
|
|
177
|
-
.modal.left-sheet,
|
|
178
163
|
dialog.right,
|
|
179
|
-
dialog.right-sheet
|
|
180
|
-
.modal.right-sheet {
|
|
164
|
+
dialog.right-sheet {
|
|
181
165
|
float: none !important;
|
|
182
166
|
width: min(var(--md-comp-basic-dialog-sheet-width), 85%);
|
|
183
167
|
max-width: none;
|
|
@@ -190,8 +174,7 @@ dialog.right-sheet,
|
|
|
190
174
|
}
|
|
191
175
|
|
|
192
176
|
dialog.left,
|
|
193
|
-
dialog.left-sheet
|
|
194
|
-
.modal.left-sheet {
|
|
177
|
+
dialog.left-sheet {
|
|
195
178
|
inset-inline-start: 0;
|
|
196
179
|
inset-inline-end: auto;
|
|
197
180
|
border-radius: 0 var(--md-comp-basic-dialog-container-shape)
|
|
@@ -199,8 +182,7 @@ dialog.left-sheet,
|
|
|
199
182
|
}
|
|
200
183
|
|
|
201
184
|
dialog.right,
|
|
202
|
-
dialog.right-sheet
|
|
203
|
-
.modal.right-sheet {
|
|
185
|
+
dialog.right-sheet {
|
|
204
186
|
inset-inline-start: auto;
|
|
205
187
|
inset-inline-end: 0;
|
|
206
188
|
border-radius: var(--md-comp-basic-dialog-container-shape) 0 0
|
|
@@ -63,7 +63,7 @@ header:has(> nav) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Icon-only actions — 48dp target, 24dp glyph, 4dp from the container edge.
|
|
66
|
-
> nav:not(.tabs) > :is(a, button):not(.
|
|
66
|
+
> nav:not(.tabs) > :is(a, button):not(.button):not(.circle):not(.extra):has(> i:only-child) {
|
|
67
67
|
display: inline-flex;
|
|
68
68
|
flex: 0 0 auto;
|
|
69
69
|
align-items: center;
|
|
@@ -100,7 +100,7 @@ header:has(> nav) {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
// Text destinations, either loose or grouped in a menu/list.
|
|
103
|
-
> nav:not(.tabs) > a:not(:has(> i:only-child)):not(.
|
|
103
|
+
> nav:not(.tabs) > a:not(:has(> i:only-child)):not(.button):not(.circle):not(.breadcrumb) {
|
|
104
104
|
@extend %app-bar-destination;
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -117,11 +117,29 @@ header:has(> nav) {
|
|
|
117
117
|
align-items: stretch;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
// Direct destinations only. Dropdown JS parks the menu next to the
|
|
121
|
+
// trigger, so a descendant `a` would also paint a square hover on
|
|
122
|
+
// top of the menu's pill.
|
|
123
|
+
> li > a {
|
|
121
124
|
@extend %app-bar-destination;
|
|
122
125
|
}
|
|
123
126
|
}
|
|
124
127
|
|
|
128
|
+
// Breadcrumb trail. Layout only — colors stay on the breadcrumb tokens
|
|
129
|
+
// (which this header remaps to inherit). Do not treat the crumbs as
|
|
130
|
+
// destinations.
|
|
131
|
+
> nav:not(.tabs) > ol {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-wrap: wrap;
|
|
134
|
+
align-items: center;
|
|
135
|
+
align-self: center;
|
|
136
|
+
flex: 1 1 auto;
|
|
137
|
+
min-width: 0;
|
|
138
|
+
list-style: none;
|
|
139
|
+
margin: 0;
|
|
140
|
+
padding-inline: 12px;
|
|
141
|
+
}
|
|
142
|
+
|
|
125
143
|
> nav:not(.tabs) > form {
|
|
126
144
|
display: flex;
|
|
127
145
|
flex: 1 1 auto;
|
|
@@ -278,7 +296,7 @@ header.fixed:has(> nav) {
|
|
|
278
296
|
}
|
|
279
297
|
|
|
280
298
|
// Bottom app bar. 80dp row, icons on the start, a FAB (any .btn) pushed to the end.
|
|
281
|
-
footer:
|
|
299
|
+
footer:has(> nav:only-child) {
|
|
282
300
|
--md-comp-bottom-app-bar-container-color: var(--md-sys-color-surface);
|
|
283
301
|
--md-comp-bottom-app-bar-container-height: 80px;
|
|
284
302
|
|
|
@@ -297,7 +315,7 @@ footer:not(.page-footer):has(> nav) {
|
|
|
297
315
|
margin: 0;
|
|
298
316
|
}
|
|
299
317
|
|
|
300
|
-
> nav:not(.tabs) > :is(a, button):not(.
|
|
318
|
+
> nav:not(.tabs) > :is(a, button):not(.button):not(.circle):not(.extra):has(> i:only-child) {
|
|
301
319
|
display: inline-flex;
|
|
302
320
|
flex: 0 0 auto;
|
|
303
321
|
align-items: center;
|
|
@@ -333,7 +351,7 @@ footer:not(.page-footer):has(> nav) {
|
|
|
333
351
|
}
|
|
334
352
|
}
|
|
335
353
|
|
|
336
|
-
> nav:not(.tabs) > :is(.
|
|
354
|
+
> nav:not(.tabs) > :is(.button, .circle, .extra) {
|
|
337
355
|
margin-inline-start: auto;
|
|
338
356
|
}
|
|
339
357
|
|
|
@@ -1,27 +1,146 @@
|
|
|
1
1
|
@use "../abstracts" as *;
|
|
2
2
|
|
|
3
|
-
.
|
|
3
|
+
// Site footer.
|
|
4
|
+
//
|
|
5
|
+
// Anatomy is the HTML. A <footer> is the landmark. A heading is a column
|
|
6
|
+
// title. A <nav> (or ul) is a link list. The last child <small> is the
|
|
7
|
+
// legal bar. A footer whose only child is a <nav> is the bottom app bar,
|
|
8
|
+
// not this component.
|
|
9
|
+
//
|
|
10
|
+
// Tokens:
|
|
11
|
+
// --md-comp-footer-padding-block 3rem
|
|
12
|
+
// --md-comp-footer-padding-inline 1rem
|
|
13
|
+
// --md-comp-footer-gap 2rem
|
|
14
|
+
// --md-comp-footer-legal-height 48px
|
|
15
|
+
//
|
|
16
|
+
// Unfilled by default (dashed hairline). .filled uses surface-container.
|
|
17
|
+
// There is no JavaScript.
|
|
18
|
+
|
|
19
|
+
footer:not(:has(> nav:only-child)) {
|
|
20
|
+
--md-comp-footer-padding-block: 3rem;
|
|
21
|
+
--md-comp-footer-padding-inline: 1rem;
|
|
22
|
+
--md-comp-footer-gap: 2rem;
|
|
23
|
+
--md-comp-footer-legal-height: 48px;
|
|
24
|
+
|
|
25
|
+
box-sizing: border-box;
|
|
4
26
|
margin-top: 5rem;
|
|
5
|
-
padding
|
|
27
|
+
padding: var(--md-comp-footer-padding-block) var(--md-comp-footer-padding-inline) 1rem;
|
|
6
28
|
border-top: 1px dashed var(--md-sys-color-outline-variant);
|
|
29
|
+
color: var(--md-sys-color-on-surface);
|
|
30
|
+
|
|
7
31
|
p {
|
|
8
|
-
|
|
32
|
+
margin: 0 0 8px;
|
|
33
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
34
|
+
@include typescale("body-medium");
|
|
35
|
+
font-family: $font-stack;
|
|
9
36
|
}
|
|
10
|
-
|
|
37
|
+
|
|
38
|
+
a:not(.button, .circle, .extra) {
|
|
11
39
|
color: var(--md-sys-color-primary);
|
|
40
|
+
text-decoration: none;
|
|
41
|
+
@include focus-visible;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
:is(h1, h2, h3, h4, h5, h6) {
|
|
45
|
+
margin: 0 0 8px;
|
|
46
|
+
color: var(--md-sys-color-on-surface);
|
|
47
|
+
@include typescale("title-small");
|
|
48
|
+
font-family: $font-stack;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ul {
|
|
52
|
+
margin: 0;
|
|
53
|
+
padding: 0;
|
|
54
|
+
list-style: none;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
footer:not(:has(> nav:only-child)).filled,
|
|
59
|
+
footer:not(:has(> nav:only-child)).surface {
|
|
60
|
+
background-color: var(--md-sys-color-surface-container);
|
|
61
|
+
border-top: 1px solid var(--md-sys-color-outline-variant);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Columns: direct <nav> children. A wrapping .container is the grid
|
|
65
|
+
// when the author uses one. Legacy .row still spans the full measure.
|
|
66
|
+
footer:not(:has(> nav:only-child)) > .container,
|
|
67
|
+
footer:not(:has(> nav:only-child)):not(:has(> .container)) {
|
|
68
|
+
display: grid;
|
|
69
|
+
gap: var(--md-comp-footer-gap);
|
|
70
|
+
grid-template-columns: 1fr;
|
|
71
|
+
|
|
72
|
+
@include bp-up("small") {
|
|
73
|
+
grid-template-columns: repeat(2, 1fr);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@include bp-up("large") {
|
|
77
|
+
grid-template-columns: repeat(4, 1fr);
|
|
12
78
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
79
|
+
|
|
80
|
+
@include bp-up("xlarge") {
|
|
81
|
+
grid-template-columns: repeat(5, 1fr);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
footer:not(:has(> nav:only-child)) > .container > .row,
|
|
86
|
+
footer:not(:has(> nav:only-child)) > .row {
|
|
87
|
+
grid-column: 1 / -1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
footer:not(:has(> nav:only-child)) nav {
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
93
|
+
align-items: flex-start;
|
|
94
|
+
gap: 0;
|
|
95
|
+
min-width: 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
footer:not(:has(> nav:only-child)) nav > a:not(.button, .circle, .extra),
|
|
99
|
+
footer:not(:has(> nav:only-child)) ul a:not(.button, .circle, .extra) {
|
|
100
|
+
display: inline-flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
box-sizing: border-box;
|
|
103
|
+
min-height: 48px;
|
|
104
|
+
padding: 0 12px;
|
|
105
|
+
margin-inline-start: -12px;
|
|
106
|
+
border-radius: 2rem;
|
|
107
|
+
@include typescale("label-large");
|
|
108
|
+
font-family: $font-stack;
|
|
109
|
+
|
|
110
|
+
&:hover {
|
|
111
|
+
background-color: color-mix(in oklab, var(--md-sys-color-on-surface) 8%, transparent);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
footer:not(:has(> nav:only-child)) > small:last-child {
|
|
116
|
+
display: flex;
|
|
117
|
+
flex-wrap: wrap;
|
|
118
|
+
align-items: center;
|
|
119
|
+
justify-content: space-between;
|
|
120
|
+
gap: 8px 16px;
|
|
121
|
+
box-sizing: border-box;
|
|
122
|
+
min-height: var(--md-comp-footer-legal-height);
|
|
123
|
+
margin: 0;
|
|
124
|
+
padding-block: 12px;
|
|
125
|
+
grid-column: 1 / -1;
|
|
126
|
+
border-top: 1px solid var(--md-sys-color-outline-variant);
|
|
127
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
128
|
+
@include typescale("body-small");
|
|
129
|
+
font-family: $font-stack;
|
|
130
|
+
|
|
131
|
+
a:not(.button) {
|
|
132
|
+
color: var(--md-sys-color-primary);
|
|
21
133
|
}
|
|
22
134
|
}
|
|
23
135
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
136
|
+
// Sticky: pin the footer to the bottom of a short page. Only when the
|
|
137
|
+
// landmark is a direct child of body — not a footer nested in a demo.
|
|
138
|
+
body:has(> footer:not(:has(> nav:only-child))) {
|
|
139
|
+
min-height: 100dvh;
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-direction: column;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
body:has(> footer:not(:has(> nav:only-child))) > main {
|
|
145
|
+
flex: 1 0 auto;
|
|
27
146
|
}
|