actual-css 0.3.1 → 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.
Files changed (203) hide show
  1. package/CHANGELOG.md +67 -3
  2. package/README.md +35 -30
  3. package/dist/actual.css +73 -4946
  4. package/dist/actual.full.css +7090 -0
  5. package/dist/actual.full.js +1 -0
  6. package/dist/actual.full.min.css +1 -0
  7. package/dist/actual.js +1 -1
  8. package/dist/actual.min.css +1 -1
  9. package/docs/design-notes/cascade-layer.md +34 -13
  10. package/docs/design-notes/column-layout.md +677 -0
  11. package/docs/design-notes/forced-colors.md +3 -0
  12. package/docs/design-notes/grid.md +612 -0
  13. package/docs/design-notes/naming.md +15 -0
  14. package/docs/design-notes/widget-primitives.md +1 -0
  15. package/docs/navigation.json +5 -1
  16. package/docs/pages/components/alert.md +16 -14
  17. package/docs/pages/components/aura.md +1 -1
  18. package/docs/pages/components/avatar.md +6 -6
  19. package/docs/pages/components/badge.md +7 -7
  20. package/docs/pages/components/button.md +16 -16
  21. package/docs/pages/components/card.md +13 -9
  22. package/docs/pages/components/chat.md +8 -8
  23. package/docs/pages/components/dialog.md +7 -7
  24. package/docs/pages/components/drawer.md +3 -3
  25. package/docs/pages/components/fab.md +7 -7
  26. package/docs/pages/components/navbar.md +9 -8
  27. package/docs/pages/components/pagination.md +4 -3
  28. package/docs/pages/components/skeleton.md +4 -4
  29. package/docs/pages/components/spinner.md +5 -5
  30. package/docs/pages/components/table.md +30 -5
  31. package/docs/pages/enhancements/flyout.md +13 -13
  32. package/docs/pages/enhancements/overview.md +1 -1
  33. package/docs/pages/enhancements/scrollspy.md +6 -6
  34. package/docs/pages/enhancements/status-bar.md +5 -1
  35. package/docs/pages/enhancements/tabs.md +6 -6
  36. package/docs/pages/enhancements/tooltip.md +1 -1
  37. package/docs/pages/examples/overview.md +39 -22
  38. package/docs/pages/forms/choice-cards.md +11 -6
  39. package/docs/pages/forms/controls.md +1 -1
  40. package/docs/pages/forms/detached-actions.md +1 -1
  41. package/docs/pages/forms/floating-field.md +10 -5
  42. package/docs/pages/forms/form-actions.md +1 -1
  43. package/docs/pages/forms/input-policy.md +1 -1
  44. package/docs/pages/forms/joined-controls.md +4 -4
  45. package/docs/pages/forms/labels.md +6 -6
  46. package/docs/pages/forms/otp.md +1 -1
  47. package/docs/pages/forms/overview.md +19 -19
  48. package/docs/pages/forms/password.md +1 -1
  49. package/docs/pages/forms/range.md +1 -1
  50. package/docs/pages/forms/states-and-sizes.md +41 -45
  51. package/docs/pages/forms/sticky-actions.md +3 -3
  52. package/docs/pages/forms/switch.md +110 -2
  53. package/docs/pages/forms/validation.md +9 -9
  54. package/docs/pages/foundations/philosophy.md +1 -1
  55. package/docs/pages/foundations/theming.md +17 -2
  56. package/docs/pages/foundations/tokens.md +22 -10
  57. package/docs/pages/foundations/typography.md +50 -20
  58. package/docs/pages/guides/bootstrap.md +11 -11
  59. package/docs/pages/guides/integrating-actual-css.md +186 -0
  60. package/docs/pages/guides/introduction.md +23 -26
  61. package/docs/pages/guides/modular-import.md +173 -0
  62. package/docs/pages/guides/progressive-enhancement.md +81 -78
  63. package/docs/pages/guides/tailwind.md +6 -8
  64. package/docs/pages/layout/app-shell.md +1 -1
  65. package/docs/pages/layout/center.md +1 -1
  66. package/docs/pages/layout/choosing.md +39 -0
  67. package/docs/pages/layout/column-layout.md +206 -0
  68. package/docs/pages/layout/frame.md +6 -1
  69. package/docs/pages/layout/grid.md +100 -102
  70. package/docs/pages/layout/list.md +1 -1
  71. package/docs/pages/layout/media.md +1 -1
  72. package/docs/pages/layout/overview.md +15 -2
  73. package/docs/pages/layout/scroll-snap.md +2 -2
  74. package/docs/pages/layout/scroll-target.md +45 -0
  75. package/docs/pages/layout/sidebar-layout.md +20 -19
  76. package/docs/pages/layout/stack.md +53 -1
  77. package/docs/pages/layout/switcher.md +10 -26
  78. package/docs/pages/layout/topbar.md +2 -2
  79. package/docs/pages/patterns/actions.md +1 -1
  80. package/docs/pages/patterns/code-block.md +1 -1
  81. package/docs/pages/patterns/exclusive-accordion.md +1 -1
  82. package/docs/pages/patterns/hierarchical-nav.md +1 -1
  83. package/docs/pages/patterns/icon-input.md +1 -1
  84. package/docs/pages/patterns/intent-nesting.md +1 -1
  85. package/docs/pages/patterns/navigation-list.md +1 -1
  86. package/docs/pages/patterns/overview.md +1 -1
  87. package/docs/pages/patterns/structured-lists.md +1 -1
  88. package/docs/pages/utilities/accessibility.md +3 -3
  89. package/docs/pages/utilities/flex.md +15 -15
  90. package/docs/pages/utilities/links.md +4 -4
  91. package/docs/pages/utilities/list.md +8 -8
  92. package/docs/pages/utilities/overflow.md +8 -8
  93. package/docs/pages/utilities/overview.md +1 -1
  94. package/docs/pages/utilities/shape.md +3 -3
  95. package/docs/pages/utilities/sizing-wrapping.md +23 -16
  96. package/docs/pages/utilities/spacing.md +20 -20
  97. package/docs/pages/utilities/text.md +10 -10
  98. package/llms.txt +46 -4
  99. package/package.json +42 -13
  100. package/scripts/reserved-classes.json +261 -0
  101. package/src/cli/actual-css.js +133 -0
  102. package/src/css/actual.css +1 -31
  103. package/src/css/actual.full.css +11 -2
  104. package/src/css/components/alert.css +17 -4
  105. package/src/css/components/badge.css +18 -6
  106. package/src/css/components/breadcrumb.css +1 -1
  107. package/src/css/components/button.css +19 -1
  108. package/src/css/components/card.css +27 -2
  109. package/src/css/components/drawer.css +27 -2
  110. package/src/css/components/flyout.css +5 -0
  111. package/src/css/components/index.css +32 -27
  112. package/src/css/components/join.css +8 -1
  113. package/src/css/components/key.css +2 -0
  114. package/src/css/components/menu.css +11 -1
  115. package/src/css/components/meter.css +4 -1
  116. package/src/css/components/modal.css +5 -0
  117. package/src/css/components/pagination.css +11 -0
  118. package/src/css/components/spinner.css +5 -0
  119. package/src/css/components/status-bar.css +5 -0
  120. package/src/css/components/surface.css +5 -0
  121. package/src/css/components/table.css +6 -0
  122. package/src/css/components/tooltip.css +5 -0
  123. package/src/css/core/index.css +9 -0
  124. package/src/css/core/print.css +18 -0
  125. package/src/css/{theme.css → core/theme.css} +20 -10
  126. package/src/css/{tokens.css → core/tokens.css} +15 -2
  127. package/src/css/{variants.css → core/variants.css} +3 -2
  128. package/src/css/effects/index.css +2 -0
  129. package/src/css/forms/base.css +8 -0
  130. package/src/css/forms/choice-card.css +5 -4
  131. package/src/css/forms/choice.css +49 -37
  132. package/src/css/forms/control.css +4 -1
  133. package/src/css/forms/custom-select.css +2 -0
  134. package/src/css/{optional → forms}/floating-field.css +25 -7
  135. package/src/css/forms/index.css +10 -13
  136. package/src/css/forms/native.css +15 -2
  137. package/src/css/{optional → forms}/otp.css +20 -16
  138. package/src/css/forms/switch.css +31 -29
  139. package/src/css/layout/app-shell.css +6 -0
  140. package/src/css/layout/center.css +13 -0
  141. package/src/css/layout/cluster.css +21 -0
  142. package/src/css/layout/column-layout.css +144 -0
  143. package/src/css/layout/container-query.css +13 -0
  144. package/src/css/layout/frame.css +19 -0
  145. package/src/css/layout/grid.css +141 -0
  146. package/src/css/layout/index.css +42 -0
  147. package/src/css/layout/measure.css +9 -0
  148. package/src/css/layout/media.css +10 -0
  149. package/src/css/layout/scroll-target.css +15 -0
  150. package/src/css/layout/scroller.css +41 -0
  151. package/src/css/layout/sidebar-layout.css +31 -0
  152. package/src/css/layout/stack.css +21 -0
  153. package/src/css/layout/switcher.css +23 -0
  154. package/src/css/{optional/layout-extra.css → layout/topbar.css} +0 -20
  155. package/src/css/typography/index.css +5 -0
  156. package/src/css/typography/lead.css +7 -0
  157. package/src/css/{components → typography}/overline.css +2 -2
  158. package/src/css/{prose.css → typography/prose.css} +53 -38
  159. package/src/css/{utilities.css → utilities/base.css} +2 -0
  160. package/src/css/utilities/index.css +3 -0
  161. package/src/js/escape.js +36 -0
  162. package/src/js/flyout.js +22 -12
  163. package/src/js/full.js +26 -0
  164. package/src/js/index.js +5 -21
  165. package/src/js/surface.js +1 -31
  166. package/src/js/tooltip.js +46 -18
  167. package/src/js/validation.js +1 -1
  168. package/src/tooling/css-bundle.js +308 -0
  169. package/dist/actual-themes.min.css +0 -1
  170. package/dist/optional.css +0 -1048
  171. package/dist/optional.min.css +0 -1
  172. package/docs/pages/guides/optional-components.md +0 -33
  173. package/src/css/grid.css +0 -109
  174. package/src/css/layout.css +0 -123
  175. package/src/css/optional/index.css +0 -10
  176. package/src/css/optional/scroller.css +0 -63
  177. package/src/css/print.css +0 -47
  178. package/src/css/themes/corporate.css +0 -60
  179. package/src/css/themes/cyberpunk.css +0 -60
  180. package/src/css/themes/dim.css +0 -33
  181. package/src/css/themes/edge.css +0 -117
  182. package/src/css/themes/forest.css +0 -65
  183. package/src/css/themes/gradient.css +0 -97
  184. package/src/css/themes/index.css +0 -47
  185. package/src/css/themes/indigo.css +0 -33
  186. package/src/css/themes/lavender.css +0 -66
  187. package/src/css/themes/mono.css +0 -60
  188. package/src/css/themes/neon.css +0 -66
  189. package/src/css/themes/ocean.css +0 -60
  190. package/src/css/themes/petrol.css +0 -64
  191. package/src/css/themes/spruce.css +0 -64
  192. package/src/css/themes/square.css +0 -65
  193. package/src/css/themes/sunset.css +0 -66
  194. /package/src/css/{optional → components}/chat.css +0 -0
  195. /package/src/css/{optional → components}/fab.css +0 -0
  196. /package/src/css/{base.css → core/base.css} +0 -0
  197. /package/src/css/{focus.css → core/focus.css} +0 -0
  198. /package/src/css/{intents.css → core/intents.css} +0 -0
  199. /package/src/css/{reset.css → core/reset.css} +0 -0
  200. /package/src/css/{optional → effects}/aura.css +0 -0
  201. /package/src/css/{optional → layout}/scroll-snap.css +0 -0
  202. /package/src/css/{optional/typography-fluid.css → typography/fluid.css} +0 -0
  203. /package/src/css/{optional/utilities-extra.css → utilities/extra.css} +0 -0
