@expressivecss/expressive 0.4.0 → 0.6.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +127 -0
  2. package/README.md +4 -9
  3. package/dist/css/expressive.css +2617 -951
  4. package/dist/css/expressive.css.map +1 -1
  5. package/dist/css/expressive.min.css +1 -1
  6. package/dist/css/expressive.min.css.map +1 -1
  7. package/dist/js/expressive.cjs +643 -804
  8. package/dist/js/expressive.cjs.map +4 -4
  9. package/dist/js/expressive.js +643 -804
  10. package/dist/js/expressive.js.map +4 -4
  11. package/dist/js/expressive.min.js +11 -11
  12. package/dist/js/expressive.min.js.map +4 -4
  13. package/dist/js/expressive.mjs +643 -804
  14. package/dist/js/expressive.mjs.map +4 -4
  15. package/dist/types/behaviors/bottomSheets.d.ts +18 -0
  16. package/dist/types/behaviors/sideSheets.d.ts +18 -0
  17. package/dist/types/components/autocomplete.d.ts +11 -11
  18. package/dist/types/components/index.d.ts +3 -5
  19. package/dist/types/components/{dropdown.d.ts → menu.d.ts} +38 -37
  20. package/dist/types/components/navigationRail.d.ts +53 -0
  21. package/dist/types/components/range.d.ts +3 -0
  22. package/dist/types/components/registry.d.ts +7 -15
  23. package/dist/types/components/select.d.ts +12 -12
  24. package/dist/types/components/{toasts.d.ts → snackbar.d.ts} +28 -25
  25. package/dist/types/index.d.ts +3 -1
  26. package/package.json +3 -2
  27. package/src/sass/README.md +13 -11
  28. package/src/sass/abstracts/_breakpoints.scss +14 -3
  29. package/src/sass/abstracts/_mixins.scss +3 -3
  30. package/src/sass/abstracts/_variables.scss +27 -2
  31. package/src/sass/base/_global.scss +1 -1
  32. package/src/sass/base/_grid.scss +66 -116
  33. package/src/sass/base/_index.scss +1 -1
  34. package/src/sass/components/_badges.scss +80 -60
  35. package/src/sass/components/_bottom-sheet.scss +137 -0
  36. package/src/sass/components/_cards.scss +4 -4
  37. package/src/sass/components/_chips.scss +6 -5
  38. package/src/sass/components/_dialog.scss +268 -0
  39. package/src/sass/components/_index.scss +9 -7
  40. package/src/sass/components/_list.scss +253 -0
  41. package/src/sass/components/_menu.scss +341 -0
  42. package/src/sass/components/_navbar.scss +65 -117
  43. package/src/sass/components/_navigation-bar.scss +165 -0
  44. package/src/sass/components/_navigation-rail.scss +308 -0
  45. package/src/sass/components/_page-footer.scss +7 -3
  46. package/src/sass/components/_panes.scss +294 -0
  47. package/src/sass/components/_side-sheet.scss +193 -0
  48. package/src/sass/components/_sidenav.scss +78 -49
  49. package/src/sass/components/{_toast.scss → _snackbar.scss} +35 -34
  50. package/src/sass/components/_tabs.scss +1 -27
  51. package/src/sass/components/_toolbar.scss +91 -25
  52. package/src/sass/components/_tooltip.scss +1 -1
  53. package/src/sass/components/forms/_fieldset.scss +1 -1
  54. package/src/sass/components/forms/_input-fields.scss +3 -3
  55. package/src/sass/components/forms/_range.scss +423 -98
  56. package/src/sass/components/forms/_select.scss +19 -17
  57. package/src/sass/tokens/_reference.scss +37 -13
  58. package/src/sass/tokens/_theme.scss +5 -13
  59. package/src/sass/utilities/_colors.scss +16 -74
  60. package/src/sass/utilities/_visibility.scss +8 -0
  61. package/dist/types/components/collapsible.d.ts +0 -79
  62. package/dist/types/components/pushpin.d.ts +0 -51
  63. package/dist/types/components/tapTarget.d.ts +0 -57
  64. package/src/sass/components/_collapsible.scss +0 -179
  65. package/src/sass/components/_collection.scss +0 -180
  66. package/src/sass/components/_dropdown.scss +0 -225
  67. package/src/sass/components/_modal.scss +0 -190
  68. package/src/sass/components/_pushpin.scss +0 -11
  69. package/src/sass/components/_tapTarget.scss +0 -187
@@ -1,6 +1,6 @@
1
1
  @use "../abstracts" as *;
2
2
 
3
- // Snackbars (toasts).
3
+ // Snackbars.
4
4
  //
