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,206 @@
1
+ # Column Layout
2
+
3
+ `.column-layout` is an explicit twelve-column composition canvas. Place regions
4
+ with `.column-span-N` and `.column-start-N`.
5
+
6
+ Reach for it when the placement of each region **is** the design. If the regions
7
+ are a collection, a known density, peers that switch together, or a main region
8
+ with an aside, one of the other primitives already says so — and says it with
9
+ intrinsic responsive behavior this one does not have.
10
+
11
+ ```html demo
12
+ <div class="column-layout">
13
+ <main class="column-span-8 card">Main — 8 columns</main>
14
+ <aside class="column-span-4 card">Aside — 4 columns</aside>
15
+ </div>
16
+ ```
17
+
18
+ Neither child names a start line, so grid auto-placement flows the aside into
19
+ columns 9 through 12.
20
+
21
+ ## Spans
22
+
23
+ A span declares how many of the twelve units a region occupies.
24
+
25
+ ```html demo
26
+ <div class="column-layout">
27
+ <div class="column-span-3 card">3</div>
28
+ <div class="column-span-6 card">6</div>
29
+ <div class="column-span-3 card">3</div>
30
+ </div>
31
+ ```
32
+
33
+ A child with no placement class spans the whole canvas, so a heading can share
34
+ the canvas with placed regions without carrying a class.
35
+
36
+ ```html demo
37
+ <div class="column-layout">
38
+ <h3>Full canvas — no class needed</h3>
39
+ <div class="column-span-4 card">4</div>
40
+ <div class="column-span-4 card">4</div>
41
+ <div class="column-span-4 card">4</div>
42
+ </div>
43
+ ```
44
+
45
+ Regions that do not fit wrap to the next row, as any grid does. Two
46
+ `.column-span-8` regions need sixteen units, so the second moves down.
47
+
48
+ ## Starts
49
+
50
+ A start declares the line a region begins on. This replaces margin-based
51
+ offsets and is direction-independent: line 1 is the inline start, so the
52
+ placement flips with `dir="rtl"` on its own.
53
+
54
+ ```html demo
55
+ <div class="column-layout">
56
+ <article class="column-span-10 column-start-2 card">
57
+ Columns 2 through 11
58
+ </article>
59
+ </div>
60
+ ```
61
+
62
+ Used without a span, a start runs to the end of the canvas.
63
+
64
+ ```html demo
65
+ <div class="column-layout">
66
+ <aside class="column-start-9 card">Columns 9 through 12</aside>
67
+ </div>
68
+ ```
69
+
70
+ Keep a combined placement inside the canvas: `S + N - 1 <= 12`. So
71
+ `.column-start-9 .column-span-4` is valid and `.column-start-10 .column-span-4`
72
+ is not. Exceeding the canvas adds a thirteenth, content-sized column, and every
73
+ other region shrinks with it — the failure is canvas-wide, not local to the
74
+ region you got wrong.
75
+
76
+ ## Cross-section alignment
77
+
78
+ The canvas is shared across sibling sections, so regions in different sections
79
+ can line up on the same columns — something a collection or a sidebar cannot
80
+ guarantee. This is the case no other primitive can replace.
81
+
82
+ ```html demo
83
+ <div class="stack">
84
+ <div class="column-layout">
85
+ <h3 class="column-span-8 column-start-3">Feature title</h3>
86
+ <p class="muted column-span-8 column-start-3">Kicker aligned to the same line.</p>
87
+ </div>
88
+
89
+ <div class="column-layout">
90
+ <p class="column-span-8 column-start-3">
91
+ Body copy starts on the same column as the title above and spans the same
92
+ eight columns.
93
+ </p>
94
+ <aside class="column-span-2 column-start-11 card">Inline note</aside>
95
+ </div>
96
+ </div>
97
+ ```
98
+
99
+ Both sections name the same `column-start-3` / `column-span-8`, so their content
100
+ shares a left edge and an alignment gutter without a wrapping grid.
101
+
102
+ ## The responsive contract
103
+
104
+ `.column-layout` has **no automatic collapse**. The canvas stays twelve columns
105
+ at every width, and the application owns narrow-container behavior.
106
+
107
+ This is deliberate. `8 + 4` and `3 + 9` do not become unusable at the same
108
+ width, a centered article may only need wider gutters, and a dashboard may want
109
+ three regions to become two before stacking. A single framework threshold would
110
+ be wrong more often than right, and a hidden one would have to be undone rather
111
+ than extended.
112
+
113
+ The simplest recomposition stacks everything:
114
+
115
+ ```css
116
+ @container (width < 40rem) {
117
+ .profile-layout > * {
118
+ grid-column: 1 / -1;
119
+ }
120
+ }
121
+ ```
122
+
123
+ A coordinate system is more useful when you keep it through an intermediate
124
+ state:
125
+
126
+ ```css
127
+ @container (width < 48rem) {
128
+ .profile-main {
129
+ grid-column: 1 / span 6;
130
+ }
131
+
132
+ .profile-aside {
133
+ grid-column: 7 / span 6;
134
+ }
135
+ }
136
+
137
+ @container (width < 32rem) {
138
+ .profile-main,
139
+ .profile-aside {
140
+ grid-column: 1 / -1;
141
+ }
142
+ }
143
+ ```
144
+
145
+ ```html
146
+ <div class="container-query">
147
+ <div class="column-layout profile-layout">
148
+ <main class="column-span-8 profile-main">...</main>
149
+ <aside class="column-span-4 column-start-9 profile-aside">...</aside>
150
+ </div>
151
+ </div>
152
+ ```
153
+
154
+ The `.container-query` wrapper here enables **your** `@container` rules, not a
155
+ hidden framework behavior. Remove your rules and the wrapper stops mattering.
156
+ This is the opposite of a primitive whose responsive contract depends on a
157
+ wrapper someone else has to remember.
158
+
159
+ Placement classes carry zero specificity, so a single-class rule of your own
160
+ wins without `!important` and without having to undo a framework declaration
161
+ first.
162
+
163
+ ## Narrow containers
164
+
165
+ Twelve columns is a wide-context tool. With the default `--gap`, a 279px
166
+ container spends 132px on its eleven gaps and leaves about 12px per unit — a
167
+ `.column-span-4` region is 84px wide.
168
+
169
+ The framework guarantees the canvas itself never overflows its container: the
170
+ tracks are `minmax(0, 1fr)` and every child gets `min-inline-size: 0`, so item
171
+ boxes stay inside their tracks. It does not guarantee that content inside a
172
+ narrow span stays readable, or that an unbreakable word will not paint outside
173
+ its track. Define a narrow representation where the composition needs one.
174
+
175
+ ## Scope
176
+
177
+ The primitive is horizontal only. There are no `.row-span-*`, `.area-*`, or
178
+ `.order-*` classes, and no breakpoint variants such as `md-column-span-6` —
179
+ those would move responsive strategy back into markup. For genuinely
180
+ two-dimensional placement, use CSS Grid directly on your own class:
181
+
182
+ ```css
183
+ .dashboard-summary {
184
+ grid-row: 1 / span 2;
185
+ }
186
+ ```
187
+
188
+ The column count is fixed at twelve and is not configurable. Twelve is what
189
+ makes the vocabulary shared and lets `6 + 6`, `4 + 4 + 4`, `3 + 3 + 3 + 3`,
190
+ `8 + 4`, and `2 + 8 + 2` all land on the same canvas. For a track system whose
191
+ sizes carry meaning rather than twelve interchangeable units, use
192
+ `--grid-columns` on `.grid`.
193
+
194
+ Unlike `.grid-N`, the track template does not read `--gap`, so the gap
195
+ utilities are exact here at every width.
196
+
197
+ A region carrying a placement class must generate a box. `display: contents`
198
+ removes that box and promotes its descendants to grid items, which leaves the
199
+ placement with nothing to apply to.
200
+
201
+ ### Classes
202
+
203
+ - `.column-layout` establishes the twelve-column canvas.
204
+ - `.column-span-1` … `.column-span-12` set the width in canvas units.
205
+ - `.column-start-1` … `.column-start-12` set the starting line, running to the
206
+ canvas end unless a span refines it.
@@ -27,4 +27,9 @@ Use local variables for common ratios.
27
27
  .avatar-preview {
28
28
  --frame-ratio: 1;
29
29
  }
