@expressivecss/expressive 0.10.0 → 0.11.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 (68) hide show
  1. package/CHANGELOG.md +104 -1
  2. package/README.md +22 -1
  3. package/dist/css/expressive.css +107 -10
  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/fonts/material-symbols-outlined.woff2 +0 -0
  8. package/dist/fonts/material-symbols-rounded.woff2 +0 -0
  9. package/dist/fonts/material-symbols-sharp.woff2 +0 -0
  10. package/dist/js/chunks/{chunk-QYCYP443.mjs → chunk-74N6U5JJ.mjs} +12 -6
  11. package/dist/js/chunks/chunk-74N6U5JJ.mjs.map +7 -0
  12. package/dist/js/chunks/{chunk-ZIZVUWRL.mjs → chunk-7GKXUG4B.mjs} +8 -8
  13. package/dist/js/chunks/{chunk-7MM4VJJO.mjs → chunk-AYYYWUJ4.mjs} +7 -5
  14. package/dist/js/chunks/chunk-AYYYWUJ4.mjs.map +7 -0
  15. package/dist/js/chunks/{chunk-ZZBZI2XN.mjs → chunk-CDW6WIRT.mjs} +2 -2
  16. package/dist/js/chunks/chunk-FRB7TOCS.mjs +135 -0
  17. package/dist/js/chunks/chunk-FRB7TOCS.mjs.map +7 -0
  18. package/dist/js/chunks/{chunk-AOGFNMXS.mjs → chunk-I5KR22BY.mjs} +2 -2
  19. package/dist/js/chunks/{chunk-AOGFNMXS.mjs.map → chunk-I5KR22BY.mjs.map} +2 -2
  20. package/dist/js/chunks/{chunk-YFXEJ7GR.mjs → chunk-IMUPRRI6.mjs} +6 -7
  21. package/dist/js/chunks/chunk-IMUPRRI6.mjs.map +7 -0
  22. package/dist/js/chunks/chunk-PMBPAFAS.mjs +7 -0
  23. package/dist/js/chunks/{chunk-PB5L3EXF.mjs.map → chunk-PMBPAFAS.mjs.map} +1 -1
  24. package/dist/js/chunks/{chunk-G576EP5O.mjs → chunk-XFJ452AZ.mjs} +74 -11
  25. package/dist/js/chunks/chunk-XFJ452AZ.mjs.map +7 -0
  26. package/dist/js/expressive.cjs +139 -88
  27. package/dist/js/expressive.cjs.map +2 -2
  28. package/dist/js/expressive.js +139 -88
  29. package/dist/js/expressive.js.map +2 -2
  30. package/dist/js/expressive.min.js +10 -10
  31. package/dist/js/expressive.min.js.map +3 -3
  32. package/dist/js/expressive.mjs +9 -9
  33. package/dist/js/internal/components/autocomplete.mjs +1 -1
  34. package/dist/js/internal/components/carousel.mjs +1 -1
  35. package/dist/js/internal/components/chips.mjs +2 -2
  36. package/dist/js/internal/components/datepicker.mjs +2 -2
  37. package/dist/js/internal/components/index.mjs +7 -7
  38. package/dist/js/internal/components/registry.mjs +8 -8
  39. package/dist/js/internal/components/scrollspy.mjs +1 -1
  40. package/dist/js/internal/components/select.mjs +1 -1
  41. package/dist/js/internal/components/tabs.mjs +2 -2
  42. package/dist/js/modular.mjs +9 -9
  43. package/dist/types/components/autocomplete.d.ts +2 -1
  44. package/dist/types/components/datepicker.d.ts +1 -0
  45. package/dist/types/components/scrollspy.d.ts +5 -4
  46. package/dist/types/components/select.d.ts +7 -1
  47. package/dist/types/modular.d.ts +1 -1
  48. package/package.json +1 -1
  49. package/src/sass/abstracts/_mixins.scss +19 -11
  50. package/src/sass/components/_buttons.scss +45 -0
  51. package/src/sass/components/_chips.scss +5 -9
  52. package/src/sass/components/_dialog.scss +0 -7
  53. package/src/sass/components/_navbar.scss +3 -3
  54. package/src/sass/components/forms/_fieldset.scss +20 -1
  55. package/src/sass/components/forms/_file-input.scss +11 -3
  56. package/src/sass/components/forms/_select.scss +3 -2
  57. package/src/sass/utilities/_helpers.scss +18 -0
  58. package/src/sass/utilities/_spacing.scss +8 -1
  59. package/src/sass/utilities/_visibility.scss +5 -0
  60. package/dist/js/chunks/chunk-7MM4VJJO.mjs.map +0 -7
  61. package/dist/js/chunks/chunk-G576EP5O.mjs.map +0 -7
  62. package/dist/js/chunks/chunk-PB5L3EXF.mjs +0 -7
  63. package/dist/js/chunks/chunk-QYCYP443.mjs.map +0 -7
  64. package/dist/js/chunks/chunk-TZZ24ZQS.mjs +0 -154
  65. package/dist/js/chunks/chunk-TZZ24ZQS.mjs.map +0 -7
  66. package/dist/js/chunks/chunk-YFXEJ7GR.mjs.map +0 -7
  67. /package/dist/js/chunks/{chunk-ZIZVUWRL.mjs.map → chunk-7GKXUG4B.mjs.map} +0 -0
  68. /package/dist/js/chunks/{chunk-ZZBZI2XN.mjs.map → chunk-CDW6WIRT.mjs.map} +0 -0
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  version
3
- } from "./chunks/chunk-PB5L3EXF.mjs";
3
+ } from "./chunks/chunk-PMBPAFAS.mjs";
4
4
  import {
5
5
  AutoInit
6
- } from "./chunks/chunk-ZIZVUWRL.mjs";
6
+ } from "./chunks/chunk-7GKXUG4B.mjs";
7
7
  import "./chunks/chunk-WWPAPHMA.mjs";