5
5
  // Anatomy is the HTML. A .snackbar is the container. A <p> (or <span>,
6
6
  // or loose text) is the supporting text. A trailing <button> is the
@@ -13,14 +13,18 @@
13
13
  // text body-medium / inverse-on-surface, two lines max
14
14
  // action label-large / inverse-primary text button
15
15
  // close 24dp icon, inverse-on-surface
16
- // inset 8dp compact, 24dp from start+bottom on larger screens
16
+ // inset 8dp compact, 24dp from the bottom on larger screens
17
+ // placement bottom of the UI; centered from the small breakpoint
17
18
  //
18
- // The constructor adds .snackbar. A static .snackbar is in-flow (docs
19
- // previews). .active pins it to the viewport. There is no AutoInit.
19
+ // Snackbars must not interrupt browsing: the container is pointer-events
20
+ // none except on the bar, and the live region is polite. One at a time
21
+ // is a JS concern. The constructor adds .snackbar. A static .snackbar
22
+ // is in-flow (docs previews). .active pins it to the viewport. There
23
+ // is no AutoInit.
20
24
 
21
25
  $_bar: ".snackbar";
22
26
 
23
- #toast-container {
27
+ #snackbar-container {
24
28
  --md-comp-snackbar-container-margin-leading: 8px;
25
29
  --md-comp-snackbar-container-margin-trailing: 8px;
26
30
  --md-comp-snackbar-container-margin-bottom: 8px;
@@ -33,10 +37,11 @@ $_bar: ".snackbar";
33
37
  position: fixed;
34
38
  z-index: 10000;
35
39
  inset: auto var(--md-comp-snackbar-container-margin-trailing)
36
- var(--md-comp-snackbar-container-margin-bottom)
40
+ max(var(--md-comp-snackbar-container-margin-bottom), env(safe-area-inset-bottom, 0px))
37
41
  var(--md-comp-snackbar-container-margin-leading);
38
42
  width: auto;
39
43
  max-width: calc(100% - var(--md-comp-snackbar-container-margin-leading) - var(--md-comp-snackbar-container-margin-trailing));
44
+ // The page stays browsable — only the bar itself receives pointer events.
40
45
  pointer-events: none;
41
46
 
42
47
  > * {
@@ -48,26 +53,20 @@ $_bar: ".snackbar";
48
53
  --md-comp-snackbar-container-margin-trailing: 24px;
49
54
  --md-comp-snackbar-container-margin-bottom: 24px;
50
55
  --md-comp-snackbar-container-margin-top: 24px;
51
- align-items: flex-start;
56
+ align-items: center;
57
+ left: 50%;
58
+ right: auto;
52
59
  width: max-content;
53
60
  min-width: min(344px, calc(100% - 48px));
54
61
  max-width: min(672px, calc(100% - 48px));
62
+ transform: translateX(-50%);
55
63
  }
56
64
 
57
- // Position helpers on the container, or on a child via :has().
65
+ // Opt-in: M3 places snackbars at the bottom. `.top` is the exception.
58
66
  &:has(> .top),
59
67
  &.top {
60
- inset: var(--md-comp-snackbar-container-margin-top)
61
- var(--md-comp-snackbar-container-margin-trailing)
62
- auto
63
- var(--md-comp-snackbar-container-margin-leading);
64
- }
65
-
66
- &:has(> .center),
67
- &.center {
68
- left: 50%;
69
- right: auto;
70
- transform: translateX(-50%);
68
+ inset-block-start: var(--md-comp-snackbar-container-margin-top);
69
+ inset-block-end: auto;
71
70
  }
72
71
  }
73
72
 
@@ -215,45 +214,47 @@ $_bar: ".snackbar";
215
214
  }
216
215
  }
217
216
 
218
- // Stacked in-flow previews. JS toasts use the container gap instead.
217
+ // Stacked in-flow previews. JS-created snackbars use the container gap instead.
219
218
  #{$_bar} + #{$_bar} {
220
219
  margin-top: 8px;
221
220
  }
222
221
 
223
- // JS enter animation starts the bar 35px below its rest position.
224
- #toast-container #{$_bar} {
222
+ #snackbar-container #{$_bar} {
225
223
  position: relative;
226
- top: 35px;
227
224
  margin-top: 0;
228
225
  }
229
226
 
230
227
  // Static overlay. In-flow without this (docs previews). Not AutoInit —
231
228
  // add and remove the class yourself, or use the constructor for timing.
229
+ // Default: bottom of the UI, centered from the small breakpoint.
232
230
  #{$_bar}.active {
233
231
  position: fixed;