@@ -0,0 +1,173 @@
1
+ # Modular imports
2
+
3
+ Actual CSS ships one minimal core (`actual-css`) and one all-in entrypoint (`actual-css/full`). Projects can also compose the framework from family manifests or individual modules.
4
+
5
+ ## Entrypoints
6
+
7
+ ```css
8
+ @import "actual-css"; /* minimal core */
9
+ @import "actual-css/full"; /* complete framework */
10
+ ```
11
+
12
+ `actual-css` contains the shared baseline: reset, tokens, theme, document defaults, intents, universal variants, focus, and print.
13
+
14
+ It contains no typography, layout, forms, components, effects, or utilities.
15
+
16
+ `actual-css/full` starts from the core and adds every family in cascade order:
17
+
18
+ ```text
19
+ core → typography → layout → forms → components → effects → utilities
20
+ ```
21
+
22
+ ### Focus is a core invariant
23
+
24
+ The core provides a visible `:focus` outline as the compatibility baseline. Modern browsers limit it to `:focus-visible`, hiding the pointer-focus outline.
25
+
26
+ Components may enhance or replace that treatment in interactive states, but their base styles must not cancel the shared fallback.
27
+
28
+ When an interactive state replaces the outline, it must preserve a visible focus indicator in forced-colors, either with an outline-based fallback or by keeping the replacement out of forced-colors.
29
+
30
+ ## Family manifests
31
+
32
+ | Family | Import | Contents |
33
+ | ---------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
34
+ | Core | `actual-css/css` | reset, tokens, theme, base, intents, variants, focus, print |
35
+ | Typography | `actual-css/css/typography` | prose, overline, fluid |
36
+ | Layout | `actual-css/css/layout` | stack, cluster, center, frame, media, switcher, sidebar-layout, grid, scroller, scroll-snap, topbar, container-query, app-shell |
37
+ | Forms | `actual-css/css/forms` | native control baseline |
38
+ | Forms (complete) | `actual-css/css/forms/all` | base plus input-icon, switch, range, choice-card, custom-select, floating-field, otp |
39
+ | Components | `actual-css/css/components` | buttons, surfaces, overlays, feedback, navigation, data and composed controls |
40
+ | Effects | `actual-css/css/effects` | aura |
41
+ | Utilities | `actual-css/css/utilities` | base and extra utilities |
42
+
43
+ Individual modules can be imported through their domain path:
44
+
45
+ ```css
46
+ @import "actual-css/css/forms/otp";
47
+ @import "actual-css/css/components/chat";
48
+ @import "actual-css/css/effects/aura";
49
+ @import "actual-css/css/layout/scroller";
50
+ @import "actual-css/css/typography/fluid";
51
+ @import "actual-css/css/utilities/extra";
52
+ ```
53
+
54
+ ## Use your existing CSS pipeline
55
+
56
+ Actual CSS is plain CSS and does not require its own build tool.
57
+
58
+ If a project already uses Vite, PostCSS, Webpack, Parcel, Lightning CSS, or another CSS pipeline, keep using it and import the Actual CSS package exports directly.
59
+
60
+ For example:
61
+
62
+ ```css
63
+ @import "actual-css/css";
64
+ @import "actual-css/css/layout";
65
+ @import "actual-css/css/forms/all";
66
+ @import "actual-css/css/components/button";
67
+ @import "actual-css/css/components/card";
68
+
69
+ @import "./theme.css";
70
+ @import "./app.css";
71
+ ```
72
+
73
+ The consuming pipeline remains responsible for features such as asset handling, URL rebasing, source maps, CSS Modules, import modifiers, transpilation, and browser targeting.
74
+
75
+ Actual CSS intentionally does not require a particular bundler or transpiler.
76
+
77
+ ## Optional CLI bundler
78
+
79
+ For projects without a CSS pipeline, Actual CSS includes a small zero-dependency import flattener:
80
+
81
+ ```sh
82
+ npx actual-css bundle src/app.css --out public/app.css
83
+ ```
84
+
85
+ or:
86
+
87
+ ```sh
88
+ bunx actual-css bundle src/app.css --out public/app.css
89
+ ```
90
+
91
+ Add `--minify` for lightweight whitespace/comment minification:
92
+
93
+ ```sh
94
+ npx actual-css bundle src/app.css --out public/app.css --minify
95
+ ```
96
+
97
+ The CLI resolves and inlines:
98
+
99
+ ```css
100
+ @import "./local.css";
101
+ @import "actual-css/css/layout";
102
+ @import "actual-css/css/components/card";
103
+ ```
104
+
105
+ It deliberately does **not** transpile CSS. Modern syntax such as nesting, `@container`, `@scope`, `:has()`, `color-mix()`, `light-dark()`, and media-query range syntax is preserved for the browser.
106
+
107
+ The CLI is a simple flattener, not a general-purpose CSS build pipeline.
108
+
109
+ ### Limitations
110
+
111
+ Local and package imports may be plain imports, or carry a layer modifier:
112
+
113
+ ```css
114
+ @import "./local.css";
115
+ @import "./local.css" layer(components);
116
+ @import "./local.css" layer;
117
+ ```
118
+
119
+ A layered import is flattened into the block it stands for, so `@import "actual-css/css" layer(actual)` becomes `@layer actual { … }`. A layer declared inside the imported file becomes a sublayer of that wrapper, exactly as the import did.
120
+
121
+ Conditional modifiers are not flattened:
122
+
123
+ ```css
124
+ @import "./local.css" supports(display: grid);
125
+ @import "./local.css" screen;
126
+ @import "./local.css" layer(components) supports(display: grid);
127
+ ```
128
+
129
+ Use an existing CSS pipeline when these features are required.
130
+
131
+ One further case is refused rather than guessed: a remote import inside a layered subtree, because hoisting it before ordinary rules would move it out of its layer.
132
+
133
+ The CLI also does not process or rebase asset URLs such as:
134
+
135
+ ```css
136
+ background-image: url("../images/card.svg");
137
+ ```
138
+
139
+ Those paths remain exactly as written, so projects with relative assets should generally let their existing build pipeline handle CSS imports.
140
+
141
+ Remote and absolute imports are preserved rather than fetched and are moved before ordinary rules so they remain valid CSS.
142
+
143
+ ## Cascade layers
144
+
145
+ Actual CSS can participate in a project-owned cascade layer:
146
+
147
+ ```css
148
+ @layer actual;
149
+
150
+ @import "actual-css/full" layer(actual);
151
+ ```
152
+
153
+ Or, when composing families:
154
+
155
+ ```css
156
+ @layer actual;
157
+
158
+ @import "actual-css/css" layer(actual);
159
+ @import "actual-css/css/typography" layer(actual);
160
+ @import "actual-css/css/layout" layer(actual);
161
+ @import "actual-css/css/forms/all" layer(actual);
162
+ @import "actual-css/css/components" layer(actual);
163
+ ```
164
+
165
+ `actual-css/css/layer` also exposes the minimal core wrapped in `@layer actual`.
166
+
167
+ All of these recipes flatten with `actual-css bundle`: the CLI understands layer modifiers, so a public entrypoint of the framework is never something its own bundler has to refuse.
168
+
169
+ ## Custom properties
170
+
171
+ Component-prefixed custom properties documented on component pages are author hooks.
172
+
173
+ Color and sizing otherwise stay within the shared intent, variant, control, and button APIs.
@@ -2,11 +2,12 @@
2
2
 