8
8
  import {
9
9
  Slider
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunks/chunk-GY2Z5CJ2.mjs";
14
14
  import {
15
15
  Tabs
16
- } from "./chunks/chunk-YFXEJ7GR.mjs";
16
+ } from "./chunks/chunk-IMUPRRI6.mjs";
17
17
  import {
18
18
  Timepicker
19
19
  } from "./chunks/chunk-D4UZ4HFN.mjs";
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunks/chunk-XDB3G6RL.mjs";
32
32
  import {
33
33
  ScrollSpy
34
- } from "./chunks/chunk-TZZ24ZQS.mjs";
34
+ } from "./chunks/chunk-FRB7TOCS.mjs";
35
35
  import {
36
36
  ButtonGroup
37
37
  } from "./chunks/chunk-XO5WX3TK.mjs";
@@ -43,23 +43,23 @@ import {
43
43
  } from "./chunks/chunk-7UXHSYIA.mjs";
44
44
  import {
45
45
  Carousel
46
- } from "./chunks/chunk-AOGFNMXS.mjs";
46
+ } from "./chunks/chunk-I5KR22BY.mjs";
47
47
  import {
48
48
  CharacterCounter
49
49
  } from "./chunks/chunk-PIIAEYAJ.mjs";
50
50
  import {
51
51
  Chips
52
- } from "./chunks/chunk-ZZBZI2XN.mjs";
52
+ } from "./chunks/chunk-CDW6WIRT.mjs";
53
53
  import {
54
54
  Autocomplete
55
- } from "./chunks/chunk-7MM4VJJO.mjs";
55
+ } from "./chunks/chunk-AYYYWUJ4.mjs";
56
56
  import {
57
57
  Datepicker
58
- } from "./chunks/chunk-QYCYP443.mjs";
58
+ } from "./chunks/chunk-74N6U5JJ.mjs";
59
59
  import "./chunks/chunk-SLFNPY5M.mjs";
60
60
  import {
61
61
  FormSelect
62
- } from "./chunks/chunk-G576EP5O.mjs";
62
+ } from "./chunks/chunk-XFJ452AZ.mjs";
63
63
  import {
64
64
  Menu
65
65
  } from "./chunks/chunk-TK6PX2GC.mjs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Autocomplete
3
- } from "../../chunks/chunk-7MM4VJJO.mjs";
3
+ } from "../../chunks/chunk-AYYYWUJ4.mjs";
4
4
  import "../../chunks/chunk-TK6PX2GC.mjs";
5
5
  import "../../chunks/chunk-MISGHDUU.mjs";
6
6
  import "../../chunks/chunk-QSQ24FYT.mjs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Carousel
3
- } from "../../chunks/chunk-AOGFNMXS.mjs";
3
+ } from "../../chunks/chunk-I5KR22BY.mjs";
4
4
  import "../../chunks/chunk-MISGHDUU.mjs";
5
5
  import "../../chunks/chunk-QSQ24FYT.mjs";