234
232
  z-index: 10000;
235
- inset: auto auto 16px 16px;
233
+ left: 50%;
234
+ right: auto;
235
+ bottom: 24px;
236
236
  top: auto;
237
+ transform: translateX(-50%);
237
238
  width: max-content;
238
- max-width: min(672px, calc(100% - 32px));
239
+ max-width: min(672px, calc(100% - 48px));
239
240
 
240
241
  @include bp-down("small") {
241
- inset: auto 8px 8px 8px;
242
+ left: 8px;
243
+ right: 8px;
244
+ bottom: max(8px, env(safe-area-inset-bottom, 0px));
245
+ transform: none;
242
246
  width: auto;
243
247
  max-width: none;
244
248
  }
245
249
 
246
250
  &.top {
247
- inset: 16px auto auto 16px;
251
+ top: 24px;
252
+ bottom: auto;
248
253
 
249
254
  @include bp-down("small") {
250
- inset: 8px 8px auto 8px;
255
+ top: 8px;
256
+ left: 8px;
257
+ right: 8px;
251
258
  }
252
259
  }
253
-
254
- &.center {
255
- left: 50%;
256
- right: auto;
257
- transform: translateX(-50%);
258
- }
259
260
  }
@@ -5,7 +5,7 @@
5
5
  // Anatomy is the HTML. A <nav class="tabs"> of <a href="#panel"> is the
6
6
  // bar. A heading or <span> is the label; a leading <i> is the icon.
7
7
  // .active is the selected tab. Helpers: .tabs-secondary, .horizontal,
8
- // .max, .transparent.
8
+ // .max.
9
9
  //
10
10
  // Tokens follow https://m3.material.io/components/tabs/specs
11
11
  // primary surface, 48dp (64 with stacked icon), title-small
@@ -223,29 +223,3 @@ $_tab: "> a, > .tab > a";
223
223
  }
224
224
  }
225
225
  }
226
-
227
- // On a colored app bar (header.primary > .tabs).
228
- .tabs.transparent {
229
- --md-comp-primary-tab-container-color: transparent;
230
- --md-comp-primary-tab-label-text-color: color-mix(
231
- in oklab,
232
- var(--md-sys-color-on-primary) 74%,
233
- transparent
234
- );
235
- --md-comp-primary-tab-active-label-text-color: var(--md-sys-color-on-primary);
236
- --md-comp-primary-tab-active-indicator-color: var(--md-sys-color-on-primary);
237
- border-block-end-color: color-mix(in oklab, var(--md-sys-color-on-primary) 20%, transparent);
238
-
239
- #{$_tab} {
240
- &:hover,
241
- &:focus {
242
- color: var(--md-sys-color-on-primary);
243
- background-color: color-mix(in oklab, var(--md-sys-color-on-primary) 8%, transparent);
244
- }
245
-
246
- &.active:hover,
247
- &.active:focus {
248
- background-color: color-mix(in oklab, var(--md-sys-color-on-primary) 10%, transparent);
249
- }
250
- }
251
- }
@@ -1,32 +1,41 @@
1
1
  @use "../abstracts" as *;
2
2
 
3
- // Toolbars.
3
+ // Toolbars (M3 Expressive).
4
4
  //
5
5
  // Anatomy is the HTML. A <nav class="toolbar"> is the bar. Direct
6
6
  // <button> / <a> children are the actions. An <i> is the icon; wrap a
7
- // label in <span>. .active marks the selected action. Helpers are only
8
- // for variants markup cannot express: .filled, .vertical, .max / .docked,
9
- // .fixed, .top, .bottom.
7
+ // label in <span>. .active marks the selected action. A .filled action
8
+ // is the emphasized control (the in-bar FAB). Helpers are only for
9
+ // variants markup cannot express: .docked, .vibrant / .filled (on the
10
+ // nav), .vertical, .fixed, .top, .bottom.
11
+ //
12
+ // Two variants:
13
+ // floating default. Hugs its actions, 64dp, 32dp stadium,
14
+ // surface-container, elevation 2. Horizontal or .vertical.
15
+ // docked .docked (or .max). Full width, 64dp, square, no
16
+ // elevation. Replaces the bottom app bar.
17
+ //
18
+ // Color: standard (surface-container) or .vibrant (primary-container).
19
+ // Pair a floating bar with a FAB via .toolbar-group. Do not show a
20
+ // toolbar at the same time as nav.navigation-bar.
10
21
  //
11
22
  // Tokens follow https://m3.material.io/components/toolbars/specs