30
- ```
30
+ ```
31
+
32
+ `overflow: hidden` is what makes the frame a media frame: it clips the media to
33
+ the ratio and its corners. Floating decorations (badges, live dots, captions
34
+ that overhang) therefore cannot live inside the frame — they are clipped too.
35
+ Place them in a sibling or wrapper around the frame instead.
@@ -1,25 +1,26 @@
1
1
  # Grid
2
2
 
3
- Responsive equal-width item grids with a tunable minimum item width.
3
+ Two contracts sit behind these classes. Pick by asking what determines the
4
+ column count.
5
+
6
+ - The **item width** is what matters — use `.grid` and tune `--grid-min`.
7
+ - The **column density** is what matters — use `.grid-2`, `.grid-3`, `.grid-4`,
8
+ or `.grid-6`.
9
+
10
+ ## Space-driven collection
11
+
12
+ `.grid` fits as many columns as the available inline space permits. Incomplete
13
+ final rows are part of the contract.
4
14
 
5
15
  ```html demo
6
16
  <section class="grid">
7
- <article class="card">
8
- <h3>Starter</h3>
9
- <p>For small projects.</p>
10
- </article>
11
- <article class="card">
12
- <h3>Team</h3>
13
- <p>For shared products.</p>
14
- </article>
15
- <article class="card">
16
- <h3>Scale</h3>
17
- <p>For larger systems.</p>
18
- </article>
17
+ <article class="card"><h3>Starter</h3><p>For small projects.</p></article>
18
+ <article class="card"><h3>Team</h3><p>For shared products.</p></article>
19
+ <article class="card"><h3>Scale</h3><p>For larger systems.</p></article>
19
20
  </section>
20
21
  ```