6
6
  export {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Chips
3
- } from "../../chunks/chunk-ZZBZI2XN.mjs";
4
- import "../../chunks/chunk-7MM4VJJO.mjs";
3
+ } from "../../chunks/chunk-CDW6WIRT.mjs";
4
+ import "../../chunks/chunk-AYYYWUJ4.mjs";
5
5
  import "../../chunks/chunk-TK6PX2GC.mjs";
6
6
  import "../../chunks/chunk-MISGHDUU.mjs";
7
7
  import "../../chunks/chunk-QSQ24FYT.mjs";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  Datepicker
3
- } from "../../chunks/chunk-QYCYP443.mjs";
3
+ } from "../../chunks/chunk-74N6U5JJ.mjs";
4
4
  import "../../chunks/chunk-SLFNPY5M.mjs";
5
- import "../../chunks/chunk-G576EP5O.mjs";
5
+ import "../../chunks/chunk-XFJ452AZ.mjs";
6
6
  import "../../chunks/chunk-TK6PX2GC.mjs";
7
7
  import "../../chunks/chunk-MISGHDUU.mjs";
8
8
  import "../../chunks/chunk-QSQ24FYT.mjs";
@@ -7,7 +7,7 @@ import {
7
7
  } from "../../chunks/chunk-GY2Z5CJ2.mjs";
8
8
  import {
9
9
  Tabs
10
- } from "../../chunks/chunk-YFXEJ7GR.mjs";
10
+ } from "../../chunks/chunk-IMUPRRI6.mjs";
11
11
  import {
12
12
  Timepicker
13
13
  } from "../../chunks/chunk-D4UZ4HFN.mjs";
@@ -25,7 +25,7 @@ import {
25
25
  } from "../../chunks/chunk-XDB3G6RL.mjs";
26
26
  import {
27
27
  ScrollSpy
28
- } from "../../chunks/chunk-TZZ24ZQS.mjs";
28
+ } from "../../chunks/chunk-FRB7TOCS.mjs";
29
29
  import {
30
30
  ButtonGroup
31
31
  } from "../../chunks/chunk-XO5WX3TK.mjs";
@@ -37,23 +37,23 @@ import {
37
37
  } from "../../chunks/chunk-7UXHSYIA.mjs";
38
38
  import {
39
39
  Carousel
40
- } from "../../chunks/chunk-AOGFNMXS.mjs";
40
+ } from "../../chunks/chunk-I5KR22BY.mjs";
41
41
  import {
42
42
  CharacterCounter
43
43
  } from "../../chunks/chunk-PIIAEYAJ.mjs";
44
44
  import {
45
45
  Chips
46
- } from "../../chunks/chunk-ZZBZI2XN.mjs";
46
+ } from "../../chunks/chunk-CDW6WIRT.mjs";
47
47
  import {
48
48
  Autocomplete
49
- } from "../../chunks/chunk-7MM4VJJO.mjs";
49
+ } from "../../chunks/chunk-AYYYWUJ4.mjs";
50
50
  import {
51
51
  Datepicker
52
- } from "../../chunks/chunk-QYCYP443.mjs";
52
+ } from "../../chunks/chunk-74N6U5JJ.mjs";
53
53
  import "../../chunks/chunk-SLFNPY5M.mjs";
54
54
  import {
55
55
  FormSelect
56
- } from "../../chunks/chunk-G576EP5O.mjs";
56
+ } from "../../chunks/chunk-XFJ452AZ.mjs";
57
57
  import {
58
58
  Menu
59
59
  } from "../../chunks/chunk-TK6PX2GC.mjs";
@@ -1,27 +1,27 @@
1
1
  import {
2
2
  AUTO_INIT_COMPONENTS,
3
3
  AutoInit
4
- } from "../../chunks/chunk-ZIZVUWRL.mjs";
4
+ } from "../../chunks/chunk-7GKXUG4B.mjs";
5
5
  import "../../chunks/chunk-WWPAPHMA.mjs";
6
6
  import "../../chunks/chunk-JKNPQQWY.mjs";
7
7
  import "../../chunks/chunk-GY2Z5CJ2.mjs";
8
- import "../../chunks/chunk-YFXEJ7GR.mjs";
8
+ import "../../chunks/chunk-IMUPRRI6.mjs";
9
9
  import "../../chunks/chunk-D4UZ4HFN.mjs";
10
10
  import "../../chunks/chunk-JODJAGFS.mjs";
11
11
  import "../../chunks/chunk-N3UHGN3N.mjs";
12
12
  import "../../chunks/chunk-JNPIWFJT.mjs";
13
13
  import "../../chunks/chunk-XDB3G6RL.mjs";