12
- // floating hug, 64dp, 32dp stadium, surface-variant, elevation 2
13
- // docked full width, 64dp, 0 radius, surface-variant, no elevation
14
- // (M3 replacement for the bottom app bar)
15
- // vibrant primary-container / on-primary-container (.filled)
16
23
  // action 48dp target, 24dp icon, transparent at rest
17
- // selected secondary-container / on-secondary-container
24
+ // selected secondary-container (standard) / surface (vibrant)
25
+ // emphasized 48dp, 16dp corners, primary / on-primary
18
26
  //
19
- // nav.toolbar only — do not style every <nav> (app bars, card actions,
20
- // radio rows). div.fixed-action-btn.toolbar is the FAB-to-toolbar
21
- // transition, not this component.
27
+ // nav.toolbar only — do not style every <nav>. div.fixed-action-btn.toolbar
28
+ // is the FAB-to-toolbar transition, not this component.
22
29
 
23
30
  nav.toolbar {
24
- --md-comp-toolbar-container-color: var(--md-sys-color-surface-variant);
31
+ --md-comp-toolbar-container-color: var(--md-sys-color-surface-container);
25
32
  --md-comp-toolbar-container-shape: 32px;
26
33
  --md-comp-toolbar-container-height: 64px;
27
34
  --md-comp-toolbar-leading-space: 12px;
28
35
  --md-comp-toolbar-action-size: 48px;
29
36
  --md-comp-toolbar-icon-size: 24px;
37
+ --md-comp-toolbar-selected-container-color: var(--md-sys-color-secondary-container);
38
+ --md-comp-toolbar-selected-color: var(--md-sys-color-on-secondary-container);
30
39
 
31
40
  box-sizing: border-box;
32
41
  display: inline-flex;
@@ -48,7 +57,7 @@ nav.toolbar {
48
57
  }
49
58
 
50
59
  // Actions — transparent at rest so they sit on the container, not filled.
51
- // .extra is the 56dp FAB; leave it alone so a docked bar can embed one.
60
+ // .extra is the 56dp companion FAB; leave it alone.
52
61
  > :is(a, button):not(.extra) {
53
62
  box-sizing: border-box;
54
63
  display: inline-flex;
@@ -81,17 +90,17 @@ nav.toolbar {
81
90
  line-height: var(--md-comp-toolbar-icon-size);
82
91
  }
83
92
 
84
- &:hover:not(.active) {
93
+ &:hover:not(.active, .filled) {
85
94
  background-color: color-mix(in oklab, currentColor 8%, transparent);
86
95
  }
87
96
 
88
- &:active:not(.active) {
97
+ &:active:not(.active, .filled) {
89
98
  background-color: color-mix(in oklab, currentColor 10%, transparent);
90
99
  }
91
100
 
92
101
  &.active {
93
- background-color: var(--md-sys-color-secondary-container);
94
- color: var(--md-sys-color-on-secondary-container);
102
+ background-color: var(--md-comp-toolbar-selected-container-color);
103
+ color: var(--md-comp-toolbar-selected-color);
95
104
  }
96
105
 
97
106
  &:disabled {
@@ -109,6 +118,46 @@ nav.toolbar {
109
118
  border-radius: 50%;
110
119
  }
111
120
 
121
+ // Emphasized action (the in-bar FAB). 48dp, 16dp corners, primary.
122
+ > :is(a, button).filled:not(.extra) {
123
+ background-color: var(--md-sys-color-primary);
124
+ color: var(--md-sys-color-on-primary);
125
+ border-radius: 16px;
126
+ box-shadow: none;
127
+
128
+ &:hover {
129
+ background-color: color-mix(
130
+ in oklab,
131
+ var(--md-sys-color-on-primary) 8%,
132
+ var(--md-sys-color-primary)
133
+ );
134
+ }
135
+
136
+ &:active {
137
+ background-color: color-mix(
138
+ in oklab,
139
+ var(--md-sys-color-on-primary) 10%,
140
+ var(--md-sys-color-primary)
141
+ );
142
+ }
143
+ }
144
+
145
+ > :is(a, button).filled:not(.extra):has(> span) {
146
+ height: 40px;
147
+ min-height: 40px;
148
+ padding: 0 24px;
149
+ border-radius: 20px;
150
+ width: auto;
151
+ }
152
+
153
+ // Text field or other control stretching between leading and trailing.
154
+ > .field {
155
+ flex: 1 1 auto;
156
+ align-self: center;
157
+ min-width: 0;
158
+ margin: 0;
159
+ }
160
+
112
161
  // Spacer between leading and trailing actions.
113
162
  > .max {
114
163
  flex: 1 1 auto;
@@ -118,15 +167,13 @@ nav.toolbar {
118
167
  }
119
168
  }
120
169
 
121
- // Vibrant. Pair with .active using the inverse of the container.
170
+ // Vibrant color style. Pair .active with surface so it still contrasts.
171
+ nav.toolbar.vibrant,
122
172
  nav.toolbar.filled {
123
173
  --md-comp-toolbar-container-color: var(--md-sys-color-primary-container);
174
+ --md-comp-toolbar-selected-container-color: var(--md-sys-color-surface);
175
+ --md-comp-toolbar-selected-color: var(--md-sys-color-on-surface);
124
176
  color: var(--md-sys-color-on-primary-container);
125
-
126
- > :is(a, button).active {
127
- background-color: var(--md-sys-color-surface-variant);
128
- color: var(--md-sys-color-on-surface);
129
- }
130
177
  }
131
178
 
132
179
  // Vertical floating bar.
@@ -144,7 +191,8 @@ nav.toolbar.vertical {
144
191
  }
145
192
 
146
193
  // Docked — full width, square, no lift. M3's replacement for the bottom
147
- // app bar. .max is the BeerCSS name; .docked is the M3 name.
194
+ // app bar. Shorter than that bar (64dp, not 80). .max is the BeerCSS
195
+ // name; .docked is the M3 name.
148
196
  nav.toolbar.max,
149
197
  nav.toolbar.docked {
150
198
  display: flex;
@@ -154,6 +202,22 @@ nav.toolbar.docked {
154
202
  @include z-depth("0");
155
203
  }
156
204
 
205
+ // Pair a floating toolbar with a companion FAB. The FAB is a sibling,
206
+ // not a child — typically .extra.circle.
207
+ .toolbar-group {
208
+ display: inline-flex;
209
+ align-items: center;
210
+ gap: 8px;
211
+
212
+ &.vertical {
213
+ flex-direction: column;
214
+ }
215
+
216
+ > nav.toolbar {
217
+ margin: 0;
218
+ }
219
+ }
220
+
157
221
  // Pin to the viewport. Floating defaults to bottom-center; docked
158
222
  // defaults to the bottom edge.
159
223
  nav.toolbar.fixed {
@@ -184,9 +248,11 @@ nav.toolbar:is(.max, .docked).fixed,
184
248
  nav.toolbar:is(.max, .docked).fixed.bottom {
185
249
  inset: auto 0 0 0;
186
250
  transform: none;
251
+ padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
187
252
  }
188
253
 
189
254
  nav.toolbar:is(.max, .docked).fixed.top {
190
255
  inset: 0 0 auto 0;
191
256
  transform: none;
257
+ padding-bottom: 8px;
192
258
  }
@@ -119,7 +119,7 @@ body > .tooltip {
119
119
  // Rich tooltip — title, supporting text, optional action.
120
120
  .tooltip.rich,
121
121
  .tooltip.max {
122
- --md-comp-rich-tooltip-container-color: var(--md-sys-color-surface);
122
+ --md-comp-rich-tooltip-container-color: var(--md-sys-color-surface-container);
123
123
  --md-comp-rich-tooltip-container-shape: 12px;
124
124
 
125
125
  display: flex;
@@ -85,7 +85,7 @@ fieldset {
85
85
  }
86
86
 
87
87
  fieldset.filled {
88
- --md-comp-fieldset-container-color: var(--md-sys-color-surface-variant);
88
+ --md-comp-fieldset-container-color: var(--md-sys-color-surface-container-highest);
89
89
  --md-comp-fieldset-outline-color: transparent;
90
90
  }
91
91
 
@@ -38,7 +38,7 @@ $_text-inputs: "input:not([type]):not(.browser-default), input[type=text]:not(.b
38
38
  }
39
39
 
40
40
  .field {
41
- --md-comp-filled-text-field-container-color: var(--md-sys-color-surface-variant);
41
+ --md-comp-filled-text-field-container-color: var(--md-sys-color-surface-container-highest);
42
42
  --md-comp-filled-text-field-container-shape: 1rem;
43
43
  --md-comp-filled-text-field-caret-color: var(--md-sys-color-primary);
44
44
  --input-color: var(--md-comp-filled-text-field-caret-color);
@@ -293,8 +293,8 @@ textarea {
293
293
  li {
294
294
  .highlight { color: var(--md-sys-color-on-surface); }
295
295
  img {
296
- height: $dropdown-item-height - 10;
297
- width: $dropdown-item-height - 10;
296
+ height: $menu-item-height - 10;
297
+ width: $menu-item-height - 10;
298
298
  margin: 5px 15px;
299
299
  }
300
300
  }