@fpkit/acss 3.0.0 → 3.1.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.
- package/libs/chunk-5RAWNUVD.js +8 -0
- package/libs/chunk-5RAWNUVD.js.map +1 -0
- package/libs/{chunk-D2PSO7MU.js → chunk-CWRNJA4P.js} +2 -2
- package/libs/{chunk-C622WBGW.cjs → chunk-DYFAUAB7.cjs} +3 -3
- package/libs/chunk-NWJDAHP6.cjs +17 -0
- package/libs/chunk-NWJDAHP6.cjs.map +1 -0
- package/libs/components/breadcrumbs/breadcrumb.cjs +5 -5
- package/libs/components/breadcrumbs/breadcrumb.js +2 -2
- package/libs/components/flexbox/flex.css +1 -0
- package/libs/components/flexbox/flex.css.map +1 -0
- package/libs/components/flexbox/flex.min.css +3 -0
- package/libs/components/link/link.cjs +5 -5
- package/libs/components/link/link.css +1 -1
- package/libs/components/link/link.css.map +1 -1
- package/libs/components/link/link.js +1 -1
- package/libs/components/link/link.min.css +2 -2
- package/libs/hooks.cjs +3 -3
- package/libs/hooks.js +2 -2
- package/libs/index.cjs +29 -28
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +243 -52
- package/libs/index.d.ts +243 -52
- package/libs/index.js +14 -14
- package/libs/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/flexbox/README.mdx +996 -0
- package/src/components/flexbox/flex.scss +847 -0
- package/src/components/flexbox/flex.stories.tsx +1233 -0
- package/src/components/flexbox/flex.test.tsx +689 -0
- package/src/components/flexbox/flex.tsx +484 -0
- package/src/components/flexbox/flex.types.ts +224 -0
- package/src/components/link/link.tsx +1 -1
- package/src/index.scss +1 -0
- package/src/index.ts +17 -0
- package/src/styles/flexbox/flex.css +736 -0
- package/src/styles/flexbox/flex.css.map +1 -0
- package/src/styles/index.css +735 -1
- package/src/styles/index.css.map +1 -1
- package/src/styles/link/link.css +1 -1
- package/libs/chunk-KG4GHIQJ.js +0 -8
- package/libs/chunk-KG4GHIQJ.js.map +0 -1
- package/libs/chunk-ZOBAJTNE.cjs +0 -17
- package/libs/chunk-ZOBAJTNE.cjs.map +0 -1
- package/libs/components/alert/alert.min.min.css +0 -2
- package/libs/components/badge/badge.min.min.css +0 -2
- package/libs/components/breadcrumbs/breadcrumb.min.min.css +0 -2
- package/libs/components/buttons/button.min.min.css +0 -2
- package/libs/components/cards/card-style.min.min.css +0 -2
- package/libs/components/cards/card.min.min.css +0 -2
- package/libs/components/details/details.min.min.css +0 -2
- package/libs/components/dialog/dialog.min.min.css +0 -2
- package/libs/components/form/form.min.min.css +0 -2
- package/libs/components/icons/icon.min.min.css +0 -2
- package/libs/components/images/img.min.min.css +0 -2
- package/libs/components/layout/landmarks.min.min.css +0 -2
- package/libs/components/link/link.min.min.css +0 -2
- package/libs/components/list/list.min.min.css +0 -2
- package/libs/components/nav/nav.min.min.css +0 -2
- package/libs/components/progress/progress.min.min.css +0 -2
- package/libs/components/styles/index.min.min.css +0 -2
- package/libs/components/tag/tag.min.min.css +0 -2
- package/libs/components/text-to-speech/text-to-speech.min.min.css +0 -2
- /package/libs/{chunk-D2PSO7MU.js.map → chunk-CWRNJA4P.js.map} +0 -0
- /package/libs/{chunk-C622WBGW.cjs.map → chunk-DYFAUAB7.cjs.map} +0 -0
|
@@ -0,0 +1,996 @@
|
|
|
1
|
+
import { Meta } from "@storybook/addon-docs/blocks";
|
|
2
|
+
|
|
3
|
+
<Meta title="FP.REACT Components/Layout/Flex/Readme" />
|
|
4
|
+
|
|
5
|
+
# Flex Component
|
|
6
|
+
|
|
7
|
+
A powerful, type-safe flexbox layout component with compound pattern, responsive
|
|
8
|
+
props, and semantic element restrictions. Built for modern React applications
|
|
9
|
+
with accessibility-first design and full TypeScript support.
|
|
10
|
+
|
|
11
|
+
## Summary
|
|
12
|
+
|
|
13
|
+
The `Flex` component provides a declarative React API for flexbox layouts,
|
|
14
|
+
converting props to utility classes for optimal performance. Features responsive
|
|
15
|
+
breakpoint props, preset layout variants, and enforced semantic HTML structure.
|
|
16
|
+
|
|
17
|
+
**Latest Version:** v3.0.0+ (Enhanced with type-safe semantic elements)
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- 🧩 **Compound component pattern** - Flex.Item and Flex.Spacer sub-components
|
|
22
|
+
- 📱 **Responsive props** - Different layouts at sm/md/lg/xl breakpoints
|
|
23
|
+
- 🎯 **Preset variants** - Common patterns like 'center', 'between', 'stack'
|
|
24
|
+
- 🔒 **Type-safe semantic elements** - Restricts `as` prop to valid container
|
|
25
|
+
elements
|
|
26
|
+
- ⚡ **Performance optimized** - Generates utility classes, not inline styles
|
|
27
|
+
- 🎨 **CSS custom properties** - Full theming via CSS variables
|
|
28
|
+
- 📦 **TypeScript support** - Comprehensive type definitions with autocomplete
|
|
29
|
+
- ♿ **Accessibility-first** - Semantic HTML by default
|
|
30
|
+
- 🧪 **100% test coverage** - 62 comprehensive tests
|
|
31
|
+
|
|
32
|
+
## Accessibility
|
|
33
|
+
|
|
34
|
+
This component has been designed for WCAG 2.1 AA compliance:
|
|
35
|
+
|
|
36
|
+
- ✅ Uses semantic HTML container elements (section, article, nav, etc.)
|
|
37
|
+
- ✅ Type system enforces proper element usage (no inline/interactive elements)
|
|
38
|
+
- ✅ Forwards all ARIA attributes to rendered elements
|
|
39
|
+
- ✅ No interactive behavior by default (purely layout)
|
|
40
|
+
- ✅ Supports semantic list structures (ul/ol with li elements)
|
|
41
|
+
- ✅ Maintains logical tab order based on DOM structure
|
|
42
|
+
- ✅ Flexbox respects text spacing and zoom requirements
|
|
43
|
+
|
|
44
|
+
### Semantic Element Restrictions
|
|
45
|
+
|
|
46
|
+
The `as` prop is restricted to semantic container elements to ensure proper HTML
|
|
47
|
+
structure:
|
|
48
|
+
|
|
49
|
+
**✅ Allowed Elements:**
|
|
50
|
+
|
|
51
|
+
- **Block containers**: `div` (default), `section`, `article`, `aside`, `main`,
|
|
52
|
+
`header`, `footer`
|
|
53
|
+
- **List containers**: `ul`, `ol`, `dl`, `nav`
|
|
54
|
+
- **Form containers**: `form`, `fieldset`
|
|
55
|
+
- **List items** (Flex.Item only): `li`, `dt`, `dd`
|
|
56
|
+
|
|
57
|
+
**❌ Not Allowed:**
|
|
58
|
+
|
|
59
|
+
- Inline elements: `span`, `a`, `strong`, `em`
|
|
60
|
+
- Interactive elements: `button`, `input`, `select`
|
|
61
|
+
- Void elements: `img`, `hr`, `br`
|
|
62
|
+
|
|
63
|
+
This restriction prevents common accessibility mistakes and ensures semantic
|
|
64
|
+
HTML structure.
|
|
65
|
+
|
|
66
|
+
## Props
|
|
67
|
+
|
|
68
|
+
### Flex (Main Component)
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
interface FlexProps extends ResponsiveFlexProps {
|
|
72
|
+
/** Preset layout variant */
|
|
73
|
+
variant?: "center" | "between" | "around" | "stack" | "spread";
|
|
74
|
+
|
|
75
|
+
/** Use inline-flex instead of flex */
|
|
76
|
+
inline?: boolean;
|
|
77
|
+
|
|
78
|
+
/** Element type to render as (restricted to container elements) */
|
|
79
|
+
as?: FlexContainerElement;
|
|
80
|
+
|
|
81
|
+
/** Additional CSS class names */
|
|
82
|
+
className?: string;
|
|
83
|
+
|
|
84
|
+
/** Inline styles and CSS custom properties */
|
|
85
|
+
styles?: React.CSSProperties;
|
|
86
|
+
|
|
87
|
+
/** Children elements */
|
|
88
|
+
children?: React.ReactNode;
|
|
89
|
+
|
|
90
|
+
/** Responsive props for small screens (≥30rem / 480px) */
|
|
91
|
+
sm?: ResponsiveFlexProps;
|
|
92
|
+
|
|
93
|
+
/** Responsive props for medium screens (≥48rem / 768px) */
|
|
94
|
+
md?: ResponsiveFlexProps;
|
|
95
|
+
|
|
96
|
+
/** Responsive props for large screens (≥62rem / 992px) */
|
|
97
|
+
lg?: ResponsiveFlexProps;
|
|
98
|
+
|
|
99
|
+
/** Responsive props for extra large screens (≥80rem / 1280px) */
|
|
100
|
+
xl?: ResponsiveFlexProps;
|
|
101
|
+
|
|
102
|
+
/** Flex direction */
|
|
103
|
+
direction?: "row" | "row-reverse" | "column" | "column-reverse";
|
|
104
|
+
|
|
105
|
+
/** Flex wrap behavior */
|
|
106
|
+
wrap?: "wrap" | "nowrap" | "wrap-reverse";
|
|
107
|
+
|
|
108
|
+
/** Gap between flex items */
|
|
109
|
+
gap?: "0" | "xs" | "sm" | "md" | "lg" | "xl";
|
|
110
|
+
|
|
111
|
+
/** Row gap (vertical spacing) */
|
|
112
|
+
rowGap?: "0" | "xs" | "sm" | "md" | "lg" | "xl";
|
|
113
|
+
|
|
114
|
+
/** Column gap (horizontal spacing) */
|
|
115
|
+
colGap?: "0" | "xs" | "sm" | "md" | "lg" | "xl";
|
|
116
|
+
|
|
117
|
+
/** Justify content (main axis alignment) */
|
|
118
|
+
justify?: "start" | "end" | "center" | "between" | "around" | "evenly";
|
|
119
|
+
|
|
120
|
+
/** Align items (cross axis alignment) */
|
|
121
|
+
align?: "start" | "end" | "center" | "baseline" | "stretch";
|
|
122
|
+
|
|
123
|
+
/** Align content (multi-line alignment) */
|
|
124
|
+
alignContent?:
|
|
125
|
+
| "start"
|
|
126
|
+
| "end"
|
|
127
|
+
| "center"
|
|
128
|
+
| "between"
|
|
129
|
+
| "around"
|
|
130
|
+
| "evenly"
|
|
131
|
+
| "stretch";
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Flex.Item
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
interface FlexItemProps {
|
|
139
|
+
/** Element type to render as (includes list items) */
|
|
140
|
+
as?: FlexItemElement;
|
|
141
|
+
|
|
142
|
+
/** Flex grow factor */
|
|
143
|
+
grow?: 0 | 1;
|
|
144
|
+
|
|
145
|
+
/** Flex shrink factor */
|
|
146
|
+
shrink?: 0 | 1;
|
|
147
|
+
|
|
148
|
+
/** Flex basis */
|
|
149
|
+
basis?: "auto" | "0" | "full";
|
|
150
|
+
|
|
151
|
+
/** Flex shorthand */
|
|
152
|
+
flex?: "1" | "auto" | "initial" | "none";
|
|
153
|
+
|
|
154
|
+
/** Align self (overrides parent align-items) */
|
|
155
|
+
alignSelf?: "auto" | "start" | "end" | "center" | "baseline" | "stretch";
|
|
156
|
+
|
|
157
|
+
/** Order of the flex item */
|
|
158
|
+
order?: "first" | "last" | "none";
|
|
159
|
+
|
|
160
|
+
/** Additional CSS class names */
|
|
161
|
+
className?: string;
|
|
162
|
+
|
|
163
|
+
/** Inline styles and CSS custom properties */
|
|
164
|
+
styles?: React.CSSProperties;
|
|
165
|
+
|
|
166
|
+
/** Children elements */
|
|
167
|
+
children?: React.ReactNode;
|
|
168
|
+
|
|
169
|
+
/** Responsive props for different breakpoints */
|
|
170
|
+
sm?: { flex?: "1" | "auto" | "none" };
|
|
171
|
+
md?: { flex?: "1" | "auto" | "none" };
|
|
172
|
+
lg?: { flex?: "1" | "auto" | "none" };
|
|
173
|
+
xl?: { flex?: "1" | "auto" | "none" };
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Flex.Spacer
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
interface FlexSpacerProps {
|
|
181
|
+
/** Element type to render as (container elements only) */
|
|
182
|
+
as?: FlexContainerElement;
|
|
183
|
+
|
|
184
|
+
/** Additional CSS class names */
|
|
185
|
+
className?: string;
|
|
186
|
+
|
|
187
|
+
/** Inline styles and CSS custom properties */
|
|
188
|
+
styles?: React.CSSProperties;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Default Values
|
|
193
|
+
|
|
194
|
+
| Prop | Default | Description |
|
|
195
|
+
| ----------- | ------- | ----------------------------------------- |
|
|
196
|
+
| `as` | `"div"` | Container element type |
|
|
197
|
+
| `inline` | `false` | Display mode (flex vs inline-flex) |
|
|
198
|
+
| `direction` | - | No default (uses CSS default: row) |
|
|
199
|
+
| `wrap` | - | No default (uses CSS default: nowrap) |
|
|
200
|
+
| `gap` | - | No gap by default |
|
|
201
|
+
| `justify` | - | No default (uses CSS default: flex-start) |
|
|
202
|
+
| `align` | - | No default (uses CSS default: stretch) |
|
|
203
|
+
|
|
204
|
+
## Usage Examples
|
|
205
|
+
|
|
206
|
+
### Basic Flex Container
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { Flex } from "@fpkit/acss";
|
|
210
|
+
|
|
211
|
+
function BasicLayout() {
|
|
212
|
+
return (
|
|
213
|
+
<Flex direction="row" gap="md" justify="between" align="center">
|
|
214
|
+
<div>Item 1</div>
|
|
215
|
+
<div>Item 2</div>
|
|
216
|
+
<div>Item 3</div>
|
|
217
|
+
</Flex>
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Responsive Layout
|
|
223
|
+
|
|
224
|
+
Column on mobile, row on medium+ screens:
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { Flex } from "@fpkit/acss";
|
|
228
|
+
|
|
229
|
+
function ResponsiveLayout() {
|
|
230
|
+
return (
|
|
231
|
+
<Flex direction="column" gap="sm" md={{ direction: "row", gap: "lg" }}>
|
|
232
|
+
<Flex.Item flex="none" md={{ flex: "1" }}>
|
|
233
|
+
<h2>Sidebar</h2>
|
|
234
|
+
<p>Navigation content</p>
|
|
235
|
+
</Flex.Item>
|
|
236
|
+
|
|
237
|
+
<Flex.Item flex="none" md={{ flex: "1" }}>
|
|
238
|
+
<h2>Main Content</h2>
|
|
239
|
+
<p>Primary content area</p>
|
|
240
|
+
</Flex.Item>
|
|
241
|
+
</Flex>
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Using Preset Variants
|
|
247
|
+
|
|
248
|
+
Quick layouts with common patterns:
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { Flex } from "@fpkit/acss";
|
|
252
|
+
|
|
253
|
+
function PresetVariants() {
|
|
254
|
+
return (
|
|
255
|
+
<>
|
|
256
|
+
{/* Center everything */}
|
|
257
|
+
<Flex variant="center">
|
|
258
|
+
<div>Centered content</div>
|
|
259
|
+
</Flex>
|
|
260
|
+
|
|
261
|
+
{/* Space between items */}
|
|
262
|
+
<Flex variant="between">
|
|
263
|
+
<div>Left</div>
|
|
264
|
+
<div>Right</div>
|
|
265
|
+
</Flex>
|
|
266
|
+
|
|
267
|
+
{/* Vertical stack */}
|
|
268
|
+
<Flex variant="stack" gap="md">
|
|
269
|
+
<div>Item 1</div>
|
|
270
|
+
<div>Item 2</div>
|
|
271
|
+
</Flex>
|
|
272
|
+
</>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Flex.Spacer for Pushing Items Apart
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
import { Flex } from "@fpkit/acss";
|
|
281
|
+
|
|
282
|
+
function Header() {
|
|
283
|
+
return (
|
|
284
|
+
<Flex as="header" align="center" gap="md">
|
|
285
|
+
<div>Logo</div>
|
|
286
|
+
<nav>
|
|
287
|
+
<a href="/">Home</a>
|
|
288
|
+
<a href="/about">About</a>
|
|
289
|
+
</nav>
|
|
290
|
+
<Flex.Spacer />
|
|
291
|
+
<button>Sign In</button>
|
|
292
|
+
<button>Sign Up</button>
|
|
293
|
+
</Flex>
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Semantic Navigation with Flex
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
import { Flex } from "@fpkit/acss";
|
|
302
|
+
|
|
303
|
+
function Navigation() {
|
|
304
|
+
return (
|
|
305
|
+
<Flex as="nav" role="navigation" aria-label="Main navigation" gap="md">
|
|
306
|
+
<a href="/">Home</a>
|
|
307
|
+
<a href="/products">Products</a>
|
|
308
|
+
<a href="/about">About</a>
|
|
309
|
+
<a href="/contact">Contact</a>
|
|
310
|
+
</Flex>
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Semantic List Structure
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
import { Flex } from "@fpkit/acss";
|
|
319
|
+
|
|
320
|
+
function ProductList({ products }) {
|
|
321
|
+
return (
|
|
322
|
+
<Flex as="ul" direction="column" gap="md">
|
|
323
|
+
{products.map((product) => (
|
|
324
|
+
<Flex.Item as="li" key={product.id}>
|
|
325
|
+
<h3>{product.name}</h3>
|
|
326
|
+
<p>{product.description}</p>
|
|
327
|
+
<span>${product.price}</span>
|
|
328
|
+
</Flex.Item>
|
|
329
|
+
))}
|
|
330
|
+
</Flex>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Complex Responsive Grid
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
import { Flex } from "@fpkit/acss";
|
|
339
|
+
|
|
340
|
+
function ProductGrid({ products }) {
|
|
341
|
+
return (
|
|
342
|
+
<Flex
|
|
343
|
+
direction="column"
|
|
344
|
+
gap="sm"
|
|
345
|
+
sm={{ direction: "row", wrap: "wrap", gap: "md" }}
|
|
346
|
+
>
|
|
347
|
+
{products.map((product) => (
|
|
348
|
+
<Flex.Item
|
|
349
|
+
key={product.id}
|
|
350
|
+
flex="none"
|
|
351
|
+
sm={{ flex: "1" }}
|
|
352
|
+
styles={{ minWidth: "300px" }}
|
|
353
|
+
>
|
|
354
|
+
<article>
|
|
355
|
+
<img src={product.image} alt={product.name} />
|
|
356
|
+
<h3>{product.name}</h3>
|
|
357
|
+
<p>{product.description}</p>
|
|
358
|
+
<button>Add to Cart</button>
|
|
359
|
+
</article>
|
|
360
|
+
</Flex.Item>
|
|
361
|
+
))}
|
|
362
|
+
</Flex>
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Form Layout with Flexbox
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
import { Flex } from "@fpkit/acss";
|
|
371
|
+
|
|
372
|
+
function LoginForm() {
|
|
373
|
+
return (
|
|
374
|
+
<Flex as="form" direction="column" gap="md">
|
|
375
|
+
<Flex direction="column" gap="xs">
|
|
376
|
+
<label htmlFor="email">Email</label>
|
|
377
|
+
<input id="email" type="email" />
|
|
378
|
+
</Flex>
|
|
379
|
+
|
|
380
|
+
<Flex direction="column" gap="xs">
|
|
381
|
+
<label htmlFor="password">Password</label>
|
|
382
|
+
<input id="password" type="password" />
|
|
383
|
+
</Flex>
|
|
384
|
+
|
|
385
|
+
<Flex gap="md" justify="between" align="center">
|
|
386
|
+
<label>
|
|
387
|
+
<input type="checkbox" /> Remember me
|
|
388
|
+
</label>
|
|
389
|
+
<button type="submit">Sign In</button>
|
|
390
|
+
</Flex>
|
|
391
|
+
</Flex>
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Flex.Item with Alignment
|
|
397
|
+
|
|
398
|
+
```tsx
|
|
399
|
+
import { Flex } from "@fpkit/acss";
|
|
400
|
+
|
|
401
|
+
function AlignmentExample() {
|
|
402
|
+
return (
|
|
403
|
+
<Flex direction="row" gap="md" styles={{ minHeight: "200px" }}>
|
|
404
|
+
<Flex.Item alignSelf="start">
|
|
405
|
+
<div>Aligned to start</div>
|
|
406
|
+
</Flex.Item>
|
|
407
|
+
|
|
408
|
+
<Flex.Item alignSelf="center">
|
|
409
|
+
<div>Centered vertically</div>
|
|
410
|
+
</Flex.Item>
|
|
411
|
+
|
|
412
|
+
<Flex.Item alignSelf="end">
|
|
413
|
+
<div>Aligned to end</div>
|
|
414
|
+
</Flex.Item>
|
|
415
|
+
|
|
416
|
+
<Flex.Item alignSelf="stretch">
|
|
417
|
+
<div>Stretched to full height</div>
|
|
418
|
+
</Flex.Item>
|
|
419
|
+
</Flex>
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Visual Order Control
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { Flex } from "@fpkit/acss";
|
|
428
|
+
|
|
429
|
+
function OrderExample() {
|
|
430
|
+
return (
|
|
431
|
+
<Flex direction="row" gap="md">
|
|
432
|
+
<Flex.Item order="last">
|
|
433
|
+
<div>Renders first in HTML, displays last visually</div>
|
|
434
|
+
</Flex.Item>
|
|
435
|
+
|
|
436
|
+
<Flex.Item>
|
|
437
|
+
<div>Normal order (middle)</div>
|
|
438
|
+
</Flex.Item>
|
|
439
|
+
|
|
440
|
+
<Flex.Item order="first">
|
|
441
|
+
<div>Renders last in HTML, displays first visually</div>
|
|
442
|
+
</Flex.Item>
|
|
443
|
+
</Flex>
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Dashboard Layout
|
|
449
|
+
|
|
450
|
+
```tsx
|
|
451
|
+
import { Flex } from "@fpkit/acss";
|
|
452
|
+
|
|
453
|
+
function Dashboard() {
|
|
454
|
+
return (
|
|
455
|
+
<Flex direction="column" gap="lg" styles={{ minHeight: "100vh" }}>
|
|
456
|
+
{/* Header */}
|
|
457
|
+
<Flex as="header" justify="between" align="center" gap="md">
|
|
458
|
+
<h1>Dashboard</h1>
|
|
459
|
+
<nav>
|
|
460
|
+
<Flex gap="md">
|
|
461
|
+
<a href="/profile">Profile</a>
|
|
462
|
+
<a href="/settings">Settings</a>
|
|
463
|
+
<button>Logout</button>
|
|
464
|
+
</Flex>
|
|
465
|
+
</nav>
|
|
466
|
+
</Flex>
|
|
467
|
+
|
|
468
|
+
{/* Main content area */}
|
|
469
|
+
<Flex as="main" flex="1" gap="lg">
|
|
470
|
+
{/* Sidebar */}
|
|
471
|
+
<Flex
|
|
472
|
+
as="aside"
|
|
473
|
+
direction="column"
|
|
474
|
+
gap="md"
|
|
475
|
+
styles={{ width: "250px" }}
|
|
476
|
+
>
|
|
477
|
+
<nav>
|
|
478
|
+
<Flex direction="column" gap="sm">
|
|
479
|
+
<a href="/dashboard">Overview</a>
|
|
480
|
+
<a href="/analytics">Analytics</a>
|
|
481
|
+
<a href="/reports">Reports</a>
|
|
482
|
+
</Flex>
|
|
483
|
+
</nav>
|
|
484
|
+
</Flex>
|
|
485
|
+
|
|
486
|
+
{/* Content */}
|
|
487
|
+
<Flex as="section" direction="column" gap="md" flex="1">
|
|
488
|
+
<h2>Overview</h2>
|
|
489
|
+
<Flex wrap="wrap" gap="md">
|
|
490
|
+
<Flex.Item flex="1" styles={{ minWidth: "300px" }}>
|
|
491
|
+
<article>Metric 1</article>
|
|
492
|
+
</Flex.Item>
|
|
493
|
+
<Flex.Item flex="1" styles={{ minWidth: "300px" }}>
|
|
494
|
+
<article>Metric 2</article>
|
|
495
|
+
</Flex.Item>
|
|
496
|
+
<Flex.Item flex="1" styles={{ minWidth: "300px" }}>
|
|
497
|
+
<article>Metric 3</article>
|
|
498
|
+
</Flex.Item>
|
|
499
|
+
</Flex>
|
|
500
|
+
</Flex>
|
|
501
|
+
</Flex>
|
|
502
|
+
|
|
503
|
+
{/* Footer */}
|
|
504
|
+
<Flex as="footer" justify="center" gap="md">
|
|
505
|
+
<a href="/privacy">Privacy</a>
|
|
506
|
+
<a href="/terms">Terms</a>
|
|
507
|
+
<a href="/contact">Contact</a>
|
|
508
|
+
</Flex>
|
|
509
|
+
</Flex>
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Styling
|
|
515
|
+
|
|
516
|
+
The Flex component uses CSS utility classes and custom properties for styling.
|
|
517
|
+
|
|
518
|
+
### CSS Utility Classes Generated
|
|
519
|
+
|
|
520
|
+
The component automatically generates utility class names from props:
|
|
521
|
+
|
|
522
|
+
```tsx
|
|
523
|
+
// These props:
|
|
524
|
+
<Flex direction="row" gap="md" justify="between" align="center">
|
|
525
|
+
|
|
526
|
+
// Generate these classes:
|
|
527
|
+
// "flex flex-row gap-md justify-between items-center"
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Responsive Classes
|
|
531
|
+
|
|
532
|
+
Responsive props generate breakpoint-prefixed classes:
|
|
533
|
+
|
|
534
|
+
```tsx
|
|
535
|
+
// These props:
|
|
536
|
+
<Flex
|
|
537
|
+
direction="column"
|
|
538
|
+
md={{ direction: "row", gap: "lg" }}
|
|
539
|
+
>
|
|
540
|
+
|
|
541
|
+
// Generate these classes:
|
|
542
|
+
// "flex flex-col md:flex-row md:gap-lg"
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### CSS Custom Properties
|
|
546
|
+
|
|
547
|
+
Override default spacing via CSS variables:
|
|
548
|
+
|
|
549
|
+
```css
|
|
550
|
+
:root {
|
|
551
|
+
/* Gap sizes (in rem) */
|
|
552
|
+
--flex-gap-0: 0;
|
|
553
|
+
--flex-gap-xs: 0.25rem;
|
|
554
|
+
--flex-gap-sm: 0.5rem;
|
|
555
|
+
--flex-gap-md: 1rem;
|
|
556
|
+
--flex-gap-lg: 1.5rem;
|
|
557
|
+
--flex-gap-xl: 2rem;
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
### Custom Styling Examples
|
|
562
|
+
|
|
563
|
+
**Inline Styles:**
|
|
564
|
+
|
|
565
|
+
```tsx
|
|
566
|
+
<Flex styles={{ backgroundColor: "#f5f5f5", padding: "2rem" }}>
|
|
567
|
+
<div>Custom styled flex</div>
|
|
568
|
+
</Flex>
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
**CSS Classes:**
|
|
572
|
+
|
|
573
|
+
```tsx
|
|
574
|
+
<Flex className="custom-layout shadow-lg">
|
|
575
|
+
<div>With custom classes</div>
|
|
576
|
+
</Flex>
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
**CSS Variables:**
|
|
580
|
+
|
|
581
|
+
```tsx
|
|
582
|
+
<Flex
|
|
583
|
+
gap="md"
|
|
584
|
+
styles={
|
|
585
|
+
{
|
|
586
|
+
"--flex-gap-md": "2rem",
|
|
587
|
+
} as React.CSSProperties
|
|
588
|
+
}
|
|
589
|
+
>
|
|
590
|
+
<div>Custom gap size</div>
|
|
591
|
+
</Flex>
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
## Breakpoints
|
|
595
|
+
|
|
596
|
+
The component supports four responsive breakpoints:
|
|
597
|
+
|
|
598
|
+
| Breakpoint | Minimum Width | Example Usage |
|
|
599
|
+
| ---------- | -------------- | ----------------------------- |
|
|
600
|
+
| `sm` | 30rem (480px) | `sm={{ direction: "row" }}` |
|
|
601
|
+
| `md` | 48rem (768px) | `md={{ gap: "lg" }}` |
|
|
602
|
+
| `lg` | 62rem (992px) | `lg={{ wrap: "wrap" }}` |
|
|
603
|
+
| `xl` | 80rem (1280px) | `xl={{ justify: "between" }}` |
|
|
604
|
+
|
|
605
|
+
### Responsive Design Patterns
|
|
606
|
+
|
|
607
|
+
**Mobile-First Approach:**
|
|
608
|
+
|
|
609
|
+
```tsx
|
|
610
|
+
<Flex
|
|
611
|
+
direction="column" // Default: column on mobile
|
|
612
|
+
sm={{ direction: "row" }} // Row on small+
|
|
613
|
+
lg={{ gap: "xl" }} // Larger gap on large+
|
|
614
|
+
>
|
|
615
|
+
{/* Content */}
|
|
616
|
+
</Flex>
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
**Desktop-First Approach:**
|
|
620
|
+
|
|
621
|
+
```tsx
|
|
622
|
+
<Flex
|
|
623
|
+
direction="row" // Default: row on desktop
|
|
624
|
+
lg={{ direction: "column" }} // Column on large screens only
|
|
625
|
+
>
|
|
626
|
+
{/* Content */}
|
|
627
|
+
</Flex>
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
## Type Safety
|
|
631
|
+
|
|
632
|
+
### Semantic Element Enforcement
|
|
633
|
+
|
|
634
|
+
TypeScript prevents invalid element usage at compile-time:
|
|
635
|
+
|
|
636
|
+
```tsx
|
|
637
|
+
// ✅ Valid - div is a container element
|
|
638
|
+
<Flex as="div">...</Flex>
|
|
639
|
+
|
|
640
|
+
// ✅ Valid - section is semantic
|
|
641
|
+
<Flex as="section">...</Flex>
|
|
642
|
+
|
|
643
|
+
// ✅ Valid - nav is a list container
|
|
644
|
+
<Flex as="nav">...</Flex>
|
|
645
|
+
|
|
646
|
+
// ❌ TypeScript Error - span is not a container element
|
|
647
|
+
<Flex as="span">...</Flex>
|
|
648
|
+
|
|
649
|
+
// ❌ TypeScript Error - button is interactive
|
|
650
|
+
<Flex as="button">...</Flex>
|
|
651
|
+
|
|
652
|
+
// ✅ Valid - li is allowed for Flex.Item
|
|
653
|
+
<Flex as="ul">
|
|
654
|
+
<Flex.Item as="li">List item</Flex.Item>
|
|
655
|
+
</Flex>
|
|
656
|
+
|
|
657
|
+
// ❌ TypeScript Error - li not allowed on main Flex
|
|
658
|
+
<Flex as="li">...</Flex>
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### Type Exports
|
|
662
|
+
|
|
663
|
+
```tsx
|
|
664
|
+
import type {
|
|
665
|
+
FlexProps,
|
|
666
|
+
FlexItemProps,
|
|
667
|
+
FlexSpacerProps,
|
|
668
|
+
FlexContainerElement,
|
|
669
|
+
FlexItemElement,
|
|
670
|
+
FlexDirection,
|
|
671
|
+
FlexWrap,
|
|
672
|
+
FlexJustify,
|
|
673
|
+
FlexAlign,
|
|
674
|
+
FlexGap,
|
|
675
|
+
FlexVariant,
|
|
676
|
+
ResponsiveFlexProps,
|
|
677
|
+
} from "@fpkit/acss";
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
## Performance
|
|
681
|
+
|
|
682
|
+
### Utility Class Generation
|
|
683
|
+
|
|
684
|
+
The component generates utility class names instead of inline styles for better
|
|
685
|
+
performance:
|
|
686
|
+
|
|
687
|
+
**✅ Good (Utility Classes):**
|
|
688
|
+
|
|
689
|
+
```tsx
|
|
690
|
+
// Generates: "flex flex-row gap-md"
|
|
691
|
+
<Flex direction="row" gap="md">
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
**❌ Slower (Inline Styles):**
|
|
695
|
+
|
|
696
|
+
```tsx
|
|
697
|
+
// Less efficient
|
|
698
|
+
<div style={{ display: 'flex', flexDirection: 'row', gap: '1rem' }}>
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
**Benefits:**
|
|
702
|
+
|
|
703
|
+
- CSS caching by browser
|
|
704
|
+
- Smaller React updates
|
|
705
|
+
- Better performance in lists
|
|
706
|
+
- Easier to override with CSS
|
|
707
|
+
|
|
708
|
+
### Responsive Performance
|
|
709
|
+
|
|
710
|
+
Responsive props use CSS media queries (not JavaScript):
|
|
711
|
+
|
|
712
|
+
```tsx
|
|
713
|
+
// Generates: "flex flex-col md:flex-row"
|
|
714
|
+
// Media query handled by CSS, not JS
|
|
715
|
+
<Flex direction="column" md={{ direction: "row" }}>
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
## Best Practices
|
|
719
|
+
|
|
720
|
+
### 1. Choose the Right Semantic Element
|
|
721
|
+
|
|
722
|
+
```tsx
|
|
723
|
+
// ✅ Good - semantic header
|
|
724
|
+
<Flex as="header" justify="between">
|
|
725
|
+
<Logo />
|
|
726
|
+
<Nav />
|
|
727
|
+
</Flex>
|
|
728
|
+
|
|
729
|
+
// ✅ Good - semantic navigation
|
|
730
|
+
<Flex as="nav" gap="md">
|
|
731
|
+
<a href="/">Home</a>
|
|
732
|
+
<a href="/about">About</a>
|
|
733
|
+
</Flex>
|
|
734
|
+
|
|
735
|
+
// ❌ Bad - using div for everything
|
|
736
|
+
<Flex as="div">...</Flex>
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### 2. Use Preset Variants for Common Patterns
|
|
740
|
+
|
|
741
|
+
```tsx
|
|
742
|
+
// ✅ Good - use preset
|
|
743
|
+
<Flex variant="center">
|
|
744
|
+
<Logo />
|
|
745
|
+
</Flex>
|
|
746
|
+
|
|
747
|
+
// ❌ Unnecessary - manual props
|
|
748
|
+
<Flex justify="center" align="center" direction="column">
|
|
749
|
+
<Logo />
|
|
750
|
+
</Flex>
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
### 3. Leverage Responsive Props
|
|
754
|
+
|
|
755
|
+
```tsx
|
|
756
|
+
// ✅ Good - mobile-first responsive
|
|
757
|
+
<Flex
|
|
758
|
+
direction="column"
|
|
759
|
+
gap="sm"
|
|
760
|
+
md={{ direction: "row", gap: "lg" }}
|
|
761
|
+
>
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### 4. Use Flex.Item for Fine Control
|
|
765
|
+
|
|
766
|
+
```tsx
|
|
767
|
+
// ✅ Good - explicit flex behavior
|
|
768
|
+
<Flex.Item flex="1">Grows to fill space</Flex.Item>
|
|
769
|
+
<Flex.Item flex="none">Fixed size</Flex.Item>
|
|
770
|
+
|
|
771
|
+
// ❌ Less clear - manual styles
|
|
772
|
+
<div style={{ flex: 1 }}>...</div>
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
### 5. Use Flex.Spacer to Push Items
|
|
776
|
+
|
|
777
|
+
```tsx
|
|
778
|
+
// ✅ Good - semantic spacer
|
|
779
|
+
<Flex>
|
|
780
|
+
<div>Left</div>
|
|
781
|
+
<Flex.Spacer />
|
|
782
|
+
<div>Right</div>
|
|
783
|
+
</Flex>
|
|
784
|
+
|
|
785
|
+
// ❌ Less semantic
|
|
786
|
+
<Flex justify="between">
|
|
787
|
+
<div>Left</div>
|
|
788
|
+
<div>Right</div>
|
|
789
|
+
</Flex>
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
### 6. Maintain Semantic List Structures
|
|
793
|
+
|
|
794
|
+
```tsx
|
|
795
|
+
// ✅ Good - proper list semantics
|
|
796
|
+
<Flex as="ul">
|
|
797
|
+
<Flex.Item as="li">Item 1</Flex.Item>
|
|
798
|
+
<Flex.Item as="li">Item 2</Flex.Item>
|
|
799
|
+
</Flex>
|
|
800
|
+
|
|
801
|
+
// ❌ Bad - invalid HTML (ul > div)
|
|
802
|
+
<Flex as="ul">
|
|
803
|
+
<div>Item 1</div>
|
|
804
|
+
<div>Item 2</div>
|
|
805
|
+
</Flex>
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
## Technical Implementation
|
|
809
|
+
|
|
810
|
+
### Architecture
|
|
811
|
+
|
|
812
|
+
- **Hybrid Approach** - CSS utilities + React component API
|
|
813
|
+
- **Class Generation** - Props convert to utility class names
|
|
814
|
+
- **Responsive Design** - Breakpoint-prefixed classes for media queries
|
|
815
|
+
- **Type Safety** - Literal union types restrict valid options
|
|
816
|
+
- **Compound Pattern** - Sub-components attached as properties
|
|
817
|
+
|
|
818
|
+
### Class Name Generation
|
|
819
|
+
|
|
820
|
+
```tsx
|
|
821
|
+
// From flex.tsx
|
|
822
|
+
const generateFlexClasses = (
|
|
823
|
+
props: ResponsiveFlexProps,
|
|
824
|
+
prefix = ""
|
|
825
|
+
): string[] => {
|
|
826
|
+
const classes: string[] = [];
|
|
827
|
+
|
|
828
|
+
if (props.direction) {
|
|
829
|
+
const dirMap = {
|
|
830
|
+
row: "flex-row",
|
|
831
|
+
"row-reverse": "flex-row-reverse",
|
|
832
|
+
column: "flex-col",
|
|
833
|
+
"column-reverse": "flex-col-reverse",
|
|
834
|
+
};
|
|
835
|
+
classes.push(`${prefix}${dirMap[props.direction]}`);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// ... more mappings
|
|
839
|
+
|
|
840
|
+
return classes;
|
|
841
|
+
};
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Responsive Class Generation
|
|
845
|
+
|
|
846
|
+
```tsx
|
|
847
|
+
// Responsive breakpoint classes
|
|
848
|
+
if (sm) classes.push(...generateFlexClasses(sm, "sm:"));
|
|
849
|
+
if (md) classes.push(...generateFlexClasses(md, "md:"));
|
|
850
|
+
if (lg) classes.push(...generateFlexClasses(lg, "lg:"));
|
|
851
|
+
if (xl) classes.push(...generateFlexClasses(xl, "xl:"));
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### Testing
|
|
855
|
+
|
|
856
|
+
The component has 100% test coverage with 62 tests:
|
|
857
|
+
|
|
858
|
+
- ✅ Basic rendering and props
|
|
859
|
+
- ✅ Direction, wrap, gap, justify, align props
|
|
860
|
+
- ✅ Preset variants
|
|
861
|
+
- ✅ Responsive breakpoint props
|
|
862
|
+
- ✅ Compound components (Flex.Item, Flex.Spacer)
|
|
863
|
+
- ✅ Flex.Item sizing and alignment
|
|
864
|
+
- ✅ Polymorphic rendering (`as` prop)
|
|
865
|
+
- ✅ Custom className and styles
|
|
866
|
+
- ✅ Display names
|
|
867
|
+
|
|
868
|
+
Run tests:
|
|
869
|
+
|
|
870
|
+
```bash
|
|
871
|
+
cd packages/fpkit && npm test flex.test.tsx
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
## Comparison: Flex Component vs Direct Utility Classes
|
|
875
|
+
|
|
876
|
+
### Using Flex Component (Recommended)
|
|
877
|
+
|
|
878
|
+
```tsx
|
|
879
|
+
<Flex direction="row" gap="md" md={{ direction: "column" }}>
|
|
880
|
+
<Flex.Item flex="1">Content</Flex.Item>
|
|
881
|
+
</Flex>
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
**Benefits:**
|
|
885
|
+
|
|
886
|
+
- ✅ TypeScript autocomplete and type safety
|
|
887
|
+
- ✅ Semantic element enforcement
|
|
888
|
+
- ✅ Cleaner JSX
|
|
889
|
+
- ✅ Easy responsive props
|
|
890
|
+
- ✅ Better refactoring
|
|
891
|
+
|
|
892
|
+
### Using Direct Utility Classes
|
|
893
|
+
|
|
894
|
+
```tsx
|
|
895
|
+
<div className="flex flex-row gap-md md:flex-col">
|
|
896
|
+
<div className="flex-1">Content</div>
|
|
897
|
+
</div>
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
**Benefits:**
|
|
901
|
+
|
|
902
|
+
- ✅ Slightly less JavaScript
|
|
903
|
+
- ✅ Direct CSS control
|
|
904
|
+
- ✅ Familiar to Tailwind users
|
|
905
|
+
|
|
906
|
+
**Both approaches are valid** - the Flex component provides a React-friendly API
|
|
907
|
+
on top of the same utility classes.
|
|
908
|
+
|
|
909
|
+
## Browser Support
|
|
910
|
+
|
|
911
|
+
- ✅ Modern browsers (Chrome, Firefox, Safari, Edge)
|
|
912
|
+
- ✅ Requires CSS flexbox support
|
|
913
|
+
- ✅ Requires React 18+
|
|
914
|
+
- ✅ TypeScript 5.0+ recommended for full type safety
|
|
915
|
+
- ✅ CSS custom properties support
|
|
916
|
+
|
|
917
|
+
## API Reference
|
|
918
|
+
|
|
919
|
+
### Exported Components
|
|
920
|
+
|
|
921
|
+
- `Flex` - Main flexbox container component
|
|
922
|
+
- `Flex.Item` - Individual flex item with sizing controls
|
|
923
|
+
- `Flex.Spacer` - Auto-expanding spacer element
|
|
924
|
+
|
|
925
|
+
### Exported Types
|
|
926
|
+
|
|
927
|
+
- `FlexProps` - Main Flex component props
|
|
928
|
+
- `FlexItemProps` - Flex.Item component props
|
|
929
|
+
- `FlexSpacerProps` - Flex.Spacer component props
|
|
930
|
+
- `FlexContainerElement` - Valid container elements
|
|
931
|
+
- `FlexItemElement` - Valid item elements (includes list items)
|
|
932
|
+
- `FlexDirection` - Direction values
|
|
933
|
+
- `FlexWrap` - Wrap values
|
|
934
|
+
- `FlexJustify` - Justify content values
|
|
935
|
+
- `FlexAlign` - Align items values
|
|
936
|
+
- `FlexAlignContent` - Align content values
|
|
937
|
+
- `FlexAlignSelf` - Align self values
|
|
938
|
+
- `FlexGap` - Gap size values
|
|
939
|
+
- `FlexVariant` - Preset variant values
|
|
940
|
+
- `ResponsiveFlexProps` - Props for responsive breakpoints
|
|
941
|
+
|
|
942
|
+
## Migration Guide
|
|
943
|
+
|
|
944
|
+
### From Previous Versions
|
|
945
|
+
|
|
946
|
+
If migrating from direct utility classes or other flex systems:
|
|
947
|
+
|
|
948
|
+
**Before:**
|
|
949
|
+
|
|
950
|
+
```tsx
|
|
951
|
+
<div className="flex flex-row gap-md">
|
|
952
|
+
<div className="flex-1">Content</div>
|
|
953
|
+
</div>
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
**After:**
|
|
957
|
+
|
|
958
|
+
```tsx
|
|
959
|
+
<Flex direction="row" gap="md">
|
|
960
|
+
<Flex.Item flex="1">Content</Flex.Item>
|
|
961
|
+
</Flex>
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
### Type Safety Updates (v3.0.0+)
|
|
965
|
+
|
|
966
|
+
Version 3.0.0 introduces semantic element restrictions:
|
|
967
|
+
|
|
968
|
+
```tsx
|
|
969
|
+
// ✅ Valid in v3.0.0+
|
|
970
|
+
<Flex as="section">...</Flex>
|
|
971
|
+
|
|
972
|
+
// ❌ TypeScript error in v3.0.0+ (was allowed before)
|
|
973
|
+
<Flex as="span">...</Flex>
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
Update code to use valid container elements only.
|
|
977
|
+
|
|
978
|
+
## Resources
|
|
979
|
+
|
|
980
|
+
- [Storybook Documentation](http://localhost:6006/?path=/docs/fp-react-components-flex--docs)
|
|
981
|
+
- [GitHub Repository](https://github.com/yourusername/acss)
|
|
982
|
+
- [CSS Flexbox Guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
|
|
983
|
+
- [MDN Flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout)
|
|
984
|
+
|
|
985
|
+
## Support
|
|
986
|
+
|
|
987
|
+
For issues, questions, or contributions:
|
|
988
|
+
|
|
989
|
+
- Open an issue on [GitHub](https://github.com/yourusername/acss/issues)
|
|
990
|
+
- Check existing [Storybook stories](http://localhost:6006) for examples
|
|
991
|
+
- Review the comprehensive test suite for usage patterns
|
|
992
|
+
|
|
993
|
+
---
|
|
994
|
+
|
|
995
|
+
**Version:** v3.0.0+ **Last Updated:** December 2025 **Test Coverage:** 100% (62
|
|
996
|
+
tests) **Maintained by:** fpkit Team
|