14
- import "../../chunks/chunk-TZZ24ZQS.mjs";
14
+ import "../../chunks/chunk-FRB7TOCS.mjs";
15
15
  import "../../chunks/chunk-XO5WX3TK.mjs";
16
16
  import "../../chunks/chunk-VAS6JQ6P.mjs";
17
17
  import "../../chunks/chunk-7UXHSYIA.mjs";
18
- import "../../chunks/chunk-AOGFNMXS.mjs";
18
+ import "../../chunks/chunk-I5KR22BY.mjs";
19
19
  import "../../chunks/chunk-PIIAEYAJ.mjs";
20
- import "../../chunks/chunk-ZZBZI2XN.mjs";
21
- import "../../chunks/chunk-7MM4VJJO.mjs";
22
- import "../../chunks/chunk-QYCYP443.mjs";
20
+ import "../../chunks/chunk-CDW6WIRT.mjs";
21
+ import "../../chunks/chunk-AYYYWUJ4.mjs";
22
+ import "../../chunks/chunk-74N6U5JJ.mjs";
23
23
  import "../../chunks/chunk-SLFNPY5M.mjs";
24
- import "../../chunks/chunk-G576EP5O.mjs";
24
+ import "../../chunks/chunk-XFJ452AZ.mjs";
25
25
  import "../../chunks/chunk-TK6PX2GC.mjs";
26
26
  import "../../chunks/chunk-MISGHDUU.mjs";
27
27
  import "../../chunks/chunk-EP3CVKB5.mjs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ScrollSpy
3
- } from "../../chunks/chunk-TZZ24ZQS.mjs";
3
+ } from "../../chunks/chunk-FRB7TOCS.mjs";
4
4
  import "../../chunks/chunk-QSQ24FYT.mjs";
5
5
  export {
6
6
  ScrollSpy
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FormSelect
3
- } from "../../chunks/chunk-G576EP5O.mjs";
3
+ } from "../../chunks/chunk-XFJ452AZ.mjs";
4
4
  import "../../chunks/chunk-TK6PX2GC.mjs";
5
5
  import "../../chunks/chunk-MISGHDUU.mjs";
6
6
  import "../../chunks/chunk-QSQ24FYT.mjs";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Tabs
3
- } from "../../chunks/chunk-YFXEJ7GR.mjs";
4
- import "../../chunks/chunk-AOGFNMXS.mjs";
3
+ } from "../../chunks/chunk-IMUPRRI6.mjs";
4
+ import "../../chunks/chunk-I5KR22BY.mjs";
5
5
  import "../../chunks/chunk-MISGHDUU.mjs";
6
6
  import "../../chunks/chunk-QSQ24FYT.mjs";
7
7
  export {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  version
3
- } from "./chunks/chunk-PB5L3EXF.mjs";
3
+ } from "./chunks/chunk-PMBPAFAS.mjs";
4
4
  import {
5
5
  AutoInit
6
- } from "./chunks/chunk-ZIZVUWRL.mjs";
6
+ } from "./chunks/chunk-7GKXUG4B.mjs";
7
7
  import "./chunks/chunk-WWPAPHMA.mjs";
8
8
  import {
9
9
  Slider
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunks/chunk-GY2Z5CJ2.mjs";
14
14
  import {
15
15
  Tabs
16
- } from "./chunks/chunk-YFXEJ7GR.mjs";
16
+ } from "./chunks/chunk-IMUPRRI6.mjs";
17
17
  import {
18
18
  Timepicker
19
19
  } from "./chunks/chunk-D4UZ4HFN.mjs";
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunks/chunk-XDB3G6RL.mjs";
32
32
  import {
33
33
  ScrollSpy
34
- } from "./chunks/chunk-TZZ24ZQS.mjs";
34
+ } from "./chunks/chunk-FRB7TOCS.mjs";
35
35
  import {
36
36
  ButtonGroup
37
37
  } from "./chunks/chunk-XO5WX3TK.mjs";
@@ -43,23 +43,23 @@ import {
43
43
  } from "./chunks/chunk-7UXHSYIA.mjs";
44
44
  import {
45
45
  Carousel
46
- } from "./chunks/chunk-AOGFNMXS.mjs";
46
+ } from "./chunks/chunk-I5KR22BY.mjs";
47
47
  import {
48
48
  CharacterCounter
49
49
  } from "./chunks/chunk-PIIAEYAJ.mjs";