21
22
 
22
- Tune the minimum item width with `--grid-min`.
23
+ Tune the item minimum with `--grid-min`.
23
24
 
24
25
  ```css
25
26
  .pricing-grid {
@@ -27,116 +28,113 @@ Tune the minimum item width with `--grid-min`.
27
28
  }
28
29
  ```
29
30
 
30
- Or replace the responsive template entirely with `--grid-columns` for a
31
- custom or asymmetric layout. Because this overrides the intrinsic
32
- `auto-fit/minmax` algorithm, you own any narrow-container collapse:
31
+ ## Count-driven density
33
32
 
34
- ```css
35
- .feature-grid {
36
- --grid-columns: minmax(0, 2fr) minmax(0, 1fr);
37
- }
33
+ `.grid-N` declares a structural density of N columns. It is responsive on its
34
+ own: it never exceeds N columns, never overflows, and every item keeps the same
35
+ width.
38
36
 
39
- @container (width < 40rem) {
40
- .feature-grid {
41
- --grid-columns: 1fr;
42
- }
43
- }
37
+ ```html demo
38
+ <div class="grid-4">
39
+ <div class="card">Exercitation</div>
40
+ <div class="card">Amet mollit</div>
41
+ <div class="card">Aute cillum</div>
42
+ <div class="card">Duis non </div>
43
+ </div>
44
44
  ```
45
45
 
46
- `--grid-columns` applies to `.grid` only. The `.grid-2`, `.grid-3`,
47
- `.grid-4`, and `.grid-6` presets retain their fixed-column contracts.
46
+ `--grid-min` does not apply here. Item width is `.grid`'s contract; column
47
+ density is `.grid-N`'s. Choose the preset that suits your item size:
48
48
 
49
- ## Fixed columns
49
+ | Item | Preset |
50
+ |-----------------------------------|----------------------|
51
+ | large card | `.grid-2` |
52
+ | card with a heading and a summary | `.grid-3`, `.grid-4` |
53
+ | compact tile, stat, avatar | `.grid-6` |
50
54
 
51
- Predictable 2/3/4/6-column grids. Full count by default; wrap in `.container-query` to make the column count collapse on narrow wrappers.
55
+ ## Balanced subdivision
52
56
 
53
- Use `.grid-2`, `.grid-3`, `.grid-4`, and `.grid-6` when the column count matters more than the item minimum width — for example, when a row should always read as "three items side by side", or when an empty cell should not stretch to fill space. Unlike `.grid`, the columns are fixed; if you have only two items in a `.grid-3`, the third cell stays empty rather than redistributing.
57
+ Left alone, a preset collapses one column at a time, so a six-item `.grid-6`
58
+ can pass through five columns — five items and a lone sixth. Wrap it in
59
+ `.container-query` and it only ever enters a **divisor of N**:
54
60
 
55
- A `.grid-2/3/4/6` without a wrapper is a **fixed grid** (always at its full column count); with a `.container-query` wrapper, it's a **responsive grid** (the column count collapses on narrow wrappers). The wrapper is the query container; the grid itself is a plain block grid.
61
+ ```text
62
+ .grid-2 2 → 1
63
+ .grid-3 3 → 1
64
+ .grid-4 4 → 2 → 1
65
+ .grid-6 6 → 3 → 2 → 1
66
+ ```
67
+
68
+ Every state splits the collection evenly, and all items keep the same width.
56
69
 
57
70
  ```html demo