3
3
  > The optional JavaScript runtime that progressively enhances Actual's semantic markup — self-registering side-effect modules, the `enhance()` DOM lifecycle, stateless command routing, and the floating and surface contracts for custom widgets.
4
4
 
5
- Actual's JavaScript modules are optional. Importing `actual-css/js` registers the
6
- complete default runtime — every built-in enhancer, including validation and
7
- status; importing a specific module registers only that behavior. The runtime
8
- does not require `DOMContentLoaded` or manual init calls, and it never touches
9
- `window`: there is no global object to call into.
5
+ Actual's JavaScript modules are optional. Importing `actual-css/js/full`
6
+ registers the complete default runtime — every built-in enhancer, including
7
+ validation and status. Importing `actual-css/js` registers only the enhancement
8
+ manifest loader; importing a specific module registers only that behavior. The
9
+ runtime does not require `DOMContentLoaded` or manual init calls, and it never
10
+ touches `window`: there is no global object to call into.
10
11
 
11
12
  ## Browser support
12
13
 
@@ -16,12 +17,12 @@ unsupported — it is not tested, documented as supported, or preserved when the
16
17
  runtime evolves. The runtime assumes the modern platform primitives available
17
18
  across Minimal and ships no compatibility layer or polyfill.
18
19
 
19
- | Tier | Firefox | Safari | Chromium |
20
- |---|---|---|---|
21
- | Degraded | 78+ | 14+ | 88+ |
22
- | **Minimal** | **98+** | **15.4+** | **99+** |
23
- | Intermediate | 121+ | 16+ | 106+ |
24
- | Recommended | 129+ | 17.5+ | 123+ |
20
+ | Tier | Firefox | Safari | Chromium |
21
+ |--------------|---------|-----------|----------|
22
+ | Degraded | 78+ | 14+ | 88+ |
23
+ | **Minimal** | **98+** | **15.4+** | **99+** |
24
+ | Intermediate | 121+ | 16+ | 106+ |
25
+ | Recommended | 129+ | 17.5+ | 123+ |
25
26
 
26
27
  The tier definitions live in the browser-support design note.
27
28
 
@@ -57,13 +58,14 @@ handle, and cleanup happens per element when an element leaves the DOM.
57
58
 
58
59
  ## The default runtime
59
60
 
60
- Loading `dist/actual.js` as a plain `<script>` (no `type="module"`, no bundler,
61
- no `import`) gets the full runtime. Static HTML that needs to trigger something
62
- from its own inline `<script>` dispatches the module's public event instead of
63
- calling into a global — `actual:status` for the status bar, for example:
61
+ Loading `dist/actual.full.js` as a plain `<script>` (no `type="module"`, no
62
+ bundler, no `import`) gets the full runtime. Static HTML that needs to trigger
63
+ something from its own inline `<script>` dispatches the module's public event
64
+ instead of calling into a global — `actual:status` for the status bar, for
65
+ example:
64
66
 
65
67
  ```html
66
- <script src="actual.js"></script>
68
+ <script src="actual.full.js"></script>
67
69
  <script>
68
70
  document.dispatchEvent(new CustomEvent("actual:status", {
69
71
  bubbles: true,
@@ -72,24 +74,24 @@ calling into a global — `actual:status` for the status bar, for example:
72
74
  </script>
73
75
  ```
74
76
 
75
- | Module | Behavior |
76
- |---|---|
77
- | `actual-css/js/flyout` | Trigger → panel surface: positioning, open/close, sheet mode (token `flyout`) |
78
- | `actual-css/js/context-menu` | Context menus on `data-context-menu` |
79
- | `actual-css/js/focus-group` | Reusable roving-focus controller; no automatic discovery |
80
- | `actual-css/js/dialog` | Native `<dialog>` behavior, focus management, dismissal |
81
- | `actual-css/js/dismiss` | The generic `--dismiss` command |
82
- | `actual-css/js/tab` | Tab panels and arrow-key navigation (token `tabs`) |
83
- | `actual-css/js/tooltip` | Tooltips on `data-tooltip` |
84
- | `actual-css/js/scrollspy` | Scroll-driven nav highlighting (token `scrollspy`) |
85
- | `actual-css/js/filter` | Input value filtering on `data-filter` |
86
- | `actual-css/js/mask` | Input masks on `data-mask` |
87
- | `actual-css/js/password` | Password reveal toggle |
88
- | `actual-css/js/validation` | Form validation (token `validation`) |
89
- | `actual-css/js/status` | Singleton status bar on `[data-status][role="status"]` |
90
- | `actual-css/js/enhancement-loader` | Declared enhancement manifests (`data-enhance-modules`, `Enhance-Modules`) |
91
-
92
- Use `actual-css/js` for demos, playgrounds, and smoke tests where one import
77
+ | Module | Behavior |
78
+ |------------------------------------|-------------------------------------------------------------------------------|
79
+ | `actual-css/js/flyout` | Trigger → panel surface: positioning, open/close, sheet mode (token `flyout`) |
80
+ | `actual-css/js/context-menu` | Context menus on `data-context-menu` |
81
+ | `actual-css/js/focus-group` | Reusable roving-focus controller; no automatic discovery |
82
+ | `actual-css/js/dialog` | Native `<dialog>` behavior, focus management, dismissal |
83
+ | `actual-css/js/dismiss` | The generic `--dismiss` command |
84
+ | `actual-css/js/tab` | Tab panels and arrow-key navigation (token `tabs`) |
85
+ | `actual-css/js/tooltip` | Tooltips on `data-tooltip` |
86
+ | `actual-css/js/scrollspy` | Scroll-driven nav highlighting (token `scrollspy`) |
87
+ | `actual-css/js/filter` | Input value filtering on `data-filter` |
88
+ | `actual-css/js/mask` | Input masks on `data-mask` |
89
+ | `actual-css/js/password` | Password reveal toggle |
90
+ | `actual-css/js/validation` | Form validation (token `validation`) |
91
+ | `actual-css/js/status` | Singleton status bar on `[data-status][role="status"]` |
92
+ | `actual-css/js/enhancement-loader` | Declared enhancement manifests (`data-enhance-modules`, `Enhance-Modules`) |
93
+
94
+ Use `actual-css/js/full` for demos, playgrounds, and smoke tests where one import
93
95
  enables every built-in behavior. Production apps can import individual modules
94
96
  such as `actual-css/js/validation` or `actual-css/js/status` when only those are
95
97
  needed.
@@ -122,15 +124,16 @@ For building custom widgets (select, tags, date picker) on Actual's primitives,
122
124
  see the widget-primitives design note. Every primitive subpath is published in
123
125
  `package.json#exports`:
124
126
 
125
- | Subpath | Purpose |
126
- |---|---|
127
- | `actual-css/js/enhance` | DOM lifecycle engine: `enhance()`, `registerEnhancement`, tokens |
128
- | `actual-css/js/events` | The `actual:*` event name constants |
129
- | `actual-css/js/floating` | Positioning engine (`reposition`, `repositionAt`, `autoUpdate`) |
130
- | `actual-css/js/focus` | Focusable-item lookup and helpers |
131
- | `actual-css/js/keys` | Roving-focus item navigation helpers |
132
- | `actual-css/js/menu` | Menu keyboard/click wiring, item vocabulary |
133
- | `actual-css/js/surface` | Surface lifecycle (`openSurface`, `closeSurface`, …) |
127
+ | Subpath | Purpose |
128
+ |--------------------------|------------------------------------------------------------------|
129
+ | `actual-css/js/enhance` | DOM lifecycle engine: `enhance()`, `registerEnhancement`, tokens |
130
+ | `actual-css/js/escape` | Per-document LIFO Escape dismissal stack |
131
+ | `actual-css/js/events` | The `actual:*` event name constants |
132
+ | `actual-css/js/floating` | Positioning engine (`reposition`, `repositionAt`, `autoUpdate`) |
133
+ | `actual-css/js/focus` | Focusable-item lookup and helpers |
134
+ | `actual-css/js/keys` | Roving-focus item navigation helpers |
135
+ | `actual-css/js/menu` | Menu keyboard/click wiring, item vocabulary |
136
+ | `actual-css/js/surface` | Surface lifecycle (`openSurface`, `closeSurface`, …) |
134
137
 
135
138
  The exports map is explicit — it *is* the statement of what is public.
136
139
 
@@ -152,14 +155,14 @@ const stop = autoUpdate(float, () => {
152
155
 
153
156
  Options passed to `reposition()`:
154
157
 
155
- | Option | Default | Contract |
156
- |---|---|---|
157
- | `placement` | `"bottom-start"` | Preferred side and alignment (`-start` / `-end`) |
158
- | `distance` | `0` | Gap between the reference and the floating element |
159
- | `flip` | `true` | Flip to the opposite side when the preferred side is out of view |
160
- | `shift` | `true` | Shift along the main axis to stay within the boundary |
161
- | `shiftPadding` | `4` | Minimum space kept from the boundary |
162
- | `scope` | viewport | Boundary element for overflow decisions |
158
+ | Option | Default | Contract |
159
+ |----------------|------------------|------------------------------------------------------------------|
160
+ | `placement` | `"bottom-start"` | Preferred side and alignment (`-start` / `-end`) |
161
+ | `distance` | `0` | Gap between the reference and the floating element |
162
+ | `flip` | `true` | Flip to the opposite side when the preferred side is out of view |
163
+ | `shift` | `true` | Shift along the main axis to stay within the boundary |
164
+ | `shiftPadding` | `4` | Minimum space kept from the boundary |
165
+ | `scope` | viewport | Boundary element for overflow decisions |
163
166
 
164
167
  `autoUpdate(element, callback)` batches scroll, resize, and element-resize
165
168
  callbacks per document and returns a stop handle; it does not keep a closed or
@@ -195,30 +198,30 @@ Two non-obvious requirements:
195
198
 
196
199
  Lifecycle: `prepareSurface` → `openSurface` → `closeSurface` →
197
200
  `disconnectSurface`. `retainSurface(panel)` reference-counts a surface shared by
198
- several triggers and returns a release function; `registerEscapeDismissal` adds
199
- an element to the per-document Escape dismiss stack; `isSurfaceOpen` and
200
- `getSurfaceAutoClose` read current state.
201
+ several triggers and returns a release function; `isSurfaceOpen` and
202
+ `getSurfaceAutoClose` read current state. The separate `escape` primitive adds
203
+ visible dismissable UI to the shared per-document Escape stack.
201
204
 
202
205
  `openSurface(menu, opts)` dispatches a cancelable `actual:surface-open` event —
203
206
  widgets can veto or decorate opens, and context menus inject their own
204
207
  `source`/`restoreFocusTo` through it.
205
208
 
206
- | Option | Default | Contract |
207
- |---|---|---|
208
- | `trigger` | — | Anchoring element; also the focus-restore target by default |
209
- | `source` | — | Alternate anchor when there is no trigger |
210
- | `x`, `y` | — | Position at a fixed viewport point instead of an anchor (context menus) |
211
- | `placement` | `"bottom-start"` | Preferred placement |
212
- | `distance` | `4` | Gap between anchor and surface |
213
- | `flip` | `true` | Flip when the preferred side is out of view |
214
- | `shift` | `true` | Shift to stay within the boundary |
215
- | `shiftPadding` | `4` | Minimum space kept from the boundary |
216
- | `scope` | viewport | Boundary element |
217
- | `mobile` | `"auto"` | `"auto"`, `"sheet"`, `"none"`, or `"anchored"` sheet behavior |
218
- | `breakpoint` | `768` | Max viewport width for an automatic sheet |
219
- | `autoClose` | `"outside"` | `"true"` closes for inside and outside clicks; `"inside"` and `"outside"` limit the side; `"false"` disables automatic click closing. Invalid values use `"true"` |
220
- | `dismissOnScroll` | `false` | Close when scrolling outside the surface follows a new user input; opening/focus scroll is ignored |
221
- | `restoreFocusTo` | `trigger` or `source` | Element focused on close |
209
+ | Option | Default | Contract |
210
+ |-------------------|-----------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
211
+ | `trigger` | — | Anchoring element; also the focus-restore target by default |
212
+ | `source` | — | Alternate anchor when there is no trigger |
213
+ | `x`, `y` | — | Position at a fixed viewport point instead of an anchor (context menus) |
214
+ | `placement` | `"bottom-start"` | Preferred placement |
215
+ | `distance` | `4` | Gap between anchor and surface |
216
+ | `flip` | `true` | Flip when the preferred side is out of view |
217
+ | `shift` | `true` | Shift to stay within the boundary |
218
+ | `shiftPadding` | `4` | Minimum space kept from the boundary |
219
+ | `scope` | viewport | Boundary element |
220
+ | `mobile` | `"auto"` | `"auto"`, `"sheet"`, `"none"`, or `"anchored"` sheet behavior |
221
+ | `breakpoint` | `768` | Max viewport width for an automatic sheet |
222
+ | `autoClose` | `"outside"` | `"true"` closes for inside and outside clicks; `"inside"` and `"outside"` limit the side; `"false"` disables automatic click closing. Invalid values use `"true"` |
223
+ | `dismissOnScroll` | `false` | Close when scrolling outside the surface follows a new user input; opening/focus scroll is ignored |
224
+ | `restoreFocusTo` | `trigger` or `source` | Element focused on close |
222
225
 
223
226
  The click policy belongs to the surface rather than to a particular menu
224
227
  anatomy. The generic primitive defaults to outside-click dismissal; flyout and
@@ -239,14 +242,14 @@ The runtime dispatches a small set of public `actual:*` events. All are
239
242
  listenable on the document; cancelable events veto the associated action when
240
243
  `preventDefault()` is called.
241
244
 
242
- | Event | Dispatch | Contract |
243
- |---|---|---|
244
- | `actual:surface-open` | `openSurface()`, before a surface opens | Cancelable. `detail: { surface, options }` |
245
- | `actual:context-menu` | context-menu, before its menu opens | Cancelable. `detail: { menu, context, origin, trigger }` |
246
- | `actual:status` | status module, or any code | Show or clear the status bar. `detail: { message, intent, duration }`; omit `message` to clear |
247
- | `actual:invalid` | validation, after a submit was blocked | `detail: { form, firstInvalid, message }` |
248
- | `actual:dialog-cancel` | dialog, before native cancel close | Cancelable. `detail: { dialog, sourceEvent }` |
249
- | `actual:dismiss` | `--dismiss` command, after hiding a target | `detail: { trigger }` |
245
+ | Event | Dispatch | Contract |
246
+ |------------------------|--------------------------------------------|------------------------------------------------------------------------------------------------|
247
+ | `actual:surface-open` | `openSurface()`, before a surface opens | Cancelable. `detail: { surface, options }` |
248
+ | `actual:context-menu` | context-menu, before its menu opens | Cancelable. `detail: { menu, context, origin, trigger }` |
249
+ | `actual:status` | status module, or any code | Show or clear the status bar. `detail: { message, intent, duration }`; omit `message` to clear |
250
+ | `actual:invalid` | validation, after a submit was blocked | `detail: { form, firstInvalid, message }` |
251
+ | `actual:dialog-cancel` | dialog, before native cancel close | Cancelable. `detail: { dialog, sourceEvent }` |
252
+ | `actual:dismiss` | `--dismiss` command, after hiding a target | `detail: { trigger }` |
250
253
 
251
254
  ## Extending the runtime
252
255
 
@@ -25,14 +25,14 @@ The layered import is the cleanest way to keep both stylesheets during the
25
25
  migration:
26
26
 
27
27
  ```css
28
- /* Migration setup — Actual rules sit in @layer actual */
29
28
  @import "tailwind.css"; /* your compiled Tailwind output */
30
- @import "actual-css/css/layer";
29
+ @layer actual;
30
+ @import "actual-css/full" layer(actual);
31
31
  /* Unlayered project overrides stay on top */
32
32
  @import "app.css";
33
33
  ```
34
34
 
35
- `actual.layer.css` wraps every Actual rule in a single `@layer actual`, so
35
+ The full import places every Actual rule in a single `actual` layer, so
36
36
  unlayered Tailwind output and project CSS keep precedence while the migration
37
37
  runs. See [Cascade layer strategy](https://github.com/lekoala/actual-css/blob/master/docs/design-notes/cascade-layer.md) for the
38
38
  limitations of the approach.
@@ -128,13 +128,11 @@ Actual:
128
128
  </div>
129
129
  ```
130
130
 
131
- If the grid should respond to its container:
131
+ If these are independent items that should reflow with available space:
132
132
 
133
133
  ```html
134
- <div class="container-query">
135
- <div class="grid-3">
136
- ...
137
- </div>
134
+ <div class="grid" style="--grid-min: 16rem">
135
+ ...
138
136
  </div>
139
137
  ```
140
138
 
@@ -22,4 +22,4 @@ Use semantic elements by default.
22
22
  }
23
23
  ```
24
24
 
25
- Sticky header/footer behavior should be opt-in and documented only if it becomes part of the shipped layout API.
25
+ Sticky header/footer behavior should be opt-in and documented only if it becomes part of the shipped layout API.
@@ -26,4 +26,4 @@ Tune width and side padding with local variables.
26
26
 
27
27
  `.center` intentionally uses `box-sizing: content-box`. The max inline size is
28
28
  the content measure, while inline padding is added outside that measure. This is
29
- deliberate even though the global reset uses `border-box`.
29
+ deliberate even though the global reset uses `border-box`.
@@ -0,0 +1,39 @@
1
+ # Choosing a layout
2
+
3
+ Choose a primitive from the relationship between its children, not from the
4
+ number of children visible in one mockup.
5
+
6
+ | Situation | Primitive |
7
+ |--------------------------------------------------------------|-------------------|
8
+ | Vertical flow | `.stack` |
9
+ | Inline actions, tags, or navigation that may wrap | `.cluster` |
10
+ | Responsive collection; an incomplete final row is acceptable | `.grid` |
11
+ | Known structural density, at most N columns | `.grid-N` |
12
+ | Peer regions that must switch together | `.switcher` |
13
+ | Main content followed by a secondary region | `.sidebar-layout` |
14
+ | Fixed media followed by flexible content | `.media` |
15
+ | Explicit region placement on a shared 12-column canvas | `.column-layout` |
16
+
17
+ For cards, products, results, and galleries, start with `.grid`. Use a fixed
18
+ `.grid-N` only when N columns remain part of the structure at every width. If
19
+ all peers should move together rather than form a partial row, use `.switcher`.
20
+
21
+ For a main region plus an aside, use `.sidebar-layout`.
22
+
23
+ Use `.column-layout` when the placement of each region is itself part of the
24
+ design — a 10-column article starting on column 2, regions in separate sibling
25
+ sections that must share the same column lines, an editorial composition whose
26
+ starts and spans are deliberately aligned across the page. It is the one layout
27
+ primitive with no automatic responsive behavior: the canvas stays twelve
28
+ columns and the application owns narrow-container recomposition. Choose it
29
+ because placement is the design, not because a mockup happens to contain
30
+ columns.
31
+
32
+ Use `--grid-columns` for exact track templates that do not match a built-in
33
+ layout contract: arbitrary structural counts such as seven calendar days,
34
+ asymmetric fractional tracks, or mixed intrinsic/flexible tracks. Once set, the
35
+ application owns narrow-container behavior.
36
+
37
+ `.container-query` is a low-level opt-in for a component that changes its own
38
+ representation according to allocated space. It does not enable responsive
39
+ behavior for layout primitives and never changes their meaning.