50
50
  import {
51
51
  Chips
52
- } from "./chunks/chunk-ZZBZI2XN.mjs";
52
+ } from "./chunks/chunk-CDW6WIRT.mjs";
53
53
  import {
54
54
  Autocomplete
55
- } from "./chunks/chunk-7MM4VJJO.mjs";
55
+ } from "./chunks/chunk-AYYYWUJ4.mjs";
56
56
  import {
57
57
  Datepicker
58
- } from "./chunks/chunk-QYCYP443.mjs";
58
+ } from "./chunks/chunk-74N6U5JJ.mjs";
59
59
  import "./chunks/chunk-SLFNPY5M.mjs";
60
60
  import {
61
61
  FormSelect
62
- } from "./chunks/chunk-G576EP5O.mjs";
62
+ } from "./chunks/chunk-XFJ452AZ.mjs";
63
63
  import {
64
64
  Menu
65
65
  } from "./chunks/chunk-TK6PX2GC.mjs";
@@ -135,7 +135,8 @@ export declare class Autocomplete extends Component<AutocompleteOptions> {
135
135
  _setupMenu(): void;
136
136
  _removeMenu(): void;
137
137
  _handleInputBlur: () => void;
138
- _handleInputKeyup: (e: KeyboardEvent) => void;
138
+ _handleInputKeyup: () => void;
139
+ _handleInput: () => void;
139
140
  _handleInputFocus: () => void;
140
141
  _inputChangeDetection: (value: string) => void;
141
142
  _handleInputKeydown: (e: KeyboardEvent) => void;
@@ -243,6 +243,7 @@ export declare class Datepicker extends Component<DatepickerOptions> {
243
243
  */
244
244
  static _escape(value: unknown): string;
245
245
  static _isDate(obj: any): boolean;
246
+ private static _parseDate;
246
247
  static _isWeekend(date: any): boolean;
247
248
  /**
248
249
  * @deprecated as this function has no effect without any return statement or global parameter setter.
@@ -31,17 +31,18 @@ export interface ScrollSpyOptions extends BaseOptions {
31
31
  */
32
32
  export declare class ScrollSpy extends Component<ScrollSpyOptions> {
33
33
  static _elements: ScrollSpy[];
34
- private static _observer;
35
- private static _ratios;
36
34
  private static _active;
35
+ private _observer;
36
+ private _ratio;
37
+ private _link;
38
+ private _offset;
39
+ private _offsetPriority;
37
40
  constructor(el: HTMLElement, options: Partial<ScrollSpyOptions>);
38
41
  static get defaults(): ScrollSpyOptions;
39
42
  static init(el: HTMLElement, options?: Partial<ScrollSpyOptions>): ScrollSpy;
40
43
  static init(els: InitElements<InitElement>, options?: Partial<ScrollSpyOptions>): ScrollSpy[];
41
44
  static getInstance(el: HTMLElement): ScrollSpy;
42
45
  destroy(): void;
43
- private static _ensureObserver;
44
- private static _onIntersect;
45
46
  private static _syncActive;
46
47
  private static _nearestAbove;
47
48
  private static _clearActive;
@@ -36,9 +36,11 @@ export declare class FormSelect extends Component<FormSelectOptions> {
36
36
  selectOptions: (HTMLOptionElement | HTMLOptGroupElement)[];
37
37
  private _values;
38
38
  private _createdWrapper;
39
- private _originalLabelFor;
39
+ private _originalLabels;
40
+ private _labelPlaceholder;
40
41
  private _form;
41
42
  private _resetTimer;
43
+ private _validationMessage;
42
44
  nativeTabIndex: number;
43
45
  constructor(el: HTMLSelectElement, options: FormSelectOptions);
44
46
  static get defaults(): FormSelectOptions;
@@ -71,6 +73,10 @@ export declare class FormSelect extends Component<FormSelectOptions> {
71
73
  private _setupOptionHandlers;
72
74
  private _removeOptionHandlers;
73
75
  _handleSelectChange: () => void;
76
+ private _handleInvalid;
77
+ private _handleNativeFocus;
78
+ private _syncValidationError;
79
+ private _clearValidationError;
74
80
  private _handleReset;
75
81
  _handleOptionKeydown: (e: KeyboardEvent) => void;
76
82
  _handleOptionClick: (e: MouseEvent | KeyboardEvent) => void;
@@ -5,7 +5,7 @@ export { SideSheets } from './behaviors/sideSheets';
5
5
  export { Forms } from './behaviors/forms';
6
6
  export { AutoInit } from './components/registry';
7
7
  export type { AutoInitOptions } from './components/registry';
8
- export declare const version = "0.10.0";
8
+ export declare const version = "0.11.0";
9
9
  export type * from './components/autocomplete';
10
10
  export type * from './components/appBar';
11
11
  export type * from './components/buttons';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expressivecss/expressive",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "ExpressiveCSS - a Material Design 3 front-end framework.",
5
5
  "license": "MIT",
6
6
  "author": "BaezFJ <baezdevs@gmail.com>",
@@ -183,17 +183,25 @@ $_state-layers: ("hover", "focus", "pressed", "dragged");
183
183
  // label is drawn elsewhere - a hidden radio that cannot be focused has no
184
184
  // arrow-key model left.
185
185
  //
186
- // _chips.scss and _navigation-rail.scss each carry their own copy of this and
187
- // predate the mixin; fold them in when either is next touched.
188
- @mixin visually-hidden {
189
- position: absolute;
190
- width: 1px;
191
- height: 1px;
192
- margin: -1px;
193
- padding: 0;
194
- overflow: hidden;
195
- clip-path: inset(50%);
196
- white-space: nowrap;
186
+ // `$important` is for the `.visually-hidden` utility, which has to beat a
187
+ // consumer's own `position` or `padding` the way `.hide` beats their
188
+ // `display`. Component rules leave it off.
189
+ //
190
+ // _navigation-rail.scss carries its own copy, which predates the mixin and
191
+ // omits the margin and white-space; fold it in when it is next touched.
192
+ @mixin visually-hidden($important: false) {
193
+ $flag: null;
194
+ @if $important { $flag: !important; }
195
+
196
+ position: absolute $flag;
197
+ width: 1px $flag;
198
+ height: 1px $flag;
199
+ margin: -1px $flag;
200
+ padding: 0 $flag;
201
+ border: 0 $flag;
202
+ overflow: hidden $flag;
203
+ clip-path: inset(50%) $flag;
204
+ white-space: nowrap $flag;
197
205
  }
198
206
 
199
207
  // Focus with Keyboard
@@ -346,3 +346,48 @@ $_extend-sizes: (
346
346
  :where(#{$_btn}).disabled {
347
347
  @include btn-disabled;
348
348
  }
349
+
350
+ // Reflow. A label that does not fit (enlarged text, 200% zoom, a narrow
351
+ // column) wraps between words and the container grows, instead of running
352
+ // out of the button or out of its parent. The size's container height becomes
353
+ // a minimum, so a label that fits renders exactly as before. The 4dp block
354
+ // padding only shows once the label wraps: it keeps the lines off the edges
355
+ // and fits inside every size's height with an outline and a line to spare.
356
+ //
357
+ // A minimum rather than a padding-derived height, because hosts restate
358
+ // `padding` far more often than `height`: a clear action or a list's trailing
359
+ // button that sets `padding: 0 12px` would otherwise collapse to one line of
360
+ // text. The cost is the other way round - a rule that sets a smaller `height`
361
+ // has to set `min-height` too, or name the size with the container-height
362
+ // token instead.
363
+ //
364
+ // `break-word`, not `anywhere`: `anywhere` also lowers the min-content width
365
+ // to a single character, so two buttons in a row a few pixels too narrow both
366
+ // shrink and split mid-word ("Cance|l") where they used to sit at full width.
367
+ // With `min-width: 0` on the label <span>, `break-word` still splits a single
368
+ // word longer than the parent. A bare text label has no element to take that
369
+ // minimum, so such a word overflows as it always did.
370
+ //
371
+ // Fixed geometry keeps `nowrap` and the fixed height: `.circle` and the FABs,
372
+ // the extended FAB, the chip's delete button, the carousel's dots, Timepicker's
373
+ // AM/PM controls, and hosts whose layout assumes one line. Button groups set item widths in
374
+ // script and would rewrap mid-press; a split button's two halves share one
375
+ // height; toolbars, the top app bar, dialog and sheet headers, navigation
376
+ // bars and rails, tabs, pagination and snackbar actions are fixed-height
377
+ // slots. `:where()` keeps the whole rule at zero specificity; it only has to
378
+ // come after the base rule above, whose `height` and `nowrap` it replaces.
379
+ $_fixed: ".circle, .extend, .indicator-item, .chip .close, :is(.timepicker-container, .time-picker-container) :is(.am-btn, .pm-btn), :is(.button-group, .split-button, .toolbar, .navigation-bar, .navigation-rail, .snackbar) > *, header > :is(nav, .bar) > *, :is(.pagination, .tabs, .snackbar > nav, dialog > header) *";
380
+
381
+ :where(#{$_btn}):where(:not(#{$_fixed})) {
382
+ height: auto;
383
+ min-height: var(--md-comp-filled-button-container-height);
384
+ max-width: 100%;
385
+ padding-block: 4px;
386
+ white-space: normal;
387
+ overflow-wrap: break-word;
388
+ text-align: center;
389
+
390
+ > * {
391
+ min-width: 0;
392
+ }
393
+ }
@@ -21,6 +21,10 @@
21
21
  margin: 0;
22
22
  min-height: 32px;
23
23
  height: auto;
24
+ // 4dp keeps wrapped lines off the edges. It is also exactly what a 24dp
25
+ // avatar or delete target leaves in the 32dp container, so a chip that fits
26
+ // on one line keeps its height.
27
+ padding-block: 4px;
24
28
  padding-left: var(--padding);
25
29
  padding-right: var(--padding);
26
30
  font-size: var(--font-size);
@@ -65,15 +69,7 @@
65
69
  // Filter chip. The checkbox carries the state and the form value; the label is
66
70
  // the chip. Kept focusable rather than `display: none` so it stays reachable.
67
71
  .chip-input {
68
- position: absolute;
69
- width: 1px;
70
- height: 1px;
71
- margin: -1px;
72
- padding: 0;
73
- border: 0;
74
- overflow: hidden;
75
- clip-path: inset(50%);
76
- white-space: nowrap;
72
+ @include visually-hidden;
77
73
  }
78
74
 
79
75
  .chip-input:checked + .chip {
@@ -141,13 +141,6 @@ dialog > :is(form, nav):last-child {
141
141
  padding: 0 24px 24px;
142
142
  border: 0;
143
143
  background: none;
144
-
145
- > :is(button, a.button):not(.icon-button, .circle, .extend) {
146
- max-width: 100%;
147
- height: auto;
148
- min-height: var(--md-comp-filled-button-container-height, 40px);
149
- white-space: normal;
150
- }
151
144
  }
152
145
 
153
146
  dialog:not(
@@ -5,7 +5,7 @@
5
5
  // Anatomy is the HTML. A header whose child is a nav is a top app bar.
6
6
  // Headings are the headline, icon-only links/buttons are the leading and
7
7
  // trailing actions, <menu> / <ul> hold text destinations. Helpers are only
8
- // for variants the markup cannot express: .center, .medium, .large, .fixed.
8
+ // for variants the markup cannot express: .center, .medium, .large.
9
9
  // `.medium` and `.large` are the Expressive flexible bars.
10
10
  // Destinations at the bottom of the screen are nav.navigation-bar, not this.
11
11
  //
@@ -490,12 +490,12 @@ header.large.collapsed:has(> #{$_bar}) > #{$_bar} {
490
490
  }
491
491
  }
492
492
 
493
- // Pin the bar. On scroll, fill with surface-container so it separates
493
+ // Pin every top app bar. On scroll, fill with surface-container so it separates
494
494
  // from the body (M3 Expressive). The animation only drives the mix
495
495
  // progress; a utility class on the header sets background-color itself
496
496
  // and is not overwritten. Without animation-timeline the bar stays at
497
497
  // rest (surface), the spec default.
498
- header.fixed:has(> :is(nav:not(.navigation-bar, .navigation-rail), .bar)) {
498
+ header:has(> :is(nav:not(.navigation-bar, .navigation-rail), .bar)) {
499
499
  position: sticky;
500
500
  top: 0;
501
501
  z-index: 997;
@@ -5,7 +5,8 @@
5
5
  // Anatomy is the HTML. A <fieldset> is the group. A <legend> is the
6
6
  // headline. Direct children are the fields — .field, radios, switches,
7
7
  // a .inline row of radios, a trailing <small> as supporting text. No wrapper
8
- // class. .filled / .border / .rounded are helpers markup cannot express.
8
+ // class. .filled / .border / .rounded / .plain are helpers markup cannot
9
+ // express.
9
10
  //
10
11
  // M3 has no fieldset component. Tokens follow the outlined grouping
11
12
  // container used around related form content, and the outlined text-field
@@ -99,6 +100,24 @@ fieldset.rounded {
99
100
  --md-comp-fieldset-container-shape: 12px;
100
101
  }
101
102
 
103
+ // Plain groups radios or checkboxes inside a surface that already frames them,
104
+ // such as a card, a dialog or a filled section. No outline, fill, padding or
105
+ // sibling margin, and the legend starts where the content starts instead of
106
+ // sitting in a notch 4dp outside it.
107
+ fieldset.plain {
108
+ --md-comp-fieldset-container-color: transparent;
109
+ --md-comp-fieldset-outline-width: 0;
110
+
111
+ margin: 0;
112
+ padding: 0;
113
+
114
+ > legend {
115
+ max-width: 100%;
116
+ margin-inline-start: 0;
117
+ padding-inline: 0;
118
+ }
119
+ }
120
+
102
121
  fieldset:disabled,
103
122
  fieldset[disabled] {
104
123
  --md-comp-fieldset-outline-color: color-mix(
@@ -2,7 +2,9 @@
2
2
 
3
3
  .file-field {
4
4
  display: grid;
5
- grid-template-columns: min-content auto;
5
+ // Short triggers keep their intrinsic width; long labels leave room for
6
+ // the selected filename instead of consuming the entire field.
7
+ grid-template-columns: fit-content(50%) minmax(0, 1fr);
6
8
  gap: 10px;
7
9
  //position: relative;
8
10
 
@@ -18,10 +20,16 @@
18
20
  > label.button,
19
21
  > button,
20
22
  > .btn {
23
+ display: block;
24
+ align-content: center;
25
+ overflow-wrap: break-word;
21
26
  position: relative;
22
27
  overflow: hidden;
23
- height: 3rem;
24
- line-height: 3rem;
28
+ // A minimum rather than a height, so a wrapped label grows the trigger.
29
+ // `start` keeps the grid from stretching it to the 56dp text field.
30
+ align-self: start;
31
+ min-height: 3rem;
32
+ min-width: 0;
25
33
  }
26
34
 
27
35
  span {
@@ -112,8 +112,9 @@ select.browser-default {
112
112
  transform: rotate(180deg);
113
113
  }
114
114
 
115
- // Keep the native select in the field's box so constraint-validation
116
- // bubbles land on the control, not at (0, 0).
115
+ // Keep native validation focus available and its geometry at the field.
116
+ // The aria-hidden wrapper excludes it from the accessibility tree; JS
117
+ // forwards native focus to the visible combobox after reporting finishes.
117
118
  .hide-select {
118
119
  position: absolute;
119
120
  inset: 0;
@@ -7,6 +7,24 @@
7
7
  // Positioning
8
8
  .valign-wrapper { display: flex; align-items: center; }
9
9
 
10
+ // Flex layout. One declaration each; combine on the container, and pair with
11
+ // .gap-* from _spacing.scss for the space between items. Row direction and
12
+ // start alignment are the flex defaults, so only the overrides get a class.
13
+ .flex { display: flex; }
14
+ .inline-flex { display: inline-flex; }
15
+ .flex-column { flex-direction: column; }
16
+ .flex-wrap { flex-wrap: wrap; }
17
+ .justify-start { justify-content: flex-start; }
18
+ .justify-center { justify-content: center; }
19
+ .justify-end { justify-content: flex-end; }
20
+ .justify-between { justify-content: space-between; }
21
+ .align-start { align-items: flex-start; }
22
+ .align-center { align-items: center; }
23
+ .align-end { align-items: flex-end; }
24
+ .align-stretch { align-items: stretch; }
25
+ .flex-1 { flex: 1 1 0; }
26
+ .flex-none { flex: none; }
27
+
10
28
  // Text alignment
11
29
  .left-align { text-align: left; }
12
30
  .right-align { text-align: right }
@@ -1,4 +1,4 @@
1
- // Margin and padding scale: .m-3, .pt-2, .px-4, .my-auto, ...
1
+ // Margin, padding and gap scale: .m-3, .pt-2, .px-4, .my-auto, .gap-2, ...
2
2
  //
3
3
  // Shortcut x value x direction, all !important so a helper wins over the
4
4
  // component it is applied to. Edit the maps here to change the scale.
@@ -37,3 +37,10 @@ $spacing-values: ("0": 0, "1": 0.25rem, "2": 0.5rem, "3": 0.75rem, "4": 1rem, "5
37
37
  }
38
38
  }
39
39
  }
40
+
41
+ // Gap on the same scale for flex and grid containers: .gap-0 ... .gap-6.
42
+ @each $name, $value in $spacing-values {
43
+ @if $name != "auto" {
44
+ .gap-#{$name} { gap: $value !important; }
45
+ }
46
+ }
@@ -5,6 +5,11 @@
5
5
 
6
6
  .hide { display: none !important; }
7
7
 
8
+ // Hidden from sight, still announced: a visible label's longer twin, an
9
+ // icon-only control's name, a live region's text. Important for the same
10
+ // reason `.hide` is.
11
+ .visually-hidden { @include visually-hidden(true); }
12
+
8
13
  .hide-on-compact-only,
9
14
  .hide-on-small-only,
10
15
  .hide-on-small-and-down {