@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,1233 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { within, expect } from "storybook/test";
|
|
3
|
+
import Flex from "./flex";
|
|
4
|
+
import "./flex.scss";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Flexbox Utilities and Component Story
|
|
8
|
+
* Comprehensive documentation of responsive flexbox utility classes and React Flex component
|
|
9
|
+
*/
|
|
10
|
+
const meta: Meta<typeof Flex> = {
|
|
11
|
+
title: "FP.React Components/Layout/Flex",
|
|
12
|
+
component: Flex,
|
|
13
|
+
tags: ["autodocs", "rc"],
|
|
14
|
+
parameters: {
|
|
15
|
+
docs: {
|
|
16
|
+
description: {
|
|
17
|
+
component: `
|
|
18
|
+
# Flex Container Component
|
|
19
|
+
|
|
20
|
+
A flexible container component for creating flexbox layouts with a declarative React API.
|
|
21
|
+
Supports responsive props, preset variants, and compound pattern with Flex.Item and Flex.Spacer.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Compound Pattern**: Use \`Flex.Item\` and \`Flex.Spacer\` sub-components
|
|
26
|
+
- **Responsive Props**: Different layouts at sm/md/lg/xl breakpoints
|
|
27
|
+
- **Preset Variants**: Common patterns like 'center', 'between', 'stack'
|
|
28
|
+
- **CSS Custom Properties**: Runtime theming via styles prop
|
|
29
|
+
- **Polymorphic**: Render as any HTML element via 'as' prop
|
|
30
|
+
- **Type-Safe**: Full TypeScript support with autocomplete
|
|
31
|
+
|
|
32
|
+
## Usage Approaches
|
|
33
|
+
|
|
34
|
+
### 1. React Component (Recommended)
|
|
35
|
+
\`\`\`tsx
|
|
36
|
+
<Flex gap="md" justify="between" align="center">
|
|
37
|
+
<Flex.Item flex="1">Content 1</Flex.Item>
|
|
38
|
+
<Flex.Item flex="1">Content 2</Flex.Item>
|
|
39
|
+
</Flex>
|
|
40
|
+
\`\`\`
|
|
41
|
+
|
|
42
|
+
### 2. Utility Classes (Direct HTML)
|
|
43
|
+
\`\`\`html
|
|
44
|
+
<div className="flex gap-md justify-between items-center">
|
|
45
|
+
<div className="flex-1">Content 1</div>
|
|
46
|
+
<div className="flex-1">Content 2</div>
|
|
47
|
+
</div>
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
## Breakpoints
|
|
51
|
+
|
|
52
|
+
- **sm**: 30rem (480px)
|
|
53
|
+
- **md**: 48rem (768px)
|
|
54
|
+
- **lg**: 62rem (992px)
|
|
55
|
+
- **xl**: 80rem (1280px)
|
|
56
|
+
|
|
57
|
+
## CSS Custom Properties
|
|
58
|
+
|
|
59
|
+
Override default spacing:
|
|
60
|
+
|
|
61
|
+
\`\`\`css
|
|
62
|
+
:root {
|
|
63
|
+
--flex-gap-xs: 0.25rem;
|
|
64
|
+
--flex-gap-sm: 0.5rem;
|
|
65
|
+
--flex-gap-md: 0.75rem;
|
|
66
|
+
--flex-gap-lg: 1rem;
|
|
67
|
+
--flex-gap-xl: 1.5rem;
|
|
68
|
+
}
|
|
69
|
+
\`\`\`
|
|
70
|
+
`,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export default meta;
|
|
77
|
+
type Story = StoryObj<typeof Flex>;
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// REACT COMPONENT STORIES
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Basic Flex component usage
|
|
85
|
+
*/
|
|
86
|
+
export const FlexComponent: Story = {
|
|
87
|
+
args: {
|
|
88
|
+
gap: "md",
|
|
89
|
+
children: (
|
|
90
|
+
<>
|
|
91
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
92
|
+
Item 1
|
|
93
|
+
</div>
|
|
94
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
95
|
+
Item 2
|
|
96
|
+
</div>
|
|
97
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
98
|
+
Item 3
|
|
99
|
+
</div>
|
|
100
|
+
</>
|
|
101
|
+
),
|
|
102
|
+
},
|
|
103
|
+
play: async ({ canvasElement, step }) => {
|
|
104
|
+
const canvas = within(canvasElement);
|
|
105
|
+
|
|
106
|
+
await step("Flex container renders correctly", async () => {
|
|
107
|
+
const flexContainer = canvas.getByText("Item 1").parentElement?.parentElement;
|
|
108
|
+
expect(flexContainer).toBeInTheDocument();
|
|
109
|
+
expect(flexContainer).toHaveClass("flex");
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
parameters: {
|
|
113
|
+
docs: {
|
|
114
|
+
description: {
|
|
115
|
+
story:
|
|
116
|
+
"Basic Flex component with gap spacing. The component automatically generates the appropriate utility classes from props.",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Flex with various layout props
|
|
124
|
+
*/
|
|
125
|
+
export const FlexWithProps: Story = {
|
|
126
|
+
render: () => (
|
|
127
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
128
|
+
<div>
|
|
129
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Row direction with space between</h4>
|
|
130
|
+
<Flex
|
|
131
|
+
direction="row"
|
|
132
|
+
justify="between"
|
|
133
|
+
align="center"
|
|
134
|
+
gap="md"
|
|
135
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
136
|
+
>
|
|
137
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
138
|
+
Left
|
|
139
|
+
</div>
|
|
140
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
141
|
+
Center
|
|
142
|
+
</div>
|
|
143
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
144
|
+
Right
|
|
145
|
+
</div>
|
|
146
|
+
</Flex>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div>
|
|
150
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Column direction with center alignment</h4>
|
|
151
|
+
<Flex
|
|
152
|
+
direction="column"
|
|
153
|
+
align="center"
|
|
154
|
+
gap="sm"
|
|
155
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
156
|
+
>
|
|
157
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
158
|
+
Item 1
|
|
159
|
+
</div>
|
|
160
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
161
|
+
Item 2
|
|
162
|
+
</div>
|
|
163
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
164
|
+
Item 3
|
|
165
|
+
</div>
|
|
166
|
+
</Flex>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
),
|
|
170
|
+
parameters: {
|
|
171
|
+
docs: {
|
|
172
|
+
description: {
|
|
173
|
+
story: "Demonstrates different combinations of direction, justify, align, and gap props.",
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Responsive Flex layout
|
|
181
|
+
*/
|
|
182
|
+
export const FlexResponsive: Story = {
|
|
183
|
+
render: () => (
|
|
184
|
+
<Flex
|
|
185
|
+
direction="column"
|
|
186
|
+
gap="sm"
|
|
187
|
+
md={{ direction: "row", gap: "lg", justify: "between" }}
|
|
188
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
189
|
+
>
|
|
190
|
+
<Flex.Item flex="none" md={{ flex: "1" }}>
|
|
191
|
+
<div
|
|
192
|
+
style={{
|
|
193
|
+
padding: "1rem",
|
|
194
|
+
background: "#e3f2fd",
|
|
195
|
+
borderRadius: "0.25rem",
|
|
196
|
+
minHeight: "6rem",
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
Column on mobile<br />Row on medium+<br />flex="1" on medium+
|
|
200
|
+
</div>
|
|
201
|
+
</Flex.Item>
|
|
202
|
+
<Flex.Item flex="none" md={{ flex: "1" }}>
|
|
203
|
+
<div
|
|
204
|
+
style={{
|
|
205
|
+
padding: "1rem",
|
|
206
|
+
background: "#bbdefb",
|
|
207
|
+
borderRadius: "0.25rem",
|
|
208
|
+
minHeight: "6rem",
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
Responsive layout with gap changes
|
|
212
|
+
</div>
|
|
213
|
+
</Flex.Item>
|
|
214
|
+
<Flex.Item flex="none" md={{ flex: "1" }}>
|
|
215
|
+
<div
|
|
216
|
+
style={{
|
|
217
|
+
padding: "1rem",
|
|
218
|
+
background: "#90caf9",
|
|
219
|
+
borderRadius: "0.25rem",
|
|
220
|
+
minHeight: "6rem",
|
|
221
|
+
}}
|
|
222
|
+
>
|
|
223
|
+
Resize to see behavior
|
|
224
|
+
</div>
|
|
225
|
+
</Flex.Item>
|
|
226
|
+
</Flex>
|
|
227
|
+
),
|
|
228
|
+
parameters: {
|
|
229
|
+
docs: {
|
|
230
|
+
description: {
|
|
231
|
+
story:
|
|
232
|
+
"Responsive layout that changes from column on mobile to row on medium+ screens, with different gap sizes at different breakpoints.",
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
chromatic: {
|
|
236
|
+
viewports: [375, 768, 1280],
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Flex.Item sub-component
|
|
243
|
+
*/
|
|
244
|
+
export const FlexWithItems: Story = {
|
|
245
|
+
render: () => (
|
|
246
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
247
|
+
<div>
|
|
248
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Equal width items (flex="1")</h4>
|
|
249
|
+
<Flex
|
|
250
|
+
gap="md"
|
|
251
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
252
|
+
>
|
|
253
|
+
<Flex.Item flex="1">
|
|
254
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
255
|
+
flex="1"
|
|
256
|
+
</div>
|
|
257
|
+
</Flex.Item>
|
|
258
|
+
<Flex.Item flex="1">
|
|
259
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
260
|
+
flex="1"
|
|
261
|
+
</div>
|
|
262
|
+
</Flex.Item>
|
|
263
|
+
<Flex.Item flex="1">
|
|
264
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
265
|
+
flex="1"
|
|
266
|
+
</div>
|
|
267
|
+
</Flex.Item>
|
|
268
|
+
</Flex>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
<div>
|
|
272
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Mixed sizing (flex="none" + flex="1")</h4>
|
|
273
|
+
<Flex
|
|
274
|
+
gap="md"
|
|
275
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
276
|
+
>
|
|
277
|
+
<Flex.Item flex="none" styles={{ width: "8rem" }}>
|
|
278
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
279
|
+
Fixed 8rem
|
|
280
|
+
</div>
|
|
281
|
+
</Flex.Item>
|
|
282
|
+
<Flex.Item flex="1">
|
|
283
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
284
|
+
Fills remaining space
|
|
285
|
+
</div>
|
|
286
|
+
</Flex.Item>
|
|
287
|
+
</Flex>
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<div>
|
|
291
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Custom alignment (alignSelf)</h4>
|
|
292
|
+
<Flex
|
|
293
|
+
gap="md"
|
|
294
|
+
style={{
|
|
295
|
+
padding: "1rem",
|
|
296
|
+
border: "2px dashed #ccc",
|
|
297
|
+
borderRadius: "0.5rem",
|
|
298
|
+
minHeight: "8rem",
|
|
299
|
+
}}
|
|
300
|
+
>
|
|
301
|
+
<Flex.Item alignSelf="start">
|
|
302
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
303
|
+
Start
|
|
304
|
+
</div>
|
|
305
|
+
</Flex.Item>
|
|
306
|
+
<Flex.Item alignSelf="center">
|
|
307
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
308
|
+
Center
|
|
309
|
+
</div>
|
|
310
|
+
</Flex.Item>
|
|
311
|
+
<Flex.Item alignSelf="end">
|
|
312
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
313
|
+
End
|
|
314
|
+
</div>
|
|
315
|
+
</Flex.Item>
|
|
316
|
+
</Flex>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
),
|
|
320
|
+
parameters: {
|
|
321
|
+
docs: {
|
|
322
|
+
description: {
|
|
323
|
+
story:
|
|
324
|
+
"Demonstrates Flex.Item sub-component with different flex sizing and alignment options.",
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Flex.Spacer sub-component
|
|
332
|
+
*/
|
|
333
|
+
export const FlexWithSpacer: Story = {
|
|
334
|
+
render: () => (
|
|
335
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
336
|
+
<div>
|
|
337
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Push items to opposite edges</h4>
|
|
338
|
+
<Flex
|
|
339
|
+
gap="md"
|
|
340
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
341
|
+
>
|
|
342
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
343
|
+
Left side
|
|
344
|
+
</div>
|
|
345
|
+
<Flex.Spacer />
|
|
346
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
347
|
+
Right side
|
|
348
|
+
</div>
|
|
349
|
+
</Flex>
|
|
350
|
+
</div>
|
|
351
|
+
|
|
352
|
+
<div>
|
|
353
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Multiple spacers for even distribution</h4>
|
|
354
|
+
<Flex
|
|
355
|
+
gap="md"
|
|
356
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
357
|
+
>
|
|
358
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
359
|
+
Start
|
|
360
|
+
</div>
|
|
361
|
+
<Flex.Spacer />
|
|
362
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
363
|
+
Middle
|
|
364
|
+
</div>
|
|
365
|
+
<Flex.Spacer />
|
|
366
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
367
|
+
End
|
|
368
|
+
</div>
|
|
369
|
+
</Flex>
|
|
370
|
+
</div>
|
|
371
|
+
</div>
|
|
372
|
+
),
|
|
373
|
+
parameters: {
|
|
374
|
+
docs: {
|
|
375
|
+
description: {
|
|
376
|
+
story:
|
|
377
|
+
"Flex.Spacer creates auto-expanding space (flex: 1) to push items apart. Commonly used for navbar layouts and toolbars.",
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Preset variants
|
|
385
|
+
*/
|
|
386
|
+
export const FlexVariants: Story = {
|
|
387
|
+
render: () => (
|
|
388
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
389
|
+
<div>
|
|
390
|
+
<h4 style={{ marginBottom: "0.5rem" }}>variant="center"</h4>
|
|
391
|
+
<Flex
|
|
392
|
+
variant="center"
|
|
393
|
+
style={{
|
|
394
|
+
padding: "2rem",
|
|
395
|
+
border: "2px dashed #ccc",
|
|
396
|
+
borderRadius: "0.5rem",
|
|
397
|
+
minHeight: "8rem",
|
|
398
|
+
}}
|
|
399
|
+
>
|
|
400
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
401
|
+
Centered both axes
|
|
402
|
+
</div>
|
|
403
|
+
</Flex>
|
|
404
|
+
</div>
|
|
405
|
+
|
|
406
|
+
<div>
|
|
407
|
+
<h4 style={{ marginBottom: "0.5rem" }}>variant="between"</h4>
|
|
408
|
+
<Flex
|
|
409
|
+
variant="between"
|
|
410
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
411
|
+
>
|
|
412
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
413
|
+
Left
|
|
414
|
+
</div>
|
|
415
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
416
|
+
Right
|
|
417
|
+
</div>
|
|
418
|
+
</Flex>
|
|
419
|
+
</div>
|
|
420
|
+
|
|
421
|
+
<div>
|
|
422
|
+
<h4 style={{ marginBottom: "0.5rem" }}>variant="stack"</h4>
|
|
423
|
+
<Flex
|
|
424
|
+
variant="stack"
|
|
425
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
426
|
+
>
|
|
427
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
428
|
+
Stacked Item 1
|
|
429
|
+
</div>
|
|
430
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
431
|
+
Stacked Item 2
|
|
432
|
+
</div>
|
|
433
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
434
|
+
Stacked Item 3
|
|
435
|
+
</div>
|
|
436
|
+
</Flex>
|
|
437
|
+
<p style={{ marginTop: "0.5rem", fontSize: "0.875rem", color: "#666" }}>
|
|
438
|
+
Stack variant uses column layout by default, becomes row on medium+ screens
|
|
439
|
+
</p>
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<div>
|
|
443
|
+
<h4 style={{ marginBottom: "0.5rem" }}>variant="spread"</h4>
|
|
444
|
+
<Flex
|
|
445
|
+
variant="spread"
|
|
446
|
+
gap="sm"
|
|
447
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
448
|
+
>
|
|
449
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
450
|
+
Equal
|
|
451
|
+
</div>
|
|
452
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
453
|
+
Width
|
|
454
|
+
</div>
|
|
455
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
456
|
+
Items
|
|
457
|
+
</div>
|
|
458
|
+
</Flex>
|
|
459
|
+
</div>
|
|
460
|
+
</div>
|
|
461
|
+
),
|
|
462
|
+
parameters: {
|
|
463
|
+
docs: {
|
|
464
|
+
description: {
|
|
465
|
+
story:
|
|
466
|
+
"Preset variants provide common flexbox patterns: 'center', 'between', 'around', 'stack', 'spread'.",
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Nested Flex containers
|
|
474
|
+
*/
|
|
475
|
+
export const NestedFlex: Story = {
|
|
476
|
+
render: () => (
|
|
477
|
+
<Flex
|
|
478
|
+
direction="column"
|
|
479
|
+
gap="md"
|
|
480
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
481
|
+
>
|
|
482
|
+
<Flex justify="between" align="center" gap="md">
|
|
483
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
484
|
+
Header Left
|
|
485
|
+
</div>
|
|
486
|
+
<Flex.Spacer />
|
|
487
|
+
<Flex gap="sm">
|
|
488
|
+
<div style={{ padding: "0.5rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
489
|
+
Nav 1
|
|
490
|
+
</div>
|
|
491
|
+
<div style={{ padding: "0.5rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
492
|
+
Nav 2
|
|
493
|
+
</div>
|
|
494
|
+
<div style={{ padding: "0.5rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
495
|
+
Nav 3
|
|
496
|
+
</div>
|
|
497
|
+
</Flex>
|
|
498
|
+
</Flex>
|
|
499
|
+
|
|
500
|
+
<Flex gap="md">
|
|
501
|
+
<Flex.Item flex="none" styles={{ width: "12rem" }}>
|
|
502
|
+
<div
|
|
503
|
+
style={{
|
|
504
|
+
padding: "1rem",
|
|
505
|
+
background: "#f3e5f5",
|
|
506
|
+
borderRadius: "0.25rem",
|
|
507
|
+
minHeight: "12rem",
|
|
508
|
+
}}
|
|
509
|
+
>
|
|
510
|
+
Sidebar
|
|
511
|
+
</div>
|
|
512
|
+
</Flex.Item>
|
|
513
|
+
<Flex.Item flex="1">
|
|
514
|
+
<Flex
|
|
515
|
+
direction="column"
|
|
516
|
+
gap="md"
|
|
517
|
+
style={{ padding: "1rem", background: "#f1f8e9", borderRadius: "0.25rem" }}
|
|
518
|
+
>
|
|
519
|
+
<div style={{ padding: "0.75rem", background: "#dcedc8", borderRadius: "0.25rem" }}>
|
|
520
|
+
Main content area
|
|
521
|
+
</div>
|
|
522
|
+
<Flex gap="sm">
|
|
523
|
+
<Flex.Item flex="1">
|
|
524
|
+
<div style={{ padding: "0.75rem", background: "#c5e1a5", borderRadius: "0.25rem" }}>
|
|
525
|
+
Column 1
|
|
526
|
+
</div>
|
|
527
|
+
</Flex.Item>
|
|
528
|
+
<Flex.Item flex="1">
|
|
529
|
+
<div style={{ padding: "0.75rem", background: "#c5e1a5", borderRadius: "0.25rem" }}>
|
|
530
|
+
Column 2
|
|
531
|
+
</div>
|
|
532
|
+
</Flex.Item>
|
|
533
|
+
</Flex>
|
|
534
|
+
</Flex>
|
|
535
|
+
</Flex.Item>
|
|
536
|
+
</Flex>
|
|
537
|
+
</Flex>
|
|
538
|
+
),
|
|
539
|
+
parameters: {
|
|
540
|
+
docs: {
|
|
541
|
+
description: {
|
|
542
|
+
story:
|
|
543
|
+
"Complex layout demonstrating nested Flex containers to create a typical application layout with header, sidebar, and main content.",
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Custom styling with CSS variables
|
|
551
|
+
*/
|
|
552
|
+
export const CustomStyling: Story = {
|
|
553
|
+
render: () => (
|
|
554
|
+
<Flex
|
|
555
|
+
gap="md"
|
|
556
|
+
styles={
|
|
557
|
+
{
|
|
558
|
+
"--flex-gap": "3rem",
|
|
559
|
+
padding: "2rem",
|
|
560
|
+
border: "2px solid #1976d2",
|
|
561
|
+
borderRadius: "0.5rem",
|
|
562
|
+
background: "linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%)",
|
|
563
|
+
} as React.CSSProperties
|
|
564
|
+
}
|
|
565
|
+
>
|
|
566
|
+
<div style={{ padding: "1rem", background: "white", borderRadius: "0.25rem" }}>
|
|
567
|
+
Custom gap via --flex-gap
|
|
568
|
+
</div>
|
|
569
|
+
<div style={{ padding: "1rem", background: "white", borderRadius: "0.25rem" }}>
|
|
570
|
+
Custom styles
|
|
571
|
+
</div>
|
|
572
|
+
<div style={{ padding: "1rem", background: "white", borderRadius: "0.25rem" }}>
|
|
573
|
+
Via styles prop
|
|
574
|
+
</div>
|
|
575
|
+
</Flex>
|
|
576
|
+
),
|
|
577
|
+
parameters: {
|
|
578
|
+
docs: {
|
|
579
|
+
description: {
|
|
580
|
+
story:
|
|
581
|
+
"Demonstrates custom styling using CSS custom properties and inline styles via the styles prop.",
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
},
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Polymorphic rendering
|
|
589
|
+
*/
|
|
590
|
+
export const PolymorphicFlex: Story = {
|
|
591
|
+
render: () => (
|
|
592
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
593
|
+
<div>
|
|
594
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Render as <nav></h4>
|
|
595
|
+
<Flex
|
|
596
|
+
as="nav"
|
|
597
|
+
role="navigation"
|
|
598
|
+
aria-label="Main navigation"
|
|
599
|
+
gap="md"
|
|
600
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
601
|
+
>
|
|
602
|
+
<a href="#" style={{ padding: "0.5rem", textDecoration: "none", color: "#1976d2" }}>
|
|
603
|
+
Home
|
|
604
|
+
</a>
|
|
605
|
+
<a href="#" style={{ padding: "0.5rem", textDecoration: "none", color: "#1976d2" }}>
|
|
606
|
+
About
|
|
607
|
+
</a>
|
|
608
|
+
<a href="#" style={{ padding: "0.5rem", textDecoration: "none", color: "#1976d2" }}>
|
|
609
|
+
Contact
|
|
610
|
+
</a>
|
|
611
|
+
</Flex>
|
|
612
|
+
</div>
|
|
613
|
+
|
|
614
|
+
<div>
|
|
615
|
+
<h4 style={{ marginBottom: "0.5rem" }}>Render as <section></h4>
|
|
616
|
+
<Flex
|
|
617
|
+
as="section"
|
|
618
|
+
direction="column"
|
|
619
|
+
gap="md"
|
|
620
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
621
|
+
>
|
|
622
|
+
<h3 style={{ margin: 0 }}>Section Title</h3>
|
|
623
|
+
<p style={{ margin: 0 }}>Content in a semantic section element</p>
|
|
624
|
+
</Flex>
|
|
625
|
+
</div>
|
|
626
|
+
</div>
|
|
627
|
+
),
|
|
628
|
+
parameters: {
|
|
629
|
+
docs: {
|
|
630
|
+
description: {
|
|
631
|
+
story:
|
|
632
|
+
"The 'as' prop allows Flex to render as any HTML element, enabling semantic markup while maintaining flexbox behavior.",
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// ============================================================================
|
|
639
|
+
// UTILITY CLASS STORIES (Preserved for backward compatibility)
|
|
640
|
+
// ============================================================================
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Basic flex container with default gap
|
|
644
|
+
*/
|
|
645
|
+
export const BasicFlex: Story = {
|
|
646
|
+
render: () => (
|
|
647
|
+
<div
|
|
648
|
+
className="flex"
|
|
649
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
650
|
+
>
|
|
651
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
652
|
+
Item 1
|
|
653
|
+
</div>
|
|
654
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
655
|
+
Item 2
|
|
656
|
+
</div>
|
|
657
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
658
|
+
Item 3
|
|
659
|
+
</div>
|
|
660
|
+
</div>
|
|
661
|
+
),
|
|
662
|
+
parameters: {
|
|
663
|
+
docs: {
|
|
664
|
+
description: {
|
|
665
|
+
story: "Basic flex container with default gap. The `.flex` class provides `display: flex` with automatic gap spacing.",
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Flex direction utilities
|
|
673
|
+
*/
|
|
674
|
+
export const FlexDirection: Story = {
|
|
675
|
+
render: () => (
|
|
676
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
677
|
+
<div>
|
|
678
|
+
<h3 style={{ marginBottom: "0.5rem" }}>Row (default)</h3>
|
|
679
|
+
<div
|
|
680
|
+
className="flex flex-row gap-sm"
|
|
681
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
682
|
+
>
|
|
683
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>1</div>
|
|
684
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>2</div>
|
|
685
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>3</div>
|
|
686
|
+
</div>
|
|
687
|
+
</div>
|
|
688
|
+
|
|
689
|
+
<div>
|
|
690
|
+
<h3 style={{ marginBottom: "0.5rem" }}>Column</h3>
|
|
691
|
+
<div
|
|
692
|
+
className="flex flex-col gap-sm"
|
|
693
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
694
|
+
>
|
|
695
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>1</div>
|
|
696
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>2</div>
|
|
697
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>3</div>
|
|
698
|
+
</div>
|
|
699
|
+
</div>
|
|
700
|
+
|
|
701
|
+
<div>
|
|
702
|
+
<h3 style={{ marginBottom: "0.5rem" }}>Row Reverse</h3>
|
|
703
|
+
<div
|
|
704
|
+
className="flex flex-row-reverse gap-sm"
|
|
705
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
706
|
+
>
|
|
707
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>1</div>
|
|
708
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>2</div>
|
|
709
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>3</div>
|
|
710
|
+
</div>
|
|
711
|
+
</div>
|
|
712
|
+
</div>
|
|
713
|
+
),
|
|
714
|
+
parameters: {
|
|
715
|
+
docs: {
|
|
716
|
+
description: {
|
|
717
|
+
story: "Flex direction utilities: `.flex-row`, `.flex-col`, `.flex-row-reverse`, `.flex-col-reverse`",
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Justify content (main axis alignment)
|
|
725
|
+
*/
|
|
726
|
+
export const JustifyContent: Story = {
|
|
727
|
+
render: () => (
|
|
728
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
729
|
+
{[
|
|
730
|
+
{ class: "justify-start", label: "Start" },
|
|
731
|
+
{ class: "justify-center", label: "Center" },
|
|
732
|
+
{ class: "justify-end", label: "End" },
|
|
733
|
+
{ class: "justify-between", label: "Space Between" },
|
|
734
|
+
{ class: "justify-around", label: "Space Around" },
|
|
735
|
+
{ class: "justify-evenly", label: "Space Evenly" },
|
|
736
|
+
].map(({ class: className, label }) => (
|
|
737
|
+
<div key={className}>
|
|
738
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>{label}</h4>
|
|
739
|
+
<div
|
|
740
|
+
className={`flex ${className}`}
|
|
741
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
742
|
+
>
|
|
743
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
744
|
+
A
|
|
745
|
+
</div>
|
|
746
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
747
|
+
B
|
|
748
|
+
</div>
|
|
749
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
750
|
+
C
|
|
751
|
+
</div>
|
|
752
|
+
</div>
|
|
753
|
+
</div>
|
|
754
|
+
))}
|
|
755
|
+
</div>
|
|
756
|
+
),
|
|
757
|
+
parameters: {
|
|
758
|
+
docs: {
|
|
759
|
+
description: {
|
|
760
|
+
story:
|
|
761
|
+
"Justify content utilities control main axis alignment: `.justify-start`, `.justify-center`, `.justify-end`, `.justify-between`, `.justify-around`, `.justify-evenly`",
|
|
762
|
+
},
|
|
763
|
+
},
|
|
764
|
+
},
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Align items (cross axis alignment)
|
|
769
|
+
*/
|
|
770
|
+
export const AlignItems: Story = {
|
|
771
|
+
render: () => (
|
|
772
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
773
|
+
{[
|
|
774
|
+
{ class: "items-start", label: "Start" },
|
|
775
|
+
{ class: "items-center", label: "Center" },
|
|
776
|
+
{ class: "items-end", label: "End" },
|
|
777
|
+
{ class: "items-stretch", label: "Stretch" },
|
|
778
|
+
{ class: "items-baseline", label: "Baseline" },
|
|
779
|
+
].map(({ class: className, label }) => (
|
|
780
|
+
<div key={className}>
|
|
781
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>{label}</h4>
|
|
782
|
+
<div
|
|
783
|
+
className={`flex ${className}`}
|
|
784
|
+
style={{
|
|
785
|
+
padding: "1rem",
|
|
786
|
+
border: "2px dashed #ccc",
|
|
787
|
+
borderRadius: "0.5rem",
|
|
788
|
+
minHeight: "6rem",
|
|
789
|
+
}}
|
|
790
|
+
>
|
|
791
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
792
|
+
Small
|
|
793
|
+
</div>
|
|
794
|
+
<div
|
|
795
|
+
style={{
|
|
796
|
+
padding: "0.75rem",
|
|
797
|
+
background: "#bbdefb",
|
|
798
|
+
borderRadius: "0.25rem",
|
|
799
|
+
height: "4rem",
|
|
800
|
+
}}
|
|
801
|
+
>
|
|
802
|
+
Medium
|
|
803
|
+
</div>
|
|
804
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
805
|
+
Small
|
|
806
|
+
</div>
|
|
807
|
+
</div>
|
|
808
|
+
</div>
|
|
809
|
+
))}
|
|
810
|
+
</div>
|
|
811
|
+
),
|
|
812
|
+
parameters: {
|
|
813
|
+
docs: {
|
|
814
|
+
description: {
|
|
815
|
+
story:
|
|
816
|
+
"Align items utilities control cross axis alignment: `.items-start`, `.items-center`, `.items-end`, `.items-stretch`, `.items-baseline`",
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
},
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Gap utilities
|
|
824
|
+
*/
|
|
825
|
+
export const GapUtilities: Story = {
|
|
826
|
+
render: () => (
|
|
827
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
828
|
+
{[
|
|
829
|
+
{ class: "gap-0", label: "No Gap (gap-0)" },
|
|
830
|
+
{ class: "gap-xs", label: "Extra Small (gap-xs)" },
|
|
831
|
+
{ class: "gap-sm", label: "Small (gap-sm)" },
|
|
832
|
+
{ class: "gap-md", label: "Medium (gap-md)" },
|
|
833
|
+
{ class: "gap-lg", label: "Large (gap-lg)" },
|
|
834
|
+
{ class: "gap-xl", label: "Extra Large (gap-xl)" },
|
|
835
|
+
].map(({ class: className, label }) => (
|
|
836
|
+
<div key={className}>
|
|
837
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>{label}</h4>
|
|
838
|
+
<div
|
|
839
|
+
className={`flex ${className}`}
|
|
840
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
841
|
+
>
|
|
842
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
843
|
+
Item 1
|
|
844
|
+
</div>
|
|
845
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
846
|
+
Item 2
|
|
847
|
+
</div>
|
|
848
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
849
|
+
Item 3
|
|
850
|
+
</div>
|
|
851
|
+
</div>
|
|
852
|
+
</div>
|
|
853
|
+
))}
|
|
854
|
+
</div>
|
|
855
|
+
),
|
|
856
|
+
parameters: {
|
|
857
|
+
docs: {
|
|
858
|
+
description: {
|
|
859
|
+
story:
|
|
860
|
+
"Gap utilities use fluid spacing with `clamp()`. Available: `.gap-0`, `.gap-xs`, `.gap-sm`, `.gap-md`, `.gap-lg`, `.gap-xl`. Also supports `.row-gap-*` and `.col-gap-*` for independent control.",
|
|
861
|
+
},
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Flex item sizing
|
|
868
|
+
*/
|
|
869
|
+
export const FlexSizing: Story = {
|
|
870
|
+
render: () => (
|
|
871
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
872
|
+
<div>
|
|
873
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
874
|
+
flex-1 (Equal width items)
|
|
875
|
+
</h4>
|
|
876
|
+
<div
|
|
877
|
+
className="flex gap-sm"
|
|
878
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
879
|
+
>
|
|
880
|
+
<div
|
|
881
|
+
className="flex-1"
|
|
882
|
+
style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}
|
|
883
|
+
>
|
|
884
|
+
flex-1
|
|
885
|
+
</div>
|
|
886
|
+
<div
|
|
887
|
+
className="flex-1"
|
|
888
|
+
style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}
|
|
889
|
+
>
|
|
890
|
+
flex-1
|
|
891
|
+
</div>
|
|
892
|
+
<div
|
|
893
|
+
className="flex-1"
|
|
894
|
+
style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}
|
|
895
|
+
>
|
|
896
|
+
flex-1
|
|
897
|
+
</div>
|
|
898
|
+
</div>
|
|
899
|
+
</div>
|
|
900
|
+
|
|
901
|
+
<div>
|
|
902
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
903
|
+
flex-auto (Content-based sizing)
|
|
904
|
+
</h4>
|
|
905
|
+
<div
|
|
906
|
+
className="flex gap-sm"
|
|
907
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
908
|
+
>
|
|
909
|
+
<div
|
|
910
|
+
className="flex-auto"
|
|
911
|
+
style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}
|
|
912
|
+
>
|
|
913
|
+
Short
|
|
914
|
+
</div>
|
|
915
|
+
<div
|
|
916
|
+
className="flex-auto"
|
|
917
|
+
style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}
|
|
918
|
+
>
|
|
919
|
+
Medium content here
|
|
920
|
+
</div>
|
|
921
|
+
<div
|
|
922
|
+
className="flex-auto"
|
|
923
|
+
style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}
|
|
924
|
+
>
|
|
925
|
+
Longer content that takes more space
|
|
926
|
+
</div>
|
|
927
|
+
</div>
|
|
928
|
+
</div>
|
|
929
|
+
|
|
930
|
+
<div>
|
|
931
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
932
|
+
flex-none (Fixed width)
|
|
933
|
+
</h4>
|
|
934
|
+
<div
|
|
935
|
+
className="flex gap-sm"
|
|
936
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
937
|
+
>
|
|
938
|
+
<div
|
|
939
|
+
className="flex-none"
|
|
940
|
+
style={{
|
|
941
|
+
padding: "0.75rem",
|
|
942
|
+
background: "#e3f2fd",
|
|
943
|
+
borderRadius: "0.25rem",
|
|
944
|
+
width: "8rem",
|
|
945
|
+
}}
|
|
946
|
+
>
|
|
947
|
+
Fixed 8rem
|
|
948
|
+
</div>
|
|
949
|
+
<div
|
|
950
|
+
className="flex-1"
|
|
951
|
+
style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}
|
|
952
|
+
>
|
|
953
|
+
flex-1 fills remaining
|
|
954
|
+
</div>
|
|
955
|
+
</div>
|
|
956
|
+
</div>
|
|
957
|
+
</div>
|
|
958
|
+
),
|
|
959
|
+
parameters: {
|
|
960
|
+
docs: {
|
|
961
|
+
description: {
|
|
962
|
+
story:
|
|
963
|
+
"Flex item sizing: `.flex-1` (equal distribution), `.flex-auto` (content-based), `.flex-initial` (default), `.flex-none` (no grow/shrink)",
|
|
964
|
+
},
|
|
965
|
+
},
|
|
966
|
+
},
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
/**
|
|
970
|
+
* Common patterns
|
|
971
|
+
*/
|
|
972
|
+
export const CommonPatterns: Story = {
|
|
973
|
+
render: () => (
|
|
974
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
975
|
+
<div>
|
|
976
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
977
|
+
flex-center (Center both axes)
|
|
978
|
+
</h4>
|
|
979
|
+
<div
|
|
980
|
+
className="flex-center"
|
|
981
|
+
style={{
|
|
982
|
+
padding: "2rem",
|
|
983
|
+
border: "2px dashed #ccc",
|
|
984
|
+
borderRadius: "0.5rem",
|
|
985
|
+
minHeight: "8rem",
|
|
986
|
+
}}
|
|
987
|
+
>
|
|
988
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
989
|
+
Centered Content
|
|
990
|
+
</div>
|
|
991
|
+
</div>
|
|
992
|
+
</div>
|
|
993
|
+
|
|
994
|
+
<div>
|
|
995
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
996
|
+
flex-between (Space between with center alignment)
|
|
997
|
+
</h4>
|
|
998
|
+
<div
|
|
999
|
+
className="flex-between"
|
|
1000
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1001
|
+
>
|
|
1002
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
1003
|
+
Left
|
|
1004
|
+
</div>
|
|
1005
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
1006
|
+
Right
|
|
1007
|
+
</div>
|
|
1008
|
+
</div>
|
|
1009
|
+
</div>
|
|
1010
|
+
|
|
1011
|
+
<div>
|
|
1012
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
1013
|
+
flex-stack (Vertical stack, becomes row on md+)
|
|
1014
|
+
</h4>
|
|
1015
|
+
<div
|
|
1016
|
+
className="flex-stack"
|
|
1017
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1018
|
+
>
|
|
1019
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
1020
|
+
Item 1
|
|
1021
|
+
</div>
|
|
1022
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
1023
|
+
Item 2
|
|
1024
|
+
</div>
|
|
1025
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
1026
|
+
Item 3
|
|
1027
|
+
</div>
|
|
1028
|
+
</div>
|
|
1029
|
+
<p style={{ marginTop: "0.5rem", fontSize: "0.875rem", color: "#666" }}>
|
|
1030
|
+
Resize viewport to see responsive behavior (column → row at 48rem)
|
|
1031
|
+
</p>
|
|
1032
|
+
</div>
|
|
1033
|
+
|
|
1034
|
+
<div>
|
|
1035
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>
|
|
1036
|
+
flex-spread (Equal width children)
|
|
1037
|
+
</h4>
|
|
1038
|
+
<div
|
|
1039
|
+
className="flex-spread gap-sm"
|
|
1040
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1041
|
+
>
|
|
1042
|
+
<div style={{ padding: "0.75rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
1043
|
+
A
|
|
1044
|
+
</div>
|
|
1045
|
+
<div style={{ padding: "0.75rem", background: "#bbdefb", borderRadius: "0.25rem" }}>
|
|
1046
|
+
B
|
|
1047
|
+
</div>
|
|
1048
|
+
<div style={{ padding: "0.75rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
1049
|
+
C
|
|
1050
|
+
</div>
|
|
1051
|
+
</div>
|
|
1052
|
+
</div>
|
|
1053
|
+
</div>
|
|
1054
|
+
),
|
|
1055
|
+
parameters: {
|
|
1056
|
+
docs: {
|
|
1057
|
+
description: {
|
|
1058
|
+
story:
|
|
1059
|
+
"Common flexbox patterns: `.flex-center`, `.flex-between`, `.flex-around`, `.flex-stack`, `.flex-spread`",
|
|
1060
|
+
},
|
|
1061
|
+
},
|
|
1062
|
+
},
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* Responsive utilities demonstration
|
|
1067
|
+
*/
|
|
1068
|
+
export const ResponsiveUtilities: Story = {
|
|
1069
|
+
render: () => (
|
|
1070
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem" }}>
|
|
1071
|
+
<div>
|
|
1072
|
+
<h3 style={{ marginBottom: "1rem" }}>Responsive Direction</h3>
|
|
1073
|
+
<p style={{ marginBottom: "0.5rem", fontSize: "0.875rem", color: "#666" }}>
|
|
1074
|
+
Column on mobile, row on medium+ screens
|
|
1075
|
+
</p>
|
|
1076
|
+
<div
|
|
1077
|
+
className="flex flex-col md:flex-row gap-md"
|
|
1078
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1079
|
+
>
|
|
1080
|
+
<div
|
|
1081
|
+
className="flex-1"
|
|
1082
|
+
style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}
|
|
1083
|
+
>
|
|
1084
|
+
Column 1
|
|
1085
|
+
</div>
|
|
1086
|
+
<div
|
|
1087
|
+
className="flex-1"
|
|
1088
|
+
style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}
|
|
1089
|
+
>
|
|
1090
|
+
Column 2
|
|
1091
|
+
</div>
|
|
1092
|
+
<div
|
|
1093
|
+
className="flex-1"
|
|
1094
|
+
style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}
|
|
1095
|
+
>
|
|
1096
|
+
Column 3
|
|
1097
|
+
</div>
|
|
1098
|
+
</div>
|
|
1099
|
+
</div>
|
|
1100
|
+
|
|
1101
|
+
<div>
|
|
1102
|
+
<h3 style={{ marginBottom: "1rem" }}>Responsive Gaps</h3>
|
|
1103
|
+
<p style={{ marginBottom: "0.5rem", fontSize: "0.875rem", color: "#666" }}>
|
|
1104
|
+
Small gap on mobile, large gap on medium+ screens
|
|
1105
|
+
</p>
|
|
1106
|
+
<div
|
|
1107
|
+
className="flex gap-sm md:gap-lg"
|
|
1108
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1109
|
+
>
|
|
1110
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>1</div>
|
|
1111
|
+
<div style={{ padding: "1rem", background: "#bbdefb", borderRadius: "0.25rem" }}>2</div>
|
|
1112
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>3</div>
|
|
1113
|
+
</div>
|
|
1114
|
+
</div>
|
|
1115
|
+
|
|
1116
|
+
<div>
|
|
1117
|
+
<h3 style={{ marginBottom: "1rem" }}>Responsive Justification</h3>
|
|
1118
|
+
<p style={{ marginBottom: "0.5rem", fontSize: "0.875rem", color: "#666" }}>
|
|
1119
|
+
Start alignment on mobile, space between on large+ screens
|
|
1120
|
+
</p>
|
|
1121
|
+
<div
|
|
1122
|
+
className="flex justify-start lg:justify-between"
|
|
1123
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1124
|
+
>
|
|
1125
|
+
<div style={{ padding: "1rem", background: "#e3f2fd", borderRadius: "0.25rem" }}>
|
|
1126
|
+
Left
|
|
1127
|
+
</div>
|
|
1128
|
+
<div style={{ padding: "1rem", background: "#90caf9", borderRadius: "0.25rem" }}>
|
|
1129
|
+
Right
|
|
1130
|
+
</div>
|
|
1131
|
+
</div>
|
|
1132
|
+
</div>
|
|
1133
|
+
|
|
1134
|
+
<div
|
|
1135
|
+
style={{
|
|
1136
|
+
padding: "1rem",
|
|
1137
|
+
background: "#fff3cd",
|
|
1138
|
+
border: "1px solid #ffc107",
|
|
1139
|
+
borderRadius: "0.5rem",
|
|
1140
|
+
marginTop: "1rem",
|
|
1141
|
+
}}
|
|
1142
|
+
>
|
|
1143
|
+
<strong>💡 Tip:</strong> Resize your browser window or use Storybook's viewport
|
|
1144
|
+
toolbar to see responsive behavior at different breakpoints (sm: 480px, md: 768px, lg:
|
|
1145
|
+
992px, xl: 1280px).
|
|
1146
|
+
</div>
|
|
1147
|
+
</div>
|
|
1148
|
+
),
|
|
1149
|
+
parameters: {
|
|
1150
|
+
docs: {
|
|
1151
|
+
description: {
|
|
1152
|
+
story: `Responsive modifiers allow utilities to activate at specific breakpoints.
|
|
1153
|
+
|
|
1154
|
+
**Format:** \`{breakpoint}:{utility}\`
|
|
1155
|
+
|
|
1156
|
+
**Examples:**
|
|
1157
|
+
- \`sm:flex-row\` - Row direction on screens ≥ 480px
|
|
1158
|
+
- \`md:justify-center\` - Center justify on screens ≥ 768px
|
|
1159
|
+
- \`lg:gap-xl\` - Extra large gap on screens ≥ 992px
|
|
1160
|
+
- \`xl:items-end\` - End alignment on screens ≥ 1280px
|
|
1161
|
+
|
|
1162
|
+
All base utilities support responsive modifiers: direction, wrap, justify, align, gap, and flex sizing.`,
|
|
1163
|
+
},
|
|
1164
|
+
},
|
|
1165
|
+
chromatic: {
|
|
1166
|
+
viewports: [375, 480, 768, 992, 1280],
|
|
1167
|
+
},
|
|
1168
|
+
},
|
|
1169
|
+
};
|
|
1170
|
+
|
|
1171
|
+
/**
|
|
1172
|
+
* Wrapping behavior
|
|
1173
|
+
*/
|
|
1174
|
+
export const FlexWrap: Story = {
|
|
1175
|
+
render: () => (
|
|
1176
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "1.5rem" }}>
|
|
1177
|
+
<div>
|
|
1178
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>flex-wrap (default)</h4>
|
|
1179
|
+
<div
|
|
1180
|
+
className="flex flex-wrap gap-sm"
|
|
1181
|
+
style={{ padding: "1rem", border: "2px dashed #ccc", borderRadius: "0.5rem" }}
|
|
1182
|
+
>
|
|
1183
|
+
{Array.from({ length: 12 }, (_, i) => (
|
|
1184
|
+
<div
|
|
1185
|
+
key={i}
|
|
1186
|
+
style={{
|
|
1187
|
+
padding: "0.75rem 1.5rem",
|
|
1188
|
+
background: "#e3f2fd",
|
|
1189
|
+
borderRadius: "0.25rem",
|
|
1190
|
+
}}
|
|
1191
|
+
>
|
|
1192
|
+
Item {i + 1}
|
|
1193
|
+
</div>
|
|
1194
|
+
))}
|
|
1195
|
+
</div>
|
|
1196
|
+
</div>
|
|
1197
|
+
|
|
1198
|
+
<div>
|
|
1199
|
+
<h4 style={{ marginBottom: "0.5rem", fontSize: "0.875rem" }}>flex-nowrap</h4>
|
|
1200
|
+
<div
|
|
1201
|
+
className="flex flex-nowrap gap-sm"
|
|
1202
|
+
style={{
|
|
1203
|
+
padding: "1rem",
|
|
1204
|
+
border: "2px dashed #ccc",
|
|
1205
|
+
borderRadius: "0.5rem",
|
|
1206
|
+
overflowX: "auto",
|
|
1207
|
+
}}
|
|
1208
|
+
>
|
|
1209
|
+
{Array.from({ length: 12 }, (_, i) => (
|
|
1210
|
+
<div
|
|
1211
|
+
key={i}
|
|
1212
|
+
className="flex-shrink-0"
|
|
1213
|
+
style={{
|
|
1214
|
+
padding: "0.75rem 1.5rem",
|
|
1215
|
+
background: "#bbdefb",
|
|
1216
|
+
borderRadius: "0.25rem",
|
|
1217
|
+
}}
|
|
1218
|
+
>
|
|
1219
|
+
Item {i + 1}
|
|
1220
|
+
</div>
|
|
1221
|
+
))}
|
|
1222
|
+
</div>
|
|
1223
|
+
</div>
|
|
1224
|
+
</div>
|
|
1225
|
+
),
|
|
1226
|
+
parameters: {
|
|
1227
|
+
docs: {
|
|
1228
|
+
description: {
|
|
1229
|
+
story: "Flex wrap utilities: `.flex-wrap`, `.flex-nowrap`, `.flex-wrap-reverse`",
|
|
1230
|
+
},
|
|
1231
|
+
},
|
|
1232
|
+
},
|
|
1233
|
+
};
|