58
71
  <div class="container-query">
59
- <div class="grid-3">
60
- <article class="card">
61
- <h3>Starter</h3>
62
- <p>For small projects.</p>
63
- </article>
64
- <article class="card">
65
- <h3>Team</h3>
66
- <p>For shared products.</p>
67
- </article>
68
- <article class="card">
69
- <h3>Scale</h3>
70
- <p>For larger systems.</p>
71
- </article>
72
+ <div class="grid-6">
73
+ <div class="card">1</div>
74
+ <div class="card">2</div>
75
+ <div class="card">3</div>
76
+ <div class="card">4</div>
77
+ <div class="card">5</div>
78
+ <div class="card">6</div>
72
79
  </div>
73
80
  </div>
74
81
  ```
75
82
 
76
- A `grid-4` demo:
83
+ The wrapper is an opt-in for precision, never a prerequisite for responsive
84
+ behavior — forgetting it costs you the exact chain, nothing else. It has to be
85
+ an ancestor: an element cannot query its own size without taking inline-size
86
+ containment, which would collapse the grid inside a `.cluster`, a float, or any
87
+ shrink-to-fit box. Put `.container-query` on a normal block-level wrapper for
88
+ the same reason.
77
89
 
78
- ```html demo
90
+ The chain balances the **declared density**, not your actual item count. Eight
91
+ items in `.grid-6` still give `6 + 2`. For a paginated collection, choose a page
92
+ size that suits the density — 12, 20, and 24 divide well. A partial final page
93
+ is normal.
94
+
95
+ ## Exact templates
96
+
97
+ `--grid-columns` replaces `.grid`'s intrinsic recipe. Use it for exact track
98
+ templates that do not match a built-in layout contract: arbitrary structural
99
+ counts such as seven calendar days, asymmetric fractional tracks, or mixed
100
+ intrinsic/flexible tracks. Once set, the application owns narrow-container
101
+ behavior.
102
+
103
+ ```css
104
+ /* Semantic count not represented by .grid-N */
105
+ --grid-columns: repeat(7, minmax(0, 1fr));
106
+
107
+ /* Meaningful asymmetric ratio */
108
+ --grid-columns: 2fr 1fr 1fr 1fr;
109
+
110
+ /* Intrinsic trailing control */
111
+ --grid-columns: repeat(4, minmax(0, 1fr)) auto;
112
+ ```
113
+
114
+ ```html
79
115
  <div class="container-query">
80
- <div class="grid-4">
81
- <article class="card">
82
- <h3>Starter</h3>
83
- <p>For small projects.</p>
84
- </article>
85
- <article class="card">
86
- <h3>Team</h3>
87
- <p>For shared products.</p>
88
- </article>
89
- <article class="card">
90
- <h3>Scale</h3>
91
- <p>For larger systems.</p>
92
- </article>
93
- <article class="card">
94
- <h3>Enterprise</h3>
95
- <p>Contact us.</p>
96
- </article>
97
- </div>
116
+ <div class="editorial-grid grid">...</div>
98
117
  </div>
99
118
  ```
100
119
 
101
- A `grid-6` demo for compact items:
120
+ ```css
121
+ .editorial-grid {
122
+ --grid-columns: minmax(0, 2fr) minmax(0, 1fr);
123
+ }
102
124
 
103
- ```html demo
104
- <div class="container-query">
105
- <div class="grid-6">
106
- <article class="card compact">
107
- <span class="muted">Open</span>
108
- <strong>18</strong>
109
- </article>
110
- <article class="card compact">
111
- <span class="muted">Queued</span>
112
- <strong>7</strong>
113
- </article>
114
- <article class="card compact">
115
- <span class="muted">Blocked</span>
116
- <strong>2</strong>
117
- </article>
118
- <article class="card compact">
119
- <span class="muted">Shipped</span>
120
- <strong>41</strong>
121
- </article>
122
- <article class="card compact">
123
- <span class="muted">Owners</span>
124
- <strong>6</strong>
125
- </article>
126
- <article class="card compact">
127
- <span class="muted">SLA</span>
128
- <strong>99%</strong>
129
- </article>
130
- </div>
131
- </div>
125
+ @container (width < 40rem) {
126
+ .editorial-grid {
127
+ --grid-columns: 1fr;
128
+ }
129
+ }
132
130
  ```
133
131
 
134
- ## Behavior
132
+ For an ordinary main region plus an aside, prefer `.sidebar-layout`. When a
133
+ small group of peer regions must be either entirely horizontal or entirely
134
+ stacked, prefer `.switcher`.
135
135
 
136
- - Without `.container-query`: `.grid-2` is always 2 cols, `.grid-3` is always 3 cols, `.grid-4` is always 4 cols, and `.grid-6` is always 6 cols.
137
- - With `.container-query`: `.grid-2`, `.grid-3`, and `.grid-4` collapse to one column on a narrow wrapper (under 28rem). `.grid-3` and `.grid-4` step through 2 columns between 28rem and 48rem. `.grid-6` starts at 2 columns under 28rem, steps through 3 columns between 28rem and 64rem, then returns to 6 columns.
138
- - The intermediate 2-col step is useful for lists of items divisible by both 2 and 3 (or 4) — a 12-item list reads as 12 lines, then 6 lines of 2, then 4 lines of 3 (or 3 lines of 4), depending on the grid.
139
- - `.grid-6` is for compact items such as stats, shortcut tiles, swatches, avatar summaries, and small settings cards. It does not collapse to one column by default. If item width matters more than an exact six-column rhythm, prefer `.grid` with a smaller `--grid-min`.
140
- - The wrapper is the query container, so the same class behaves differently in a narrow sidebar than in a wide main area. No viewport breakpoints are involved.
136
+ ### Hooks
141
137
 
142
- Do not add `.row`, `.col-6`, `.offset-2`, or other fixed grid-system classes unless the project later proves it needs a formal grid system.
138
+ - `--grid-min` tunes the minimum item width of the intrinsic `.grid` recipe.
139
+ It does not apply to `.grid-N`.
140
+ - `--grid-columns` replaces that recipe with an author-owned template.
@@ -38,4 +38,4 @@ Use `.list-reset` only when markers are not part of the content. Combine `.stack
38
38
  </figure>
39
39
  ```
40
40
 
41
- Keep semantic lists unstyled when the markers carry meaning.
41
+ Keep semantic lists unstyled when the markers carry meaning.
@@ -25,4 +25,4 @@ Add `.items-center` to align the leading element with short trailing content. Fo
25
25
  </div>
26
26
  ```
27
27
 
28
- The media object is the underlying pattern of `.blog-author`, `.blog-comment`, and similar compositions in templates. Components can adopt it instead of repeating the grid rule.
28
+ The media object is the underlying pattern of `.blog-author`, `.blog-comment`, and similar compositions in templates. Components can adopt it instead of repeating the grid rule.
@@ -1,6 +1,6 @@
1
1
  # Layout Overview
2
2
 
3
- Layout provides a small set of composable building blocks for common page, app, and content structure. It is not a utility-first framework and it is not a twelve-column grid system.
3
+ Layout provides a small set of composable building blocks for common page, app, and content structure. It is not a utility-first framework, and the twelve-column canvas it does ship (`.column-layout`) is an opt-in vocabulary for deliberate composition rather than the default way to build a page.
4
4
 
5
5
  - Layout classes compose components; components do not own page spacing.
6
6
  - Use custom properties to tune a layout instance.
@@ -8,6 +8,19 @@ Layout provides a small set of composable building blocks for common page, app,
8
8
  - Keep class names semantic enough to remember and generic enough to reuse.
9
9
  - Add a new layout primitive only when a pattern appears often and is awkward to express with existing primitives.
10
10
 
11
+ See [Choosing a layout](./choosing.md) for the distinctions between responsive
12
+ collections, fixed structural grids, all-or-nothing peer regions, sidebars, and
13
+ explicit column placement.
14
+
15
+ ## Child contract
16
+
17
+ Layout primitives operate on the boxes generated by their direct children.
18
+ Applying `display: contents` to a participating child removes that box and
19
+ promotes its descendants into the parent layout, bypassing the sizing or
20
+ placement assigned to the child. The layout contracts below are expressed
21
+ against direct children — keep those children as real boxes unless you intend
22
+ that bypass.
23
+
11
24
  ## Spacing tokens
12
25
 
13
26
  Layout shares the global spacing surface and exposes a small set of gap and rhythm tokens.
@@ -34,4 +47,4 @@ Most layout primitives read `--gap` and allow local overrides.
34
47
 
35
48
  Prefer a local custom property over adding many one-off utility classes. Use inline styles only for demos, prototypes, or truly dynamic values.
36
49
 
37
- There are no `.gap-sm` / `.gap-md` / `.gap-lg` density variants on the core layout primitives; set `--gap` locally when only spacing should change. The optional `utilities-extra.css` layer ships those gap utilities for row/column containers.
50
+ There are no `.gap-sm` / `.gap-md` / `.gap-lg` density variants on the core layout primitives; set `--gap` locally when only spacing should change. The extra utilities (`src/css/utilities/extra.css`) ship those gap utilities for row/column containers.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Horizontal rails that stay useful without JavaScript and snap in modern browsers.
4
4
 
5
- > **Optional** — import `actual-css/css/optional/scroll-snap` or `actual-css/css/optional/index`.
5
+ > **Module** — import `actual-css/css/layout/scroll-snap` or `actual-css/css/layout`.
6
6
 
7
7
  Use `.scroll-snap` for a niche row of items that should scroll horizontally, such as card rails, media strips, overflow tabs, or a simple touch-friendly carousel baseline. Scrolling only appears when the items are wider than the container; set `--scroll-snap-item-size` for card rails.
8
8
 
@@ -51,4 +51,4 @@ Keep scrollbars visible by default. If a product deliberately hides them, make t
51
51
  </div>
52
52
  ```
53
53
 
54
- `.scroll-snap` is not a full interactive carousel. For previous/next controls, pagination, active state, mouse drag, looping, autoplay, or robust accessibility behavior, use a dedicated carousel library such as Swiper and compose it with Actual components.
54
+ `.scroll-snap` is not a full interactive carousel. For previous/next controls, pagination, active state, mouse drag, looping, autoplay, or robust accessibility behavior, use a dedicated carousel library such as Swiper and compose it with Actual components.
@@ -0,0 +1,45 @@
1
+ # Scroll Target
2
+
3
+ Anchor scroll offset: keep `#hash` and `scrollIntoView()` targets clear of sticky headers.
4
+
5
+ > **Module** — import `actual-css/css/layout/scroll-target` or `actual-css/css/layout`.
6
+
7
+ A hash link or scripted scroll places the target flush at the scroll container's start edge. Under a sticky header such as `.topbar`, the heading you jumped to lands underneath it. Add `.scroll-target` to the elements that are link targets — sections, headings — and the browser stops early, reserving space above them.
8
+
9
+ ```html demo
10
+ <nav class="cluster" aria-label="Sections" style="margin-block-end: var(--space-30)">
11
+ <a class="btn neutral sm" href="#st-alpha">Alpha</a>
12
+ <a class="btn neutral sm" href="#st-beta">Beta</a>
13
+ <a class="btn neutral sm" href="#st-gamma">Gamma</a>
14
+ </nav>
15
+ <div class="overflow-auto" style="block-size: 10rem; border: var(--border-width) solid var(--border); border-radius: var(--radius)">
16
+ <section id="st-alpha" class="scroll-target" style="padding: var(--space-30)">
17
+ <h3>Alpha</h3>
18
+ <p>The first section. Followed by enough content to make the container scroll.</p>
19
+ </section>
20
+ <section id="st-beta" class="scroll-target" style="padding: var(--space-30)">
21
+ <h3>Beta</h3>
22
+ <p>The second section. Its top edge stops below the container edge.</p>
23
+ </section>
24
+ <section id="st-gamma" class="scroll-target" style="padding: var(--space-30)">
25
+ <h3>Gamma</h3>
26
+ <p>The last section.</p>
27
+ </section>
28
+ </div>
29
+ ```
30
+
31
+ The offset is a plain `scroll-margin-block-start`, so it works in every scroll container — the viewport, a sidebar, an overflow region — and composes with the scrollspy enhancer. Scrollspy only decides which link is active; this offset decides where the page actually lands when the link is followed.
32
+
33
+ ## CSS hooks
34
+
35
+ - `--scroll-target-offset` — space kept above the target after scrolling. Set it
36
+ once on `:root` (or on the sticky header's height) in applications with a
37
+ fixed header:
38
+
39
+ ```css
40
+ :root {
41
+ --scroll-target-offset: 5rem;
42
+ }
43
+ ```
44
+
45
+ Deliberately no `[id]` global rule: making the offset explicit per target keeps plain ids (modals, form fields, skip links) untouched.
@@ -1,27 +1,28 @@
1
1
  # Sidebar Layout
2
2
 
3
- Two-column layout where one side has a preferred width and the other takes the remaining space.
4
-
5
- Use `.sidebar-layout` for two-column layouts where the aside should align to the top of the content, stay sticky, or keep a predictable declared width.
6
-
7
- Wrap it in `.container-query` to make the switch depend on the container width. Below 64rem the columns stack; at and above it the aside takes `--sidebar-layout-size` and the content takes the remaining space. Older browsers use the viewport fallback.
3
+ Use `.sidebar-layout` for a main region followed by a secondary region. It
4
+ switches intrinsically according to its own available width: the regions sit
5
+ side by side when the main minimum, preferred aside width, and gap fit; they
6
+ otherwise stack. No `.container-query` ancestor is required.
8
7
 
9
8
  ```html demo
10
- <div class="container-query">
11
- <div class="sidebar-layout" style="--sidebar-layout-size: 18rem">
12
- <article class="stack">
13
- <h1>Long-form article</h1>
14
- <p>Article body that benefits from a sticky table of contents.</p>
15
- </article>
9
+ <div class="sidebar-layout">
10
+ <article class="stack">
11
+ <h1>Long-form article</h1>
12
+ <p>Article body that benefits from a related table of contents.</p>
13
+ </article>
16
14
 
17
- <aside class="stack">
18
- <h3>On this page</h3>
19
- <ol class="list-reset">
20
- <li><a class="link-muted" href="#">Section</a></li>
21
- </ol>
22
- </aside>
23
- </div>
15
+ <aside class="stack">
16
+ <h3>On this page</h3>
17
+ <ol class="list-reset"><li><a class="link-muted" href="#">Section</a></li></ol>
18
+ </aside>
24
19
  </div>
25
20
  ```
26
21
 
27
- Tune the side width with `--sidebar-layout-size`.
22
+ The first child is the flexible main region and the last child is the aside.
23
+ Use a custom `.grid` template only when an exact editorial ratio is structural.
24
+
25
+ ### Hooks
26
+
27
+ - `--sidebar-layout-size` sets the aside's preferred width.
28
+ - `--sidebar-content-min` sets the main region's minimum viable width.