@fpkit/acss 3.1.1 → 3.2.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 (204) hide show
  1. package/libs/{chunk-2NRIP6RB.cjs → chunk-2C3YLBWP.cjs} +3 -3
  2. package/libs/{chunk-NWJDAHP6.cjs → chunk-2GJHKWEK.cjs} +3 -3
  3. package/libs/{chunk-FVROL3V5.js → chunk-2JCDEC32.js} +3 -3
  4. package/libs/{chunk-IRLFZ3OL.js → chunk-3XJC4XUG.js} +2 -2
  5. package/libs/{chunk-L6PRDL6F.cjs → chunk-5CJPTDK3.cjs} +3 -3
  6. package/libs/{chunk-E4OSROCA.cjs → chunk-5QSNJQVH.cjs} +3 -3
  7. package/libs/{chunk-O3JIHC5M.cjs → chunk-6BUJZ4DJ.cjs} +3 -3
  8. package/libs/{chunk-WXBFBWYF.cjs → chunk-AFINOD2L.cjs} +3 -3
  9. package/libs/{chunk-HRRHPLER.js → chunk-AWZLSWDO.js} +2 -2
  10. package/libs/chunk-DDSXKOUB.js +7 -0
  11. package/libs/chunk-DDSXKOUB.js.map +1 -0
  12. package/libs/{chunk-CWRNJA4P.js → chunk-DIJBIOFE.js} +3 -3
  13. package/libs/chunk-EJ6KYBFE.cjs +13 -0
  14. package/libs/chunk-EJ6KYBFE.cjs.map +1 -0
  15. package/libs/{chunk-GUJSMQ3V.cjs → chunk-EKJYOCLY.cjs} +3 -3
  16. package/libs/{chunk-X5RKCLDC.cjs → chunk-F64GE6RG.cjs} +4 -4
  17. package/libs/{chunk-5RAWNUVD.js → chunk-IBUTNPTQ.js} +2 -2
  18. package/libs/{chunk-ZFJ4U45S.js → chunk-KDMX3FAW.js} +2 -2
  19. package/libs/{chunk-DYFAUAB7.cjs → chunk-LXODKKA3.cjs} +4 -4
  20. package/libs/{chunk-MPTMPBFT.js → chunk-M7JLT62Q.js} +2 -2
  21. package/libs/{chunk-IQ76HGVP.js → chunk-MBWI67UT.js} +2 -2
  22. package/libs/{chunk-O5XAJ7BY.cjs → chunk-NCGVF2QS.cjs} +4 -4
  23. package/libs/{chunk-W2UIN7EV.cjs → chunk-NPWHQVYB.cjs} +3 -3
  24. package/libs/chunk-OU52NIKA.js +8 -0
  25. package/libs/chunk-OU52NIKA.js.map +1 -0
  26. package/libs/{chunk-43TK2ICH.js → chunk-PMWL5XZ4.js} +3 -3
  27. package/libs/{chunk-KVKQLRJG.js → chunk-TF3GQKOY.js} +2 -2
  28. package/libs/{chunk-IEB64SWY.js → chunk-U5VA34SU.js} +2 -2
  29. package/libs/{chunk-EE3ZWSBY.cjs → chunk-URBGDUFN.cjs} +6 -6
  30. package/libs/chunk-WWPLBWCQ.cjs +18 -0
  31. package/libs/chunk-WWPLBWCQ.cjs.map +1 -0
  32. package/libs/{chunk-TPIB3RQP.js → chunk-ZF6Y7W57.js} +5 -5
  33. package/libs/component-props-50e69975.d.ts +66 -0
  34. package/libs/components/box/box.css +1 -0
  35. package/libs/components/box/box.css.map +1 -0
  36. package/libs/components/box/box.min.css +3 -0
  37. package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
  38. package/libs/components/breadcrumbs/breadcrumb.js +3 -3
  39. package/libs/components/button.cjs +4 -4
  40. package/libs/components/button.d.cts +10 -3
  41. package/libs/components/button.d.ts +10 -3
  42. package/libs/components/button.js +2 -2
  43. package/libs/components/card.cjs +7 -7
  44. package/libs/components/card.d.cts +13 -85
  45. package/libs/components/card.d.ts +13 -85
  46. package/libs/components/card.js +2 -2
  47. package/libs/components/cards/card.css +1 -1
  48. package/libs/components/cards/card.css.map +1 -1
  49. package/libs/components/cards/card.min.css +2 -2
  50. package/libs/components/cluster/cluster.css +1 -0
  51. package/libs/components/cluster/cluster.css.map +1 -0
  52. package/libs/components/cluster/cluster.min.css +3 -0
  53. package/libs/components/dialog/dialog.cjs +7 -7
  54. package/libs/components/dialog/dialog.js +5 -5
  55. package/libs/components/form/fields.cjs +4 -4
  56. package/libs/components/form/fields.js +2 -2
  57. package/libs/components/form/textarea.cjs +4 -4
  58. package/libs/components/form/textarea.js +2 -2
  59. package/libs/components/grid/grid.css +1 -0
  60. package/libs/components/grid/grid.css.map +1 -0
  61. package/libs/components/grid/grid.min.css +3 -0
  62. package/libs/components/heading/heading.cjs +3 -3
  63. package/libs/components/heading/heading.js +2 -2
  64. package/libs/components/icons/icon.cjs +4 -4
  65. package/libs/components/icons/icon.d.cts +2 -2
  66. package/libs/components/icons/icon.d.ts +2 -2
  67. package/libs/components/icons/icon.js +2 -2
  68. package/libs/components/link/link.cjs +6 -6
  69. package/libs/components/link/link.js +2 -2
  70. package/libs/components/list/list.cjs +5 -5
  71. package/libs/components/list/list.js +2 -2
  72. package/libs/components/modal.cjs +4 -4
  73. package/libs/components/modal.d.cts +1 -1
  74. package/libs/components/modal.d.ts +1 -1
  75. package/libs/components/modal.js +3 -3
  76. package/libs/components/nav/nav.cjs +7 -7
  77. package/libs/components/nav/nav.js +3 -3
  78. package/libs/components/stack/stack.css +1 -0
  79. package/libs/components/stack/stack.css.map +1 -0
  80. package/libs/components/stack/stack.min.css +3 -0
  81. package/libs/components/tables/table.d.cts +1 -1
  82. package/libs/components/tables/table.d.ts +1 -1
  83. package/libs/components/text/text.cjs +5 -5
  84. package/libs/components/text/text.js +2 -2
  85. package/libs/hooks.cjs +4 -4
  86. package/libs/hooks.js +3 -3
  87. package/libs/{icons-287fce3a.d.ts → icons-df8e744f.d.ts} +1 -1
  88. package/libs/icons.cjs +3 -3
  89. package/libs/icons.d.cts +2 -2
  90. package/libs/icons.d.ts +2 -2
  91. package/libs/icons.js +2 -2
  92. package/libs/index.cjs +64 -63
  93. package/libs/index.cjs.map +1 -1
  94. package/libs/index.css +1 -1
  95. package/libs/index.css.map +1 -1
  96. package/libs/index.d.cts +923 -4
  97. package/libs/index.d.ts +923 -4
  98. package/libs/index.js +28 -28
  99. package/libs/index.js.map +1 -1
  100. package/package.json +2 -2
  101. package/src/components/alert/STYLES.mdx +790 -0
  102. package/src/components/badge/STYLES.mdx +610 -0
  103. package/src/components/box/README.mdx +401 -0
  104. package/src/components/box/STYLES.mdx +360 -0
  105. package/src/components/box/box.scss +245 -0
  106. package/src/components/box/box.stories.tsx +395 -0
  107. package/src/components/box/box.test.tsx +425 -0
  108. package/src/components/box/box.tsx +170 -0
  109. package/src/components/box/box.types.ts +166 -0
  110. package/src/components/breadcrumbs/STYLES.mdx +99 -0
  111. package/src/components/buttons/STYLES.mdx +766 -0
  112. package/src/components/cards/STYLES.mdx +835 -0
  113. package/src/components/cards/card.scss +30 -21
  114. package/src/components/cards/card.stories.tsx +120 -80
  115. package/src/components/cards/card.tsx +14 -4
  116. package/src/components/cards/card.types.ts +13 -0
  117. package/src/components/cluster/README.mdx +595 -0
  118. package/src/components/cluster/STYLES.mdx +626 -0
  119. package/src/components/cluster/cluster.scss +86 -0
  120. package/src/components/cluster/cluster.stories.tsx +385 -0
  121. package/src/components/cluster/cluster.test.tsx +655 -0
  122. package/src/components/cluster/cluster.tsx +94 -0
  123. package/src/components/cluster/cluster.types.ts +75 -0
  124. package/src/components/details/STYLES.mdx +445 -0
  125. package/src/components/dialog/STYLES.mdx +888 -0
  126. package/src/components/flexbox/STYLES.mdx +1 -1
  127. package/src/components/form/STYLES.mdx +821 -0
  128. package/src/components/grid/README.mdx +709 -0
  129. package/src/components/grid/STYLES.mdx +785 -0
  130. package/src/components/grid/grid.scss +287 -0
  131. package/src/components/grid/grid.stories.tsx +486 -0
  132. package/src/components/grid/grid.test.tsx +981 -0
  133. package/src/components/grid/grid.tsx +222 -0
  134. package/src/components/grid/grid.types.ts +344 -0
  135. package/src/components/icons/STYLES.mdx +56 -0
  136. package/src/components/images/STYLES.mdx +75 -0
  137. package/src/components/layout/STYLES.mdx +556 -0
  138. package/src/components/link/STYLES.mdx +75 -0
  139. package/src/components/list/STYLES.mdx +631 -0
  140. package/src/components/nav/STYLES.mdx +460 -0
  141. package/src/components/progress/STYLES.mdx +64 -0
  142. package/src/components/stack/README.mdx +400 -0
  143. package/src/components/stack/STYLES.mdx +414 -0
  144. package/src/components/stack/stack.scss +109 -0
  145. package/src/components/stack/stack.stories.tsx +559 -0
  146. package/src/components/stack/stack.test.tsx +426 -0
  147. package/src/components/stack/stack.tsx +141 -0
  148. package/src/components/stack/stack.types.ts +133 -0
  149. package/src/components/tag/STYLES.mdx +105 -0
  150. package/src/components/text-to-speech/STYLES.mdx +80 -0
  151. package/src/components/ui.tsx +3 -3
  152. package/src/index.scss +7 -2
  153. package/src/index.ts +305 -12
  154. package/src/sass/GLOBALS-STYLES.md +631 -0
  155. package/src/sass/_globals.scss +45 -24
  156. package/src/sass/_styles.scss +2 -2
  157. package/src/styles/box/box.css +220 -0
  158. package/src/styles/box/box.css.map +1 -0
  159. package/src/styles/cards/card.css +23 -17
  160. package/src/styles/cards/card.css.map +1 -1
  161. package/src/styles/cluster/cluster.css +71 -0
  162. package/src/styles/cluster/cluster.css.map +1 -0
  163. package/src/styles/grid/grid.css +238 -0
  164. package/src/styles/grid/grid.css.map +1 -0
  165. package/src/styles/index.css +668 -49
  166. package/src/styles/index.css.map +1 -1
  167. package/src/styles/stack/stack.css +86 -0
  168. package/src/styles/stack/stack.css.map +1 -0
  169. package/src/types/component-props.ts +42 -14
  170. package/src/types/layout-primitives.ts +48 -0
  171. package/src/types/shared.ts +10 -26
  172. package/libs/chunk-ENTCUJ3A.cjs +0 -13
  173. package/libs/chunk-ENTCUJ3A.cjs.map +0 -1
  174. package/libs/chunk-HHLNOC5T.js +0 -7
  175. package/libs/chunk-HHLNOC5T.js.map +0 -1
  176. package/libs/chunk-KK47SYZI.js +0 -8
  177. package/libs/chunk-KK47SYZI.js.map +0 -1
  178. package/libs/chunk-W5TKWBFC.cjs +0 -18
  179. package/libs/chunk-W5TKWBFC.cjs.map +0 -1
  180. package/libs/component-props-67d978a2.d.ts +0 -38
  181. /package/libs/{chunk-2NRIP6RB.cjs.map → chunk-2C3YLBWP.cjs.map} +0 -0
  182. /package/libs/{chunk-NWJDAHP6.cjs.map → chunk-2GJHKWEK.cjs.map} +0 -0
  183. /package/libs/{chunk-FVROL3V5.js.map → chunk-2JCDEC32.js.map} +0 -0
  184. /package/libs/{chunk-IRLFZ3OL.js.map → chunk-3XJC4XUG.js.map} +0 -0
  185. /package/libs/{chunk-L6PRDL6F.cjs.map → chunk-5CJPTDK3.cjs.map} +0 -0
  186. /package/libs/{chunk-E4OSROCA.cjs.map → chunk-5QSNJQVH.cjs.map} +0 -0
  187. /package/libs/{chunk-O3JIHC5M.cjs.map → chunk-6BUJZ4DJ.cjs.map} +0 -0
  188. /package/libs/{chunk-WXBFBWYF.cjs.map → chunk-AFINOD2L.cjs.map} +0 -0
  189. /package/libs/{chunk-HRRHPLER.js.map → chunk-AWZLSWDO.js.map} +0 -0
  190. /package/libs/{chunk-CWRNJA4P.js.map → chunk-DIJBIOFE.js.map} +0 -0
  191. /package/libs/{chunk-GUJSMQ3V.cjs.map → chunk-EKJYOCLY.cjs.map} +0 -0
  192. /package/libs/{chunk-X5RKCLDC.cjs.map → chunk-F64GE6RG.cjs.map} +0 -0
  193. /package/libs/{chunk-5RAWNUVD.js.map → chunk-IBUTNPTQ.js.map} +0 -0
  194. /package/libs/{chunk-ZFJ4U45S.js.map → chunk-KDMX3FAW.js.map} +0 -0
  195. /package/libs/{chunk-DYFAUAB7.cjs.map → chunk-LXODKKA3.cjs.map} +0 -0
  196. /package/libs/{chunk-MPTMPBFT.js.map → chunk-M7JLT62Q.js.map} +0 -0
  197. /package/libs/{chunk-IQ76HGVP.js.map → chunk-MBWI67UT.js.map} +0 -0
  198. /package/libs/{chunk-O5XAJ7BY.cjs.map → chunk-NCGVF2QS.cjs.map} +0 -0
  199. /package/libs/{chunk-W2UIN7EV.cjs.map → chunk-NPWHQVYB.cjs.map} +0 -0
  200. /package/libs/{chunk-43TK2ICH.js.map → chunk-PMWL5XZ4.js.map} +0 -0
  201. /package/libs/{chunk-KVKQLRJG.js.map → chunk-TF3GQKOY.js.map} +0 -0
  202. /package/libs/{chunk-IEB64SWY.js.map → chunk-U5VA34SU.js.map} +0 -0
  203. /package/libs/{chunk-EE3ZWSBY.cjs.map → chunk-URBGDUFN.cjs.map} +0 -0
  204. /package/libs/{chunk-TPIB3RQP.js.map → chunk-ZF6Y7W57.js.map} +0 -0
@@ -0,0 +1,626 @@
1
+ import { Meta } from '@storybook/addon-docs/blocks';
2
+ import * as ClusterStories from './cluster.stories';
3
+
4
+ <Meta of={ClusterStories} title="Styles/Cluster" />
5
+
6
+ # Cluster Component Styles
7
+
8
+ Complete CSS reference for the Cluster layout primitive component.
9
+
10
+ ## CSS Architecture
11
+
12
+ The Cluster component uses a **utility-class system** with CSS custom properties for theming. All spacing values use the unified spacing scale with fluid `clamp()` for responsive design.
13
+
14
+ **Key Characteristics:**
15
+ - **Zero Runtime:** All styling via CSS classes (no JavaScript)
16
+ - **Fluid Spacing:** CSS clamp() for responsive gaps without media queries
17
+ - **Rem Units:** All measurements in rem (1rem = 16px base)
18
+ - **CSS Variables:** Themable via CSS custom properties
19
+
20
+ ## Base Styles
21
+
22
+ ### `.cluster`
23
+
24
+ Base flexbox container with wrapping enabled.
25
+
26
+ ```css
27
+ .cluster {
28
+ display: flex;
29
+ flex-wrap: wrap;
30
+ gap: var(--spacing-sm); /* Default: clamp(0.5rem, 0.45rem + 0.35vw, 0.75rem) */
31
+ }
32
+ ```
33
+
34
+ **Default Behavior:**
35
+ - Displays items in a horizontal row
36
+ - Wraps items to next line when container width is exceeded
37
+ - Default gap: `--spacing-sm` (8-12px responsive)
38
+
39
+ ## Gap Utilities
40
+
41
+ Control spacing between items using the unified spacing scale.
42
+
43
+ ### `.cluster-gap-0`
44
+
45
+ Remove all gap spacing.
46
+
47
+ ```css
48
+ .cluster-gap-0 {
49
+ gap: 0;
50
+ }
51
+ ```
52
+
53
+ **Usage:** `<Cluster gap="0">`
54
+ **Value:** `0`
55
+
56
+ ### `.cluster-gap-xs`
57
+
58
+ Extra small gap spacing.
59
+
60
+ ```css
61
+ .cluster-gap-xs {
62
+ gap: var(--spacing-xs);
63
+ }
64
+ ```
65
+
66
+ **Usage:** `<Cluster gap="xs">`
67
+ **Value:** `clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem)` (4-8px)
68
+ **Use Case:** Tight spacing for badges or compact tags
69
+
70
+ ### `.cluster-gap-sm`
71
+
72
+ Small gap spacing.
73
+
74
+ ```css
75
+ .cluster-gap-sm {
76
+ gap: var(--spacing-sm);
77
+ }
78
+ ```
79
+
80
+ **Usage:** `<Cluster gap="sm">`
81
+ **Value:** `clamp(0.5rem, 0.45rem + 0.35vw, 0.75rem)` (8-12px)
82
+ **Use Case:** Default for tag clouds and keyword lists
83
+
84
+ ### `.cluster-gap-md`
85
+
86
+ Medium gap spacing.
87
+
88
+ ```css
89
+ .cluster-gap-md {
90
+ gap: var(--spacing-md);
91
+ }
92
+ ```
93
+
94
+ **Usage:** `<Cluster gap="md">`
95
+ **Value:** `clamp(0.75rem, 0.65rem + 0.45vw, 1.125rem)` (12-18px)
96
+ **Use Case:** Button groups and navigation links
97
+
98
+ ### `.cluster-gap-lg`
99
+
100
+ Large gap spacing.
101
+
102
+ ```css
103
+ .cluster-gap-lg {
104
+ gap: var(--spacing-lg);
105
+ }
106
+ ```
107
+
108
+ **Usage:** `<Cluster gap="lg">`
109
+ **Value:** `clamp(1rem, 0.85rem + 0.6vw, 1.5rem)` (16-24px)
110
+ **Use Case:** Spacious navigation or large buttons
111
+
112
+ ### `.cluster-gap-xl`
113
+
114
+ Extra large gap spacing.
115
+
116
+ ```css
117
+ .cluster-gap-xl {
118
+ gap: var(--spacing-xl);
119
+ }
120
+ ```
121
+
122
+ **Usage:** `<Cluster gap="xl">`
123
+ **Value:** `clamp(1.5rem, 1.25rem + 0.75vw, 2rem)` (24-32px)
124
+ **Use Case:** Very spacious layouts with large items
125
+
126
+ ## Justify Utilities
127
+
128
+ Control horizontal alignment of items (justify-content).
129
+
130
+ ### `.cluster-justify-start`
131
+
132
+ Align items to the start (left in LTR).
133
+
134
+ ```css
135
+ .cluster-justify-start {
136
+ justify-content: flex-start;
137
+ }
138
+ ```
139
+
140
+ **Usage:** `<Cluster justify="start">`
141
+ **Behavior:** Items aligned to left (or right in RTL)
142
+
143
+ ### `.cluster-justify-center`
144
+
145
+ Center items horizontally.
146
+
147
+ ```css
148
+ .cluster-justify-center {
149
+ justify-content: center;
150
+ }
151
+ ```
152
+
153
+ **Usage:** `<Cluster justify="center">`
154
+ **Behavior:** Items centered horizontally within container
155
+ **Use Case:** Centered tag clouds or navigation
156
+
157
+ ### `.cluster-justify-end`
158
+
159
+ Align items to the end (right in LTR).
160
+
161
+ ```css
162
+ .cluster-justify-end {
163
+ justify-content: flex-end;
164
+ }
165
+ ```
166
+
167
+ **Usage:** `<Cluster justify="end">`
168
+ **Behavior:** Items aligned to right (or left in RTL)
169
+ **Use Case:** Right-aligned action buttons
170
+
171
+ ### `.cluster-justify-between`
172
+
173
+ Distribute items with space between.
174
+
175
+ ```css
176
+ .cluster-justify-between {
177
+ justify-content: space-between;
178
+ }
179
+ ```
180
+
181
+ **Usage:** `<Cluster justify="between">`
182
+ **Behavior:** First item at start, last item at end, equal space between
183
+ **Use Case:** Distributed navigation links
184
+
185
+ ## Align Utilities
186
+
187
+ Control vertical alignment of items within each row (align-items).
188
+
189
+ ### `.cluster-align-start`
190
+
191
+ Align items to the top of the row.
192
+
193
+ ```css
194
+ .cluster-align-start {
195
+ align-items: flex-start;
196
+ }
197
+ ```
198
+
199
+ **Usage:** `<Cluster align="start">`
200
+ **Behavior:** Items aligned to top of the row
201
+ **Use Case:** Items with varying heights
202
+
203
+ ### `.cluster-align-center`
204
+
205
+ Center items vertically within the row.
206
+
207
+ ```css
208
+ .cluster-align-center {
209
+ align-items: center;
210
+ }
211
+ ```
212
+
213
+ **Usage:** `<Cluster align="center">`
214
+ **Behavior:** Items centered vertically within row
215
+ **Use Case:** Mixed content (icons + text)
216
+
217
+ ### `.cluster-align-end`
218
+
219
+ Align items to the bottom of the row.
220
+
221
+ ```css
222
+ .cluster-align-end {
223
+ align-items: flex-end;
224
+ }
225
+ ```
226
+
227
+ **Usage:** `<Cluster align="end">`
228
+ **Behavior:** Items aligned to bottom of the row
229
+
230
+ ### `.cluster-align-baseline`
231
+
232
+ Align items by their text baseline.
233
+
234
+ ```css
235
+ .cluster-align-baseline {
236
+ align-items: baseline;
237
+ }
238
+ ```
239
+
240
+ **Usage:** `<Cluster align="baseline">`
241
+ **Behavior:** Text baselines aligned across items
242
+ **Use Case:** Navigation links or text-based buttons
243
+
244
+ ## CSS Custom Properties
245
+
246
+ ### Global Spacing Scale
247
+
248
+ Defined in `_globals.scss`:
249
+
250
+ ```scss
251
+ :root {
252
+ --spacing-0: 0;
253
+ --spacing-xs: clamp(0.25rem, 0.2rem + 0.25vw, 0.5rem); /* 4-8px */
254
+ --spacing-sm: clamp(0.5rem, 0.45rem + 0.35vw, 0.75rem); /* 8-12px */
255
+ --spacing-md: clamp(0.75rem, 0.65rem + 0.45vw, 1.125rem); /* 12-18px */
256
+ --spacing-lg: clamp(1rem, 0.85rem + 0.6vw, 1.5rem); /* 16-24px */
257
+ --spacing-xl: clamp(1.5rem, 1.25rem + 0.75vw, 2rem); /* 24-32px */
258
+ }
259
+ ```
260
+
261
+ ### Theming
262
+
263
+ Override spacing scale globally:
264
+
265
+ ```css
266
+ :root {
267
+ /* Custom spacing for larger gaps */
268
+ --spacing-md: 1.5rem;
269
+ --spacing-lg: 2rem;
270
+ }
271
+ ```
272
+
273
+ Or per component:
274
+
275
+ ```tsx
276
+ <Cluster
277
+ gap="md"
278
+ styles={{
279
+ '--spacing-md': '2rem',
280
+ } as React.CSSProperties}
281
+ >
282
+ <Tag>React</Tag>
283
+ </Cluster>
284
+ ```
285
+
286
+ ## Responsive Behavior
287
+
288
+ ### Fluid Spacing
289
+
290
+ Gap values automatically adjust based on viewport width using CSS clamp():
291
+
292
+ ```
293
+ Viewport Width → Gap Size
294
+ 320px (mobile) → Minimum (e.g., 0.5rem for sm)
295
+ ~800px (tablet) → Middle value (interpolated)
296
+ 1280px+ (desktop) → Maximum (e.g., 0.75rem for sm)
297
+ ```
298
+
299
+ **No media queries needed!** The spacing scales smoothly between min and max values.
300
+
301
+ ### Wrapping Behavior
302
+
303
+ Items automatically wrap to the next line when:
304
+ - Container width is insufficient for all items
305
+ - Sum of item widths + gaps exceeds container width
306
+
307
+ **Example:**
308
+
309
+ ```
310
+ Container: 600px
311
+ Items: 8 buttons (120px each)
312
+ Gap: 1rem (16px)
313
+
314
+ Row 1: 4 buttons (120 × 4 = 480px) + (16 × 3 = 48px gaps) = 528px ✓
315
+ Row 2: 4 buttons (wraps to next line)
316
+ ```
317
+
318
+ ## Class Generation
319
+
320
+ The Cluster component generates classes based on props:
321
+
322
+ ```tsx
323
+ <Cluster gap="md" justify="center" align="baseline">
324
+ Content
325
+ </Cluster>
326
+ ```
327
+
328
+ **Generated classes:**
329
+ ```html
330
+ <div class="cluster cluster-gap-md cluster-justify-center cluster-align-baseline">
331
+ Content
332
+ </div>
333
+ ```
334
+
335
+ ## Combining with Custom Styles
336
+
337
+ ### Custom Classes
338
+
339
+ ```tsx
340
+ <Cluster className="custom-cluster" gap="sm">
341
+ <Tag>React</Tag>
342
+ </Cluster>
343
+
344
+ <style>
345
+ .custom-cluster {
346
+ max-width: 40rem; /* 640px */
347
+ margin-inline: auto;
348
+ padding: 1rem;
349
+ background: var(--bg-subtle, #f9f9f9);
350
+ border-radius: 0.5rem;
351
+ }
352
+ </style>
353
+ ```
354
+
355
+ ### Inline Styles
356
+
357
+ ```tsx
358
+ <Cluster
359
+ gap="md"
360
+ styles={{
361
+ maxWidth: '600px',
362
+ marginInline: 'auto',
363
+ padding: '1.5rem',
364
+ }}
365
+ >
366
+ <Button>Action 1</Button>
367
+ <Button>Action 2</Button>
368
+ </Cluster>
369
+ ```
370
+
371
+ ## SCSS Source
372
+
373
+ **File:** `src/components/cluster/cluster.scss`
374
+
375
+ ```scss
376
+ /**
377
+ * Cluster Component Styles
378
+ *
379
+ * Utility classes for the Cluster layout primitive.
380
+ * Provides wrapping flex layout for inline groups (tags, badges, buttons).
381
+ * All spacing values use the unified spacing scale from globals.
382
+ * All units are in rem (1rem = 16px base).
383
+ */
384
+
385
+ // ============================================================================
386
+ // Base Cluster
387
+ // ============================================================================
388
+
389
+ .cluster {
390
+ display: flex;
391
+ flex-wrap: wrap;
392
+ gap: var(--spacing-sm); // Default small gap for inline items
393
+ }
394
+
395
+ // ============================================================================
396
+ // Gap Utilities
397
+ // ============================================================================
398
+
399
+ .cluster-gap-0 {
400
+ gap: 0;
401
+ }
402
+
403
+ .cluster-gap-xs {
404
+ gap: var(--spacing-xs);
405
+ }
406
+
407
+ .cluster-gap-sm {
408
+ gap: var(--spacing-sm);
409
+ }
410
+
411
+ .cluster-gap-md {
412
+ gap: var(--spacing-md);
413
+ }
414
+
415
+ .cluster-gap-lg {
416
+ gap: var(--spacing-lg);
417
+ }
418
+
419
+ .cluster-gap-xl {
420
+ gap: var(--spacing-xl);
421
+ }
422
+
423
+ // ============================================================================
424
+ // Justify Utilities (Horizontal Alignment)
425
+ // ============================================================================
426
+
427
+ .cluster-justify-start {
428
+ justify-content: flex-start;
429
+ }
430
+
431
+ .cluster-justify-center {
432
+ justify-content: center;
433
+ }
434
+
435
+ .cluster-justify-end {
436
+ justify-content: flex-end;
437
+ }
438
+
439
+ .cluster-justify-between {
440
+ justify-content: space-between;
441
+ }
442
+
443
+ // ============================================================================
444
+ // Align Utilities (Vertical Alignment)
445
+ // ============================================================================
446
+
447
+ .cluster-align-start {
448
+ align-items: flex-start;
449
+ }
450
+
451
+ .cluster-align-center {
452
+ align-items: center;
453
+ }
454
+
455
+ .cluster-align-end {
456
+ align-items: flex-end;
457
+ }
458
+
459
+ .cluster-align-baseline {
460
+ align-items: baseline;
461
+ }
462
+ ```
463
+
464
+ ## Compiled CSS Output
465
+
466
+ **Location:** `libs/components/cluster/cluster.css`
467
+
468
+ The SCSS is compiled to compressed CSS:
469
+
470
+ ```css
471
+ .cluster{display:flex;flex-wrap:wrap;gap:var(--spacing-sm)}.cluster-gap-0{gap:0}.cluster-gap-xs{gap:var(--spacing-xs)}.cluster-gap-sm{gap:var(--spacing-sm)}.cluster-gap-md{gap:var(--spacing-md)}.cluster-gap-lg{gap:var(--spacing-lg)}.cluster-gap-xl{gap:var(--spacing-xl)}.cluster-justify-start{justify-content:flex-start}.cluster-justify-center{justify-content:center}.cluster-justify-end{justify-content:flex-end}.cluster-justify-between{justify-content:space-between}.cluster-align-start{align-items:flex-start}.cluster-align-center{align-items:center}.cluster-align-end{align-items:flex-end}.cluster-align-baseline{align-items:baseline}
472
+ ```
473
+
474
+ **Minified Size:** ~400 bytes (gzipped: ~200 bytes)
475
+
476
+ ## Performance
477
+
478
+ ### Bundle Size
479
+ - **SCSS Source:** 1.8 KB
480
+ - **Compiled CSS:** 0.4 KB
481
+ - **Gzipped:** 0.2 KB
482
+
483
+ ### Runtime Performance
484
+ - **Zero JavaScript:** All layout via CSS
485
+ - **No Re-renders:** Static utility classes
486
+ - **GPU Accelerated:** Flexbox handled by browser compositor
487
+
488
+ ### Loading Strategy
489
+ - **Critical CSS:** Include `.cluster` base class
490
+ - **Lazy Load:** Load gap/justify/align utilities on demand
491
+
492
+ ## Browser Support
493
+
494
+ | Feature | Chrome | Firefox | Safari | Edge |
495
+ |---------|--------|---------|--------|------|
496
+ | Flexbox | ✅ 29+ | ✅ 28+ | ✅ 9+ | ✅ 12+ |
497
+ | flex-wrap | ✅ 29+ | ✅ 28+ | ✅ 9+ | ✅ 12+ |
498
+ | gap (flexbox) | ✅ 84+ | ✅ 63+ | ✅ 14.1+ | ✅ 84+ |
499
+ | CSS clamp() | ✅ 79+ | ✅ 75+ | ✅ 13.1+ | ✅ 79+ |
500
+
501
+ **Fallback:** For browsers without flexbox gap support, use margin on child elements.
502
+
503
+ ## Accessibility
504
+
505
+ ### Semantic HTML
506
+
507
+ Use appropriate elements via the `as` prop:
508
+
509
+ ```tsx
510
+ <Cluster as="nav"> {/* <nav> for navigation */}
511
+ <Cluster as="ul"> {/* <ul> for lists */}
512
+ <Cluster as="section"> {/* <section> for grouped content */}
513
+ ```
514
+
515
+ ### Focus Order
516
+
517
+ Flexbox maintains DOM order for keyboard navigation:
518
+
519
+ ```tsx
520
+ <Cluster gap="md">
521
+ <button>First</button> {/* Tab order: 1 */}
522
+ <button>Second</button> {/* Tab order: 2 */}
523
+ <button>Third</button> {/* Tab order: 3 */}
524
+ </Cluster>
525
+ ```
526
+
527
+ Even when wrapped, focus order follows DOM structure.
528
+
529
+ ### Screen Readers
530
+
531
+ Provide ARIA labels for non-semantic containers:
532
+
533
+ ```tsx
534
+ <Cluster aria-label="Technology tags">
535
+ <Tag>React</Tag>
536
+ <Tag>TypeScript</Tag>
537
+ </Cluster>
538
+ ```
539
+
540
+ ## Migration from Legacy Styles
541
+
542
+ ### From Inline Flex
543
+
544
+ **Before:**
545
+ ```css
546
+ .tag-cloud {
547
+ display: inline-flex;
548
+ flex-wrap: wrap;
549
+ gap: 8px;
550
+ }
551
+ ```
552
+
553
+ **After:**
554
+ ```tsx
555
+ <Cluster gap="sm" className="tag-cloud">
556
+ <Tag>React</Tag>
557
+ </Cluster>
558
+ ```
559
+
560
+ ### From Float Layouts
561
+
562
+ **Before:**
563
+ ```css
564
+ .tags {
565
+ overflow: auto; /* Clearfix */
566
+ }
567
+
568
+ .tags > * {
569
+ float: left;
570
+ margin-right: 8px;
571
+ margin-bottom: 8px;
572
+ }
573
+ ```
574
+
575
+ **After:**
576
+ ```tsx
577
+ <Cluster gap="sm">
578
+ <Tag>React</Tag>
579
+ </Cluster>
580
+ ```
581
+
582
+ ### From Grid with Auto-Fill
583
+
584
+ **Before:**
585
+ ```css
586
+ .grid {
587
+ display: grid;
588
+ grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
589
+ gap: 1rem;
590
+ }
591
+ ```
592
+
593
+ **After (if items have varying widths):**
594
+ ```tsx
595
+ <Cluster gap="md">
596
+ <Button>Short</Button>
597
+ <Button>Medium Length</Button>
598
+ <Button>Very Long Button Text</Button>
599
+ </Cluster>
600
+ ```
601
+
602
+ ## Related Documentation
603
+
604
+ - **README.mdx** - Component usage and patterns
605
+ - **cluster.stories.tsx** - Interactive examples
606
+ - **cluster.test.tsx** - Unit tests and behavior
607
+ - **_globals.scss** - Global spacing scale definitions
608
+
609
+ ## Version History
610
+
611
+ - **v0.5.11** - Initial release of Cluster component
612
+ - Unified spacing scale
613
+ - Gap, justify, and align utilities
614
+ - Polymorphic `as` prop
615
+ - TypeScript types and comprehensive tests
616
+
617
+ ## Resources
618
+
619
+ - **Flexbox Guide:** [MDN Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout)
620
+ - **CSS clamp():** [MDN clamp()](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp)
621
+ - **Spacing Scale:** See `_globals.scss` for complete scale
622
+ - **Component Composition:** See README.mdx for patterns
623
+
624
+ ## License
625
+
626
+ MIT
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Cluster Component Styles
3
+ *
4
+ * Utility classes for the Cluster layout primitive.
5
+ * Provides wrapping flex layout for inline groups (tags, badges, buttons).
6
+ * All spacing values use the unified spacing scale from globals.
7
+ * All units are in rem (1rem = 16px base).
8
+ */
9
+
10
+ // ============================================================================
11
+ // Base Cluster
12
+ // ============================================================================
13
+
14
+ .cluster {
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ gap: var(--spacing-sm); // Default small gap for inline items
18
+ }
19
+
20
+ // ============================================================================
21
+ // Gap Utilities
22
+ // ============================================================================
23
+
24
+ .cluster-gap-0 {
25
+ gap: 0;
26
+ }
27
+
28
+ .cluster-gap-xs {
29
+ gap: var(--spacing-xs);
30
+ }
31
+
32
+ .cluster-gap-sm {
33
+ gap: var(--spacing-sm);
34
+ }
35
+
36
+ .cluster-gap-md {
37
+ gap: var(--spacing-md);
38
+ }
39
+
40
+ .cluster-gap-lg {
41
+ gap: var(--spacing-lg);
42
+ }
43
+
44
+ .cluster-gap-xl {
45
+ gap: var(--spacing-xl);
46
+ }
47
+
48
+ // ============================================================================
49
+ // Justify Utilities (Horizontal Alignment)
50
+ // ============================================================================
51
+
52
+ .cluster-justify-start {
53
+ justify-content: flex-start;
54
+ }
55
+
56
+ .cluster-justify-center {
57
+ justify-content: center;
58
+ }
59
+
60
+ .cluster-justify-end {
61
+ justify-content: flex-end;
62
+ }
63
+
64
+ .cluster-justify-between {
65
+ justify-content: space-between;
66
+ }
67
+
68
+ // ============================================================================
69
+ // Align Utilities (Vertical Alignment)
70
+ // ============================================================================
71
+
72
+ .cluster-align-start {
73
+ align-items: flex-start;
74
+ }
75
+
76
+ .cluster-align-center {
77
+ align-items: center;
78
+ }
79
+
80
+ .cluster-align-end {
81
+ align-items: flex-end;
82
+ }
83
+
84
+ .cluster-align-baseline {
85
+ align-items: baseline;
86
+ }