@expressivecss/expressive 0.9.1 → 0.10.1

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 (190) hide show
  1. package/CHANGELOG.md +184 -1
  2. package/README.md +178 -25
  3. package/dist/css/expressive.css +428 -1222
  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-7MM4VJJO.mjs +509 -0
  11. package/dist/js/chunks/chunk-7MM4VJJO.mjs.map +7 -0
  12. package/dist/js/chunks/chunk-7UXHSYIA.mjs +183 -0
  13. package/dist/js/chunks/chunk-7UXHSYIA.mjs.map +7 -0
  14. package/dist/js/chunks/chunk-A3BJA7V4.mjs +28 -0
  15. package/dist/js/chunks/chunk-A3BJA7V4.mjs.map +7 -0
  16. package/dist/js/chunks/chunk-AOGFNMXS.mjs +691 -0
  17. package/dist/js/chunks/chunk-AOGFNMXS.mjs.map +7 -0
  18. package/dist/js/chunks/chunk-D4UZ4HFN.mjs +560 -0
  19. package/dist/js/chunks/chunk-D4UZ4HFN.mjs.map +7 -0
  20. package/dist/js/chunks/chunk-EP3CVKB5.mjs +88 -0
  21. package/dist/js/chunks/chunk-EP3CVKB5.mjs.map +7 -0
  22. package/dist/js/chunks/chunk-G576EP5O.mjs +459 -0
  23. package/dist/js/chunks/chunk-G576EP5O.mjs.map +7 -0
  24. package/dist/js/chunks/chunk-GY2Z5CJ2.mjs +320 -0
  25. package/dist/js/chunks/chunk-GY2Z5CJ2.mjs.map +7 -0
  26. package/dist/js/chunks/chunk-JKNPQQWY.mjs +191 -0
  27. package/dist/js/chunks/chunk-JKNPQQWY.mjs.map +7 -0
  28. package/dist/js/chunks/chunk-JNPIWFJT.mjs +365 -0
  29. package/dist/js/chunks/chunk-JNPIWFJT.mjs.map +7 -0
  30. package/dist/js/chunks/chunk-JODJAGFS.mjs +267 -0
  31. package/dist/js/chunks/chunk-JODJAGFS.mjs.map +7 -0
  32. package/dist/js/chunks/chunk-JR24UB4X.mjs +100 -0
  33. package/dist/js/chunks/chunk-JR24UB4X.mjs.map +7 -0
  34. package/dist/js/chunks/chunk-KR44BSYQ.mjs +55 -0
  35. package/dist/js/chunks/chunk-KR44BSYQ.mjs.map +7 -0
  36. package/dist/js/chunks/chunk-LZVBJ33S.mjs +102 -0
  37. package/dist/js/chunks/chunk-LZVBJ33S.mjs.map +7 -0
  38. package/dist/js/chunks/chunk-MISGHDUU.mjs +326 -0
  39. package/dist/js/chunks/chunk-MISGHDUU.mjs.map +7 -0
  40. package/dist/js/chunks/chunk-N3UHGN3N.mjs +175 -0
  41. package/dist/js/chunks/chunk-N3UHGN3N.mjs.map +7 -0
  42. package/dist/js/chunks/chunk-PIIAEYAJ.mjs +85 -0
  43. package/dist/js/chunks/chunk-PIIAEYAJ.mjs.map +7 -0
  44. package/dist/js/chunks/chunk-QSQ24FYT.mjs +59 -0
  45. package/dist/js/chunks/chunk-QSQ24FYT.mjs.map +7 -0
  46. package/dist/js/chunks/chunk-QYCYP443.mjs +1111 -0
  47. package/dist/js/chunks/chunk-QYCYP443.mjs.map +7 -0
  48. package/dist/js/chunks/chunk-SLFNPY5M.mjs +78 -0
  49. package/dist/js/chunks/chunk-SLFNPY5M.mjs.map +7 -0
  50. package/dist/js/chunks/chunk-TK6PX2GC.mjs +663 -0
  51. package/dist/js/chunks/chunk-TK6PX2GC.mjs.map +7 -0
  52. package/dist/js/chunks/chunk-TYM6U5DY.mjs +76 -0
  53. package/dist/js/chunks/chunk-TYM6U5DY.mjs.map +7 -0
  54. package/dist/js/chunks/chunk-TZZ24ZQS.mjs +154 -0
  55. package/dist/js/chunks/chunk-TZZ24ZQS.mjs.map +7 -0
  56. package/dist/js/chunks/chunk-VAS6JQ6P.mjs +94 -0
  57. package/dist/js/chunks/chunk-VAS6JQ6P.mjs.map +7 -0
  58. package/dist/js/chunks/chunk-WWPAPHMA.mjs +1 -0
  59. package/dist/js/chunks/chunk-WWPAPHMA.mjs.map +7 -0
  60. package/dist/js/chunks/chunk-XDB3G6RL.mjs +114 -0
  61. package/dist/js/chunks/chunk-XDB3G6RL.mjs.map +7 -0
  62. package/dist/js/chunks/chunk-XO5WX3TK.mjs +226 -0
  63. package/dist/js/chunks/chunk-XO5WX3TK.mjs.map +7 -0
  64. package/dist/js/chunks/chunk-YFXEJ7GR.mjs +286 -0
  65. package/dist/js/chunks/chunk-YFXEJ7GR.mjs.map +7 -0
  66. package/dist/js/chunks/chunk-ZAOYQ6SY.mjs +7 -0
  67. package/dist/js/chunks/chunk-ZAOYQ6SY.mjs.map +7 -0
  68. package/dist/js/chunks/chunk-ZIZVUWRL.mjs +120 -0
  69. package/dist/js/chunks/chunk-ZIZVUWRL.mjs.map +7 -0
  70. package/dist/js/chunks/chunk-ZZBZI2XN.mjs +338 -0
  71. package/dist/js/chunks/chunk-ZZBZI2XN.mjs.map +7 -0
  72. package/dist/js/expressive.cjs +747 -754
  73. package/dist/js/expressive.cjs.map +4 -4
  74. package/dist/js/expressive.js +747 -754
  75. package/dist/js/expressive.js.map +4 -4
  76. package/dist/js/expressive.min.js +11 -15
  77. package/dist/js/expressive.min.js.map +4 -4
  78. package/dist/js/expressive.mjs +83 -7490
  79. package/dist/js/expressive.mjs.map +4 -4
  80. package/dist/js/internal/behaviors/bottomSheets.mjs +9 -0
  81. package/dist/js/internal/behaviors/bottomSheets.mjs.map +7 -0
  82. package/dist/js/internal/behaviors/dialogs.mjs +8 -0
  83. package/dist/js/internal/behaviors/dialogs.mjs.map +7 -0
  84. package/dist/js/internal/behaviors/forms.mjs +8 -0
  85. package/dist/js/internal/behaviors/forms.mjs.map +7 -0
  86. package/dist/js/internal/behaviors/sheetDrag.mjs +8 -0
  87. package/dist/js/internal/behaviors/sheetDrag.mjs.map +7 -0
  88. package/dist/js/internal/behaviors/sideSheets.mjs +9 -0
  89. package/dist/js/internal/behaviors/sideSheets.mjs.map +7 -0
  90. package/dist/js/internal/components/appBar.mjs +8 -0
  91. package/dist/js/internal/components/appBar.mjs.map +7 -0
  92. package/dist/js/internal/components/autocomplete.mjs +10 -0
  93. package/dist/js/internal/components/autocomplete.mjs.map +7 -0
  94. package/dist/js/internal/components/buttonGroup.mjs +8 -0
  95. package/dist/js/internal/components/buttonGroup.mjs.map +7 -0
  96. package/dist/js/internal/components/buttons.mjs +9 -0
  97. package/dist/js/internal/components/buttons.mjs.map +7 -0
  98. package/dist/js/internal/components/cards.mjs +13 -0
  99. package/dist/js/internal/components/cards.mjs.map +7 -0
  100. package/dist/js/internal/components/carousel.mjs +9 -0
  101. package/dist/js/internal/components/carousel.mjs.map +7 -0
  102. package/dist/js/internal/components/characterCounter.mjs +8 -0
  103. package/dist/js/internal/components/characterCounter.mjs.map +7 -0
  104. package/dist/js/internal/components/chips.mjs +11 -0
  105. package/dist/js/internal/components/chips.mjs.map +7 -0
  106. package/dist/js/internal/components/datepicker.mjs +12 -0
  107. package/dist/js/internal/components/datepicker.mjs.map +7 -0
  108. package/dist/js/internal/components/expandingCard.mjs +11 -0
  109. package/dist/js/internal/components/expandingCard.mjs.map +7 -0
  110. package/dist/js/internal/components/index.mjs +88 -0
  111. package/dist/js/internal/components/index.mjs.map +7 -0
  112. package/dist/js/internal/components/lightbox.mjs +9 -0
  113. package/dist/js/internal/components/lightbox.mjs.map +7 -0
  114. package/dist/js/internal/components/menu.mjs +9 -0
  115. package/dist/js/internal/components/menu.mjs.map +7 -0
  116. package/dist/js/internal/components/navigationRail.mjs +8 -0
  117. package/dist/js/internal/components/navigationRail.mjs.map +7 -0
  118. package/dist/js/internal/components/registry.mjs +33 -0
  119. package/dist/js/internal/components/registry.mjs.map +7 -0
  120. package/dist/js/internal/components/scrollspy.mjs +8 -0
  121. package/dist/js/internal/components/scrollspy.mjs.map +7 -0
  122. package/dist/js/internal/components/select.mjs +10 -0
  123. package/dist/js/internal/components/select.mjs.map +7 -0
  124. package/dist/js/internal/components/slider.mjs +9 -0
  125. package/dist/js/internal/components/slider.mjs.map +7 -0
  126. package/dist/js/internal/components/snackbar.mjs +8 -0
  127. package/dist/js/internal/components/snackbar.mjs.map +7 -0
  128. package/dist/js/internal/components/tabs.mjs +10 -0
  129. package/dist/js/internal/components/tabs.mjs.map +7 -0
  130. package/dist/js/internal/components/timepicker.mjs +10 -0
  131. package/dist/js/internal/components/timepicker.mjs.map +7 -0
  132. package/dist/js/internal/components/tooltip.mjs +9 -0
  133. package/dist/js/internal/components/tooltip.mjs.map +7 -0
  134. package/dist/js/internal/core/component.mjs +7 -0
  135. package/dist/js/internal/core/component.mjs.map +7 -0
  136. package/dist/js/internal/core/utils.mjs +7 -0
  137. package/dist/js/internal/core/utils.mjs.map +7 -0
  138. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +8 -0
  139. package/dist/js/internal/plugins/dockedDisplayPlugin.mjs.map +7 -0
  140. package/dist/js/modular.mjs +113 -0
  141. package/dist/js/modular.mjs.map +7 -0
  142. package/dist/types/behaviors/sheetDrag.d.ts +1 -1
  143. package/dist/types/components/appBar.d.ts +1 -1
  144. package/dist/types/components/autocomplete.d.ts +9 -0
  145. package/dist/types/components/buttons.d.ts +4 -39
  146. package/dist/types/components/carousel.d.ts +10 -1
  147. package/dist/types/components/chips.d.ts +1 -0
  148. package/dist/types/components/datepicker.d.ts +7 -0
  149. package/dist/types/components/index.d.ts +0 -2
  150. package/dist/types/components/lightbox.d.ts +12 -0
  151. package/dist/types/components/menu.d.ts +3 -0
  152. package/dist/types/components/registry.d.ts +0 -4
  153. package/dist/types/components/select.d.ts +4 -0
  154. package/dist/types/components/slider.d.ts +2 -1
  155. package/dist/types/components/snackbar.d.ts +4 -2
  156. package/dist/types/components/tabs.d.ts +2 -1
  157. package/dist/types/components/timepicker.d.ts +5 -3
  158. package/dist/types/components/tooltip.d.ts +5 -3
  159. package/dist/types/index.d.ts +1 -8
  160. package/dist/types/modular.d.ts +28 -0
  161. package/package.json +16 -4
  162. package/src/sass/README.md +8 -0
  163. package/src/sass/components/_badges.scss +1 -6
  164. package/src/sass/components/_button-groups.scss +5 -1
  165. package/src/sass/components/_buttons.scss +8 -287
  166. package/src/sass/components/_chips.scss +17 -2
  167. package/src/sass/components/_dialog.scss +9 -4
  168. package/src/sass/components/_fab-menu.scss +11 -9
  169. package/src/sass/components/_icon-buttons.scss +0 -5
  170. package/src/sass/components/_index.scss +0 -5
  171. package/src/sass/components/_menu.scss +2 -2
  172. package/src/sass/components/_navigation-rail.scss +1 -1
  173. package/src/sass/components/_panes.scss +50 -78
  174. package/src/sass/components/_progress.scss +73 -13
  175. package/src/sass/components/_scrim.scss +4 -4
  176. package/src/sass/components/_side-sheet.scss +22 -12
  177. package/src/sass/components/_toolbar.scss +1 -4
  178. package/src/sass/components/_tooltip.scss +20 -2
  179. package/src/sass/components/forms/_input-fields.scss +5 -1
  180. package/src/sass/components/forms/_select.scss +1 -0
  181. package/src/sass/components/forms/_slider.scss +81 -25
  182. package/src/sass/custom.scss +38 -0
  183. package/src/sass/utilities/_helpers.scss +18 -0
  184. package/src/sass/utilities/_spacing.scss +8 -1
  185. package/dist/types/components/navigationDrawer.d.ts +0 -110
  186. package/src/sass/components/_banners.scss +0 -298
  187. package/src/sass/components/_bottom-app-bar.scss +0 -180
  188. package/src/sass/components/_floating-sheet.scss +0 -86
  189. package/src/sass/components/_navigation-drawer.scss +0 -476
  190. package/src/sass/components/_segmented-buttons.scss +0 -188
package/CHANGELOG.md CHANGED
@@ -5,6 +5,187 @@ the format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.10.1] - 2026-09-22
9
+
10
+ ### Added
11
+
12
+ - Flex helpers: `.flex`, `.inline-flex`, `.flex-column`, `.flex-wrap`,
13
+ `.justify-start|center|end|between`, `.align-start|center|end|stretch`,
14
+ `.flex-1`, `.flex-none`, and `.gap-0` to `.gap-6` on the spacing scale. One
15
+ declaration per class, in the utilities layer; the helpers page, `llm.md`,
16
+ and the skill's helper reference document them.
17
+
18
+ ### Changed
19
+
20
+ - **Offline design context for the ExpressiveCSS skill.** The generator now
21
+ copies the hard rules, window-size tables, component chooser, screen recipes,
22
+ anatomy cheat sheet, and Materialize name map from `m3-guidelines.md` into
23
+ `skills/expressivecss/references/design-rules.md`, and the root, Design,
24
+ Usage, and Install guides route to it. JavaScript component guides inline the
25
+ options table and method names from `llm.md`. The Install guide carries a
26
+ complete page skeleton. The Design guide states the framework spacing scale
27
+ and control-text rules. Six catalogue entries that repeated their page tagline
28
+ as the selection rule now say when to use the component.
29
+
30
+ - The ExpressiveCSS skill tells agents without an MCP client to run
31
+ `expressivecss-lint` from `@expressivecss/mcp-server` on the markup files they
32
+ touched before finishing.
33
+
34
+ ## [0.10.0] - 2026-09-18
35
+
36
+ ### Fixed
37
+
38
+ - Connected button groups preserve equal-width items when translated labels
39
+ exceed the available width. The group expands inside an overflow container
40
+ instead of letting labels overlap adjacent controls.
41
+
42
+ - Bottom and floating sheets keep long bodies scrollable and action rows reachable
43
+ at compact widths with enlarged text. Shared dialog headings and action labels
44
+ wrap instead of overflowing their inset container without resizing icon buttons
45
+ or FABs.
46
+
47
+ - Datepicker initializes multiple-date defaults safely, keeps generated inputs
48
+ synchronized when selections shrink or grow, and preserves the original input
49
+ when cleared. Range-end inputs supplied by applications receive input and
50
+ keyboard handlers. Teardown removes generated fields and their listeners.
51
+
52
+ - Timepicker digital fields synchronize native input events, including paste,
53
+ without depending on keyup. Invalid edits restore the last valid value on blur;
54
+ empty fields display the same fallback values they submit. Twelve-hour defaults
55
+ handle midnight, noon, 24-hour input strings and lowercase AM/PM consistently.
56
+
57
+ - Lightbox cancels interrupted transitions, honors mounted reduced-motion changes,
58
+ preserves teardown focus and releases shared ancestor overflow after the last
59
+ open instance closes. Canceled transitions no longer report completion.
60
+ Overlay dismissal stays closed inside button triggers, and shadow-root teardown
61
+ respects focus moved outside the root by application handlers.
62
+
63
+ - Enhanced selects synchronize native form resets, selection semantics and
64
+ refreshed disabled states. Disabled optgroups cannot be selected, and refresh
65
+ preserves focus on a surviving option in an open menu and rebinds reset handling
66
+ after form-owner changes.
67
+
68
+ - Pane layouts use the nearest ancestor query-container width, with viewport
69
+ fallback, for columns, compact visibility, margins and dividers. Long footer
70
+ actions wrap without changing application-owned pane selection or icon-button sizes.
71
+
72
+ - App-bar search dialogs stay closed during native focus restoration and reopen
73
+ on a fresh focus or click. Teardown removes the search activation listeners.
74
+
75
+ - Tabs keep swipe selection, `aria-current`, and the `onShow` panel synchronized
76
+ without duplicate callbacks. Swipeable teardown restores panel positions and
77
+ owned state; initialization above `responsiveThreshold` uses ordinary panels.
78
+ Initial hash selection takes precedence over stale authored panel state.
79
+
80
+ - Side sheets mirror dragging, entry motion and modal corners in RTL while
81
+ preserving logical start/end aliases. Long headings and action rows wrap.
82
+ Side and bottom sheets ignore secondary-pointer cancellation and clear drag
83
+ state when closed, removed, or interrupted by another primary press, including
84
+ close/reopen and remove/reattach sequences within one JavaScript task.
85
+
86
+ - Carousel mirrors horizontal navigation and scroll placement in RTL, leaves
87
+ editable keys alone, and keeps auto-advance suspended during internal focus
88
+ moves. Mounted reduced-motion changes preserve explicit pause and stop
89
+ in-flight smooth scrolling. Native gestures cancel deferred recentering. Teardown
90
+ cancels scroll-completion timers and listeners. The docs demonstrate an
91
+ application-owned pause/resume button using the existing methods.
92
+
93
+ - Slider labels and track gaps account for native handle travel in LTR, RTL and
94
+ vertical layouts. Paired inputs accept native track clicks and their vertical
95
+ track resizes with the inputs. Application input events update values without
96
+ dragging, and forced-colors tracks use system colors.
97
+
98
+ - Chips delete the focused token with Backspace/Delete and recover focus without
99
+ overriding deletion callbacks. Destroying one instance preserves other instances'
100
+ keyboard handlers. Input chips no longer inherit floating-label positioning;
101
+ long labels wrap without shrinking their delete controls.
102
+
103
+ - Closing menus immediately exclude their content from keyboard focus and
104
+ preserve focus moved by close callbacks. Nested keyboard navigation and
105
+ typeahead stay in their active menu; RTL flyouts mirror their keys and avoid
106
+ either viewport edge. Returning focus to a parent no longer reopens a flyout.
107
+
108
+ - Native and custom progress indicators use system colors in forced-colors mode.
109
+ Empty linear tracks remain outlined, circular values retain a visible track,
110
+ and the legacy preloader stops rotating under reduced motion.
111
+
112
+ - Custom linear progress fills and indeterminate motion follow the inherited
113
+ text direction, including RTL and nested direction overrides. Reduced-motion
114
+ static fills use the same starting edge.
115
+
116
+ - Autocomplete exposes localized loading, result and multi-selection updates
117
+ through a polite live region. Teardown removes owned status elements and Menu
118
+ listeners, and late results after destruction are ignored.
119
+
120
+ - Date picker calendars support a single Tab stop, arrow keys, Home/End,
121
+ PageUp/PageDown and Shift for year navigation. Redraws preserve calendar focus,
122
+ and disabled days expose their unavailable state without allowing selection.
123
+
124
+ - Time picker hour/minute inputs have localized accessible names. Native AM/PM
125
+ buttons expose selected state and support Enter and Space without submitting
126
+ forms. Docked opening focuses the visible hour input; 24-hour entry accepts 00.
127
+
128
+ ### Migration
129
+
130
+ - Snackbars with `action` now default to `displayLength: Infinity` and
131
+ `dismissible: true`. Explicit options still override these defaults. Custom
132
+ template controls need these options explicitly. Timed feedback needs an
133
+ equivalent persistent message in the application.
134
+
135
+ - Replace `circle extra small` with `circle extra` for the 56dp FAB.
136
+ Extended FABs require an explicit size: replace sizeless `extend` with
137
+ `extend small`, or choose `extend medium` or `extend large`.
138
+ Use primary, secondary or tertiary container colors instead of surface-colored
139
+ FABs. General surface utilities remain available for other components.
140
+
141
+ - Replace FAB speed-dial wrappers `.fab` and `.fixed-action-btn` with
142
+ `.fab-menu` and labelled actions. Remove `direction`, `hoverEnabled`,
143
+ `toolbarEnabled` and their markup switches. Use a toolbar for persistent
144
+ commands instead of FAB-to-toolbar expansion.
145
+
146
+ - Replace banners with native inline messages for persistent nonblocking issues,
147
+ snackbars for temporary feedback, or dialogs for blocking decisions.
148
+ Remove banner classes, tokens and custom Sass imports. The existing
149
+ `/banners.html` route now explains the migration.
150
+
151
+ - Replace `.floating-sheet` with a dialog for blocking work, a bottom sheet on
152
+ compact layouts, or a side sheet for optional content on wider layouts.
153
+
154
+ - Replace `.bottom-app-bar` with `.toolbar.docked` or `.toolbar.fixed`. Place an
155
+ adjacent FAB in `.toolbar-group` when the layout needs one.
156
+ - Replace `.navigation-drawer`, `.sidenav`, `NavigationDrawer`, and `Sidenav`
157
+ with `NavigationRail`. Use a navigation bar on compact layouts when the same
158
+ hierarchy fits; use a native full-screen dialog for a larger compact menu.
159
+ - Replace `.segmented-button` with `.button-group.connected`. Keep native radio
160
+ or checkbox inputs when form submission is required, and synchronize button
161
+ state with those inputs in application code.
162
+
163
+ ### Changed
164
+
165
+ - Escape dismisses a focused snackbar without closing its parent dialog.
166
+ Dismissal and replacement recover focus when it remains inside the snackbar;
167
+ closing controls are inert, and application-directed focus is preserved.
168
+
169
+ - The documentation shell now uses a five-category rail with a page list on
170
+ wide layouts and a native full-screen navigation dialog on compact layouts.
171
+ Removed component URLs redirect to their replacement documentation.
172
+
173
+ ### Removed
174
+
175
+ - The 40dp small FAB and baseline sizeless extended FAB styling. Current small
176
+ extended FABs, medium/large FABs and FAB menus remain supported.
177
+
178
+ - FAB speed-dial styling, hover/directional layouts, toolbar expansion, and
179
+ legacy AutoInit selectors. The `FloatingActionButton` API now serves FAB menus.
180
+
181
+ - Banner Sass, component semantics, generated component guides and variant tests.
182
+
183
+ - Floating sheet Sass, documentation, semantics, generated guides and tests.
184
+
185
+ - Bottom app bar Sass, navigation drawer Sass and runtime APIs, segmented
186
+ button Sass, their documentation pages, semantics, generated guides, and
187
+ component-specific tests.
188
+
8
189
  ## [0.9.1] - 2026-09-08
9
190
 
10
191
  Includes the fixes from [#140](https://github.com/BaezFJ/ExpressiveCSS/pull/140).
@@ -1509,7 +1690,9 @@ are no compatibility aliases.
1509
1690
  - `.tabs` nested in a header or app bar as a secondary row. `.tabs` is a
1510
1691
  standalone component; the `.tabs.transparent` app bar variant is gone with it.
1511
1692
 
1512
- [Unreleased]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.9.1...HEAD
1693
+ [Unreleased]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.10.1...HEAD
1694
+ [0.10.1]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.10.0...v0.10.1
1695
+ [0.10.0]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.9.1...v0.10.0
1513
1696
  [0.9.1]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.9.0...v0.9.1
1514
1697
  [0.9.0]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.8.0...v0.9.0
1515
1698
  [0.8.0]: https://github.com/BaezFJ/ExpressiveCSS/compare/v0.7.0...v0.8.0
package/README.md CHANGED
@@ -4,7 +4,7 @@ ExpressiveCSS is a Material Design 3 front-end framework built with Sass and
4
4
  TypeScript. It provides theme tokens, layout and utility classes, styled form
5
5
  controls, and JavaScript components in browser, ES module, and CommonJS builds.
6
6
 
7
- > ExpressiveCSS is currently at version `0.9.1` and under active development.
7
+ > ExpressiveCSS version `0.10.1` is under active development.
8
8
 
9
9
  Documentation: [www.expressivecss.com](https://www.expressivecss.com)
10
10
 
@@ -24,14 +24,14 @@ Documentation: [www.expressivecss.com](https://www.expressivecss.com)
24
24
  - [Node.js](https://nodejs.org/) 20 or newer
25
25
  - npm
26
26
 
27
- Use Node 24 for repository development, selected by `.nvmrc`. The framework's
28
- runtime compatibility range remains unchanged. See [CONTRIBUTING.md](CONTRIBUTING.md)
27
+ Use Node 24 for repository development, selected by `.nvmrc`. The framework still
28
+ supports its existing runtime compatibility range. See [CONTRIBUTING.md](CONTRIBUTING.md)
29
29
  for setup, checks, and the community workflow.
30
30
 
31
31
  ## MCP server for AI workflows
32
32
 
33
- This repository includes a local MCP server at `mcp/expressivecss/` that exposes an
34
- ExpressiveCSS design-to-QA workflow:
33
+ A local MCP server at `mcp/expressivecss/` provides an ExpressiveCSS design-to-QA
34
+ workflow:
35
35
 
36
36
  - Setup Expert
37
37
  - Rules Enforcer
@@ -43,7 +43,7 @@ ExpressiveCSS design-to-QA workflow:
43
43
  The MCP entry point is `mcp/expressivecss/server.js`, with sample config in
44
44
  `mcp/expressivecss/mcp.json`.
45
45
 
46
- Quick start:
46
+ Start the server:
47
47
 
48
48
  ```sh
49
49
  cd mcp/expressivecss
@@ -51,7 +51,7 @@ npm ci
51
51
  node server.js
52
52
  ```
53
53
 
54
- To use it with your MCP client, point the command to:
54
+ Configure your MCP client with either command:
55
55
 
56
56
  - `node mcp/expressivecss/server.js`
57
57
  - or `node ./server.js` from `mcp/expressivecss` as the working directory.
@@ -65,7 +65,7 @@ npm ci
65
65
  npm run build
66
66
  ```
67
67
 
68
- The compiled assets are written to `dist/`:
68
+ The build writes compiled assets to `dist/`:
69
69
 
70
70
  ```text
71
71
  dist/
@@ -88,16 +88,15 @@ dist/
88
88
  └── types/
89
89
  ```
90
90
 
91
- Source maps are produced alongside the CSS and JavaScript bundles. The
92
- stylesheet loads fonts from `../fonts/`, so keep `dist/fonts/` next to
93
- `dist/css/`.
91
+ The build writes source maps beside the CSS and JavaScript bundles. The stylesheet
92
+ loads fonts from `../fonts/`, so keep `dist/fonts/` next to `dist/css/`.
94
93
 
95
94
  ## Usage
96
95
 
97
96
  ### Browser bundle
98
97
 
99
- Include the compiled stylesheet and browser bundle, then initialize components
100
- after the page has loaded:
98
+ Load the compiled stylesheet and browser bundle, then initialize components after
99
+ the page loads:
101
100
 
102
101
  ```html
103
102
  <link rel="stylesheet" href="dist/css/expressive.min.css">
@@ -127,9 +126,8 @@ const element = document.querySelector('.custom-tooltip');
127
126
  Tooltip.init(element, { position: 'top' });
128
127
  ```
129
128
 
130
- `AutoInit()` scans `document.body` by default. Pass a container to limit the
131
- scan, or add the `no-autoinit` class to an element that should be initialized
132
- manually:
129
+ `AutoInit()` scans `document.body` by default. Pass a container to limit the scan.
130
+ Add the `no-autoinit` class to any element you want to initialize manually:
133
131
 
134
132
  ```js
135
133
  AutoInit(document.querySelector('#app'), {
@@ -148,8 +146,164 @@ Use the framework's Sass entry point in another Sass project:
148
146
  @use "@expressivecss/expressive/src/sass/expressive";
149
147
  ```
150
148
 
151
- When working directly in this repository, the entry point is
152
- `src/sass/expressive.scss`.
149
+ For work in this repository, the Sass entry point is `src/sass/expressive.scss`.
150
+
151
+ ### Reduce page downloads
152
+
153
+ Use the optional ESM entry so a bundler can remove unused components:
154
+
155
+ ```ts
156
+ import { Tabs } from '@expressivecss/expressive/modular';
157
+ import type { TabsOptions } from '@expressivecss/expressive/modular';
158
+
159
+ const tabs = Tabs.init(document.querySelector('.tabs'));
160
+ ```
161
+
162
+ The type import supports TypeScript consumers. Initialize Tabs after its markup
163
+ exists, and call `tabs.destroy()` when removing it. The modular entry does not
164
+ initialize components on import. `AutoInit` remains available, but calling it
165
+ includes the full registry. The root entry retains the existing shared behaviors.
166
+ Both ESM entries share constructors. Copy the entire `dist/js` directory when
167
+ hosting ESM files directly. Direct browser imports do not remove unused exports.
168
+ The existing single-file IIFE and CommonJS builds remain available.
169
+
170
+ | Feature | Initialization with the modular entry |
171
+ | --- | --- |
172
+ | AppBar, Autocomplete, FloatingActionButton, ButtonGroup, Carousel, CharacterCounter, Datepicker, Menu, Lightbox, ScrollSpy, FormSelect, NavigationRail, Tabs, Timepicker, Tooltip | Call the component's `.init(element, options)` |
173
+ | Cards, ExpandingCard, Slider | Call `.init(element, options)` for owned elements, or `.Init()` once to discover matching document elements |
174
+ | Chips | Call `.init()` for managed chips; use `Chips.Init()` once for removal of static chips |
175
+ | Snackbar | Use the existing Snackbar constructor |
176
+ | Input validation, textarea resize, file input paths | Call `Forms.Init()` once after choosing these enhancements |
177
+ | Dialog light dismissal | Call `Dialogs.Init()` once |
178
+ | Bottom-sheet drag dismissal | Call `BottomSheets.Init()` once; add `Dialogs.Init()` for light dismissal |
179
+ | Side-sheet drag dismissal | Call `SideSheets.Init()` once; add `Dialogs.Init()` for light dismissal |
180
+
181
+ `Range` retains its Slider alias. Component initializers include internal
182
+ dependencies such as Menu in FormSelect, FormSelect in Datepicker, and Carousel in
183
+ swipeable Tabs. Do not initialize those instances separately. Document behaviors
184
+ apply to the whole page, so do not repeat their `.Init()` calls on route changes or
185
+ alongside the root entry.
186
+
187
+ Choose Sass partials with the custom entry. With Sass's Node package importer,
188
+ compile using `sass --pkg-importer=node app.scss app.css`:
189
+
190
+ ```scss
191
+ @use "pkg:@expressivecss/expressive/scss/custom" with (
192
+ $components: ("icons-material-design", "tabs", "carousel"),
193
+ $utilities: ()
194
+ );
195
+ ```
196
+
197
+ This Tabs recipe includes styling for the swipeable option. For FormSelect and
198
+ Datepicker, use this complete recipe instead:
199
+
200
+ ```scss
201
+ @use "pkg:@expressivecss/expressive/scss/custom" with (
202
+ $components: ("icons-material-design", "buttons", "menu", "forms", "datepicker"),
203
+ $utilities: ()
204
+ );
205
+ ```
206
+
207
+ ```js
208
+ import { Forms, FormSelect, Datepicker } from '@expressivecss/expressive/modular';
209
+
210
+ Forms.Init();
211
+ const select = FormSelect.init(document.querySelector('#choice'));
212
+ const datepicker = Datepicker.init(document.querySelector('#date'), { openByDefault: true });
213
+ ```
214
+
215
+ Destroy both component instances when removing that view. Add `"docked-display"`
216
+ before `"forms"` if using the picker's optional docked display plugin.
217
+
218
+ Tokens and base styles are always included. Lists load in the order written within
219
+ the original cascade layers. Partial names are relative to `components/` or
220
+ `utilities/`, without underscores or extensions. Keep icons first and follow the
221
+ order in the corresponding `_index.scss` when combining recipes. Add the supporting
222
+ partials required by your markup. For example, `$utilities: ("spacing",
223
+ "visibility")` includes those helpers. A `null` list includes the complete group by
224
+ default; `()` omits it. An unknown partial fails compilation.
225
+
226
+ Bundlers that resolve Sass package paths can use
227
+ `@expressivecss/expressive/scss/custom`; plain Sass with a `node_modules` load path
228
+ can use `@expressivecss/expressive/src/sass/custom`. Import one framework Sass
229
+ entry per stylesheet. The original full entry and compiled CSS are unchanged.
230
+
231
+ #### Smaller icon fonts
232
+
233
+ Browsers fetch only the font families used on the page. Using outlined icons alone
234
+ avoids downloading the rounded and sharp fonts. To reduce the outlined font, create
235
+ a subset with your own font tooling and turn off the bundled font declarations:
236
+
237
+ ```scss
238
+ @use "pkg:@expressivecss/expressive/scss/custom" with (
239
+ $components: ("icons-material-design", "tabs", "carousel"),
240
+ $utilities: (),
241
+ $expressive-include-fonts: false
242
+ );
243
+
244
+ @font-face {
245
+ font-family: "Material Symbols Outlined";
246
+ font-style: normal;
247
+ font-weight: 100 700;
248
+ font-display: block;
249
+ src: url("/assets/icons-outlined-subset.woff2") format("woff2");
250
+ }
251
+
252
+ @font-face {
253
+ font-family: "Roboto";
254
+ font-style: normal;
255
+ font-weight: 400;
256
+ font-display: swap;
257
+ src: url("/assets/roboto-latin-400.woff2") format("woff2");
258
+ }
259
+
260
+ @font-face {
261
+ font-family: "Roboto";
262
+ font-style: normal;
263
+ font-weight: 500;
264
+ font-display: swap;
265
+ src: url("/assets/roboto-latin-500.woff2") format("woff2");
266
+ }
267
+
268
+ @font-face {
269
+ font-family: "Noto Sans";
270
+ font-style: normal;
271
+ font-weight: 400;
272
+ font-display: swap;
273
+ src: url("/assets/noto-sans-latin-400.woff2") format("woff2");
274
+ }
275
+
276
+ @font-face {
277
+ font-family: "Noto Sans";
278
+ font-style: normal;
279
+ font-weight: 500;
280
+ font-display: swap;
281
+ src: url("/assets/noto-sans-latin-500.woff2") format("woff2");
282
+ }
283
+ ```
284
+
285
+ Copy the four text fonts from `dist/fonts` into `/assets`, along with their license
286
+ notices. Turning off the bundled faces also disables the text fonts. The declarations
287
+ above restore their existing names and weights. Supply corresponding subset faces
288
+ for rounded or sharp icons if the site uses them. Retain ligature shaping and the
289
+ `opsz`, `wght`, `FILL`, and `GRAD` axes in each variable subset.
290
+
291
+ Include icon names from templates, dynamic content, and framework-generated UI:
292
+
293
+ | Source | Required icon name |
294
+ | --- | --- |
295
+ | Chips removal buttons | `close`, using the configurable `closeIconClass` family |
296
+ | Snackbar dismissal button | `close` when the dismissal button is enabled |
297
+ | Expandable navigation rail summaries | `expand_more`, generated by CSS |
298
+
299
+ FormSelect uses CSS masks for its caret and selection marks. Datepicker uses text
300
+ for its configurable previous/next labels. By default, neither requires an
301
+ icon-font glyph. Custom markup and option values may add requirements. Subsets do
302
+ not cover new icons automatically, so retain full fonts for unrestricted icon names.
303
+
304
+ After building, run `node --test tests/selective-builds.test.js`. It records raw,
305
+ gzip, and Brotli sizes in `.cache/selective-builds/sizes.json`. The browser suite
306
+ records font requests and full/selective screenshots separately in that directory.
153
307
 
154
308
  ### Themes
155
309
 
@@ -167,7 +321,7 @@ document.documentElement.setAttribute('theme', 'dark');
167
321
 
168
322
  ## Development
169
323
 
170
- Available npm commands include:
324
+ The repository provides these npm commands:
171
325
 
172
326
  | Command | Purpose |
173
327
  | --- | --- |
@@ -190,13 +344,12 @@ Run the documentation and smoke-test site:
190
344
  npm run docs:dev
191
345
  ```
192
346
 
193
- This builds the framework, then starts the Sass and esbuild watchers alongside
194
- the documentation server. Refresh the browser to see source changes. Astro
195
- prints the server URL.
347
+ This command builds the framework, then starts the Sass and esbuild watchers with
348
+ the documentation server. Refresh the browser to see source changes. Astro prints
349
+ the server URL.
196
350
 
197
- It is the same site published at
198
- [www.expressivecss.com](https://www.expressivecss.com), authored in
199
- `docs/src/`.
351
+ The documentation source lives in `docs/src/` and is published at
352
+ [www.expressivecss.com](https://www.expressivecss.com).
200
353
 
201
354
  ## Project structure
202
355