@fpkit/acss 3.1.0 → 3.2.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-2NRIP6RB.cjs → chunk-2C3YLBWP.cjs} +3 -3
- package/libs/{chunk-NWJDAHP6.cjs → chunk-2GJHKWEK.cjs} +3 -3
- package/libs/{chunk-FVROL3V5.js → chunk-2JCDEC32.js} +3 -3
- package/libs/{chunk-IRLFZ3OL.js → chunk-3XJC4XUG.js} +2 -2
- package/libs/{chunk-23ANBDCR.js → chunk-4I5MF54P.js} +3 -3
- package/libs/chunk-4I5MF54P.js.map +1 -0
- package/libs/chunk-5CJPTDK3.cjs +31 -0
- package/libs/chunk-5CJPTDK3.cjs.map +1 -0
- package/libs/{chunk-E4OSROCA.cjs → chunk-5QSNJQVH.cjs} +3 -3
- package/libs/{chunk-O3JIHC5M.cjs → chunk-6BUJZ4DJ.cjs} +3 -3
- package/libs/{chunk-WXBFBWYF.cjs → chunk-AFINOD2L.cjs} +3 -3
- package/libs/{chunk-HRRHPLER.js → chunk-AWZLSWDO.js} +2 -2
- package/libs/chunk-DDSXKOUB.js +7 -0
- package/libs/chunk-DDSXKOUB.js.map +1 -0
- package/libs/{chunk-CWRNJA4P.js → chunk-DIJBIOFE.js} +3 -3
- package/libs/chunk-EJ6KYBFE.cjs +13 -0
- package/libs/chunk-EJ6KYBFE.cjs.map +1 -0
- package/libs/{chunk-GUJSMQ3V.cjs → chunk-EKJYOCLY.cjs} +3 -3
- package/libs/{chunk-X5RKCLDC.cjs → chunk-F64GE6RG.cjs} +4 -4
- package/libs/chunk-FMIM3332.js +8 -0
- package/libs/chunk-FMIM3332.js.map +1 -0
- package/libs/{chunk-5RAWNUVD.js → chunk-IBUTNPTQ.js} +2 -2
- package/libs/chunk-IWP4VJEP.cjs +18 -0
- package/libs/chunk-IWP4VJEP.cjs.map +1 -0
- package/libs/{chunk-ZFJ4U45S.js → chunk-KDMX3FAW.js} +2 -2
- package/libs/{chunk-DYFAUAB7.cjs → chunk-LXODKKA3.cjs} +4 -4
- package/libs/chunk-M7JLT62Q.js +9 -0
- package/libs/chunk-M7JLT62Q.js.map +1 -0
- package/libs/{chunk-IQ76HGVP.js → chunk-MBWI67UT.js} +2 -2
- package/libs/{chunk-O5XAJ7BY.cjs → chunk-NCGVF2QS.cjs} +4 -4
- package/libs/{chunk-W2UIN7EV.cjs → chunk-NPWHQVYB.cjs} +3 -3
- package/libs/{chunk-G55UJ53G.cjs → chunk-NZVSXRTB.cjs} +3 -3
- package/libs/chunk-NZVSXRTB.cjs.map +1 -0
- package/libs/{chunk-43TK2ICH.js → chunk-PMWL5XZ4.js} +3 -3
- package/libs/{chunk-KVKQLRJG.js → chunk-TF3GQKOY.js} +2 -2
- package/libs/chunk-TNEJXNZA.cjs +22 -0
- package/libs/chunk-TNEJXNZA.cjs.map +1 -0
- package/libs/{chunk-IEB64SWY.js → chunk-U5VA34SU.js} +2 -2
- package/libs/chunk-UGMP72J2.js +8 -0
- package/libs/chunk-UGMP72J2.js.map +1 -0
- package/libs/{chunk-MGPWZRBX.cjs → chunk-URBGDUFN.cjs} +6 -6
- package/libs/{chunk-QKHPHMG2.js → chunk-ZF6Y7W57.js} +5 -5
- package/libs/component-props-50e69975.d.ts +66 -0
- package/libs/components/box/box.css +1 -0
- package/libs/components/box/box.css.map +1 -0
- package/libs/components/box/box.min.css +3 -0
- package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
- package/libs/components/breadcrumbs/breadcrumb.js +3 -3
- package/libs/components/button.cjs +4 -4
- package/libs/components/button.d.cts +10 -3
- package/libs/components/button.d.ts +10 -3
- package/libs/components/button.js +2 -2
- package/libs/components/card.cjs +7 -7
- package/libs/components/card.d.cts +13 -85
- package/libs/components/card.d.ts +13 -85
- package/libs/components/card.js +2 -2
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/cluster/cluster.css +1 -0
- package/libs/components/cluster/cluster.css.map +1 -0
- package/libs/components/cluster/cluster.min.css +3 -0
- package/libs/components/dialog/dialog.cjs +7 -7
- package/libs/components/dialog/dialog.js +5 -5
- package/libs/components/form/fields.cjs +4 -4
- package/libs/components/form/fields.js +2 -2
- package/libs/components/form/textarea.cjs +4 -4
- package/libs/components/form/textarea.js +2 -2
- package/libs/components/grid/grid.css +1 -0
- package/libs/components/grid/grid.css.map +1 -0
- package/libs/components/grid/grid.min.css +3 -0
- package/libs/components/heading/heading.cjs +3 -3
- package/libs/components/heading/heading.js +2 -2
- package/libs/components/icons/icon.cjs +4 -4
- package/libs/components/icons/icon.d.cts +2 -2
- package/libs/components/icons/icon.d.ts +2 -2
- package/libs/components/icons/icon.js +2 -2
- package/libs/components/link/link.cjs +6 -6
- package/libs/components/link/link.js +2 -2
- package/libs/components/list/list.cjs +5 -5
- package/libs/components/list/list.js +2 -2
- package/libs/components/modal.cjs +4 -4
- package/libs/components/modal.d.cts +1 -1
- package/libs/components/modal.d.ts +1 -1
- package/libs/components/modal.js +3 -3
- package/libs/components/nav/nav.cjs +7 -7
- package/libs/components/nav/nav.js +3 -3
- package/libs/components/popover/popover.cjs +4 -4
- package/libs/components/popover/popover.d.cts +1 -1
- package/libs/components/popover/popover.d.ts +1 -1
- package/libs/components/popover/popover.js +1 -1
- package/libs/components/stack/stack.css +1 -0
- package/libs/components/stack/stack.css.map +1 -0
- package/libs/components/stack/stack.min.css +3 -0
- package/libs/components/tables/table.cjs +4 -4
- package/libs/components/tables/table.d.cts +2 -2
- package/libs/components/tables/table.d.ts +2 -2
- package/libs/components/tables/table.js +1 -1
- package/libs/components/text/text.cjs +5 -5
- package/libs/components/text/text.js +2 -2
- package/libs/hooks.cjs +4 -4
- package/libs/hooks.js +3 -3
- package/libs/{icons-287fce3a.d.ts → icons-df8e744f.d.ts} +1 -1
- package/libs/icons.cjs +3 -3
- package/libs/icons.d.cts +2 -2
- package/libs/icons.d.ts +2 -2
- package/libs/icons.js +2 -2
- package/libs/index.cjs +74 -73
- 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 +925 -6
- package/libs/index.d.ts +925 -6
- package/libs/index.js +30 -30
- package/libs/index.js.map +1 -1
- package/package.json +2 -2
- package/src/App.tsx +1 -3
- package/src/components/alert/STYLES.mdx +790 -0
- package/src/components/badge/STYLES.mdx +610 -0
- package/src/components/box/README.mdx +401 -0
- package/src/components/box/STYLES.mdx +360 -0
- package/src/components/box/box.scss +245 -0
- package/src/components/box/box.stories.tsx +395 -0
- package/src/components/box/box.test.tsx +425 -0
- package/src/components/box/box.tsx +170 -0
- package/src/components/box/box.types.ts +166 -0
- package/src/components/breadcrumbs/STYLES.mdx +99 -0
- package/src/components/breadcrumbs/bc-item.tsx +0 -1
- package/src/components/buttons/STYLES.mdx +766 -0
- package/src/components/cards/STYLES.mdx +835 -0
- package/src/components/cards/card.scss +29 -21
- package/src/components/cards/card.tsx +13 -3
- package/src/components/cards/card.types.ts +13 -0
- package/src/components/cluster/README.mdx +595 -0
- package/src/components/cluster/STYLES.mdx +626 -0
- package/src/components/cluster/cluster.scss +86 -0
- package/src/components/cluster/cluster.stories.tsx +385 -0
- package/src/components/cluster/cluster.test.tsx +655 -0
- package/src/components/cluster/cluster.tsx +94 -0
- package/src/components/cluster/cluster.types.ts +75 -0
- package/src/components/details/STYLES.mdx +445 -0
- package/src/components/dialog/STYLES.mdx +888 -0
- package/src/components/flexbox/STYLES.mdx +857 -0
- package/src/components/flexbox/flex.stories.tsx +842 -141
- package/src/components/flexbox/flex.types.ts +25 -6
- package/src/components/form/STYLES.mdx +821 -0
- package/src/components/grid/README.mdx +709 -0
- package/src/components/grid/STYLES.mdx +785 -0
- package/src/components/grid/grid.scss +287 -0
- package/src/components/grid/grid.stories.tsx +486 -0
- package/src/components/grid/grid.test.tsx +981 -0
- package/src/components/grid/grid.tsx +222 -0
- package/src/components/grid/grid.types.ts +344 -0
- package/src/components/icons/STYLES.mdx +56 -0
- package/src/components/icons/components/arrow-right.tsx +0 -5
- package/src/components/images/STYLES.mdx +75 -0
- package/src/components/kit.tsx +8 -4
- package/src/components/layout/STYLES.mdx +556 -0
- package/src/components/link/STYLES.mdx +75 -0
- package/src/components/list/STYLES.mdx +631 -0
- package/src/components/nav/STYLES.mdx +460 -0
- package/src/components/popover/popover.tsx +1 -1
- package/src/components/progress/STYLES.mdx +64 -0
- package/src/components/stack/README.mdx +400 -0
- package/src/components/stack/STYLES.mdx +414 -0
- package/src/components/stack/stack.scss +109 -0
- package/src/components/stack/stack.stories.tsx +559 -0
- package/src/components/stack/stack.test.tsx +426 -0
- package/src/components/stack/stack.tsx +141 -0
- package/src/components/stack/stack.types.ts +133 -0
- package/src/components/tables/table-elements.tsx +1 -1
- package/src/components/tables/table.tsx +2 -2
- package/src/components/tag/STYLES.mdx +105 -0
- package/src/components/text-to-speech/STYLES.mdx +80 -0
- package/src/components/text-to-speech/TextToSpeech.tsx +0 -4
- package/src/components/text-to-speech/useTextToSpeech.tsx +2 -6
- package/src/components/ui.tsx +3 -3
- package/src/decorators/instructions.tsx +22 -18
- package/src/hooks/popover/popover.tsx +1 -1
- package/src/index.scss +5 -1
- package/src/index.ts +305 -12
- package/src/sass/GLOBALS-STYLES.md +631 -0
- package/src/sass/_globals.scss +45 -24
- package/src/styles/box/box.css +220 -0
- package/src/styles/box/box.css.map +1 -0
- package/src/styles/cards/card.css +22 -17
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/cluster/cluster.css +71 -0
- package/src/styles/cluster/cluster.css.map +1 -0
- package/src/styles/grid/grid.css +238 -0
- package/src/styles/grid/grid.css.map +1 -0
- package/src/styles/index.css +667 -49
- package/src/styles/index.css.map +1 -1
- package/src/styles/stack/stack.css +86 -0
- package/src/styles/stack/stack.css.map +1 -0
- package/src/types/component-props.ts +42 -13
- package/src/types/layout-primitives.ts +48 -0
- package/src/types/shared.ts +10 -26
- package/libs/chunk-23ANBDCR.js.map +0 -1
- package/libs/chunk-5QD3DWFI.js +0 -9
- package/libs/chunk-5QD3DWFI.js.map +0 -1
- package/libs/chunk-6WTC4JXH.cjs +0 -31
- package/libs/chunk-6WTC4JXH.cjs.map +0 -1
- package/libs/chunk-ENTCUJ3A.cjs +0 -13
- package/libs/chunk-ENTCUJ3A.cjs.map +0 -1
- package/libs/chunk-G55UJ53G.cjs.map +0 -1
- package/libs/chunk-HHLNOC5T.js +0 -7
- package/libs/chunk-HHLNOC5T.js.map +0 -1
- package/libs/chunk-KK47SYZI.js +0 -8
- package/libs/chunk-KK47SYZI.js.map +0 -1
- package/libs/chunk-US2I5GI7.cjs +0 -22
- package/libs/chunk-US2I5GI7.cjs.map +0 -1
- package/libs/chunk-W5TKWBFC.cjs +0 -18
- package/libs/chunk-W5TKWBFC.cjs.map +0 -1
- package/libs/chunk-Y2PFDELK.js +0 -8
- package/libs/chunk-Y2PFDELK.js.map +0 -1
- package/libs/component-props-67d978a2.d.ts +0 -38
- /package/libs/{chunk-2NRIP6RB.cjs.map → chunk-2C3YLBWP.cjs.map} +0 -0
- /package/libs/{chunk-NWJDAHP6.cjs.map → chunk-2GJHKWEK.cjs.map} +0 -0
- /package/libs/{chunk-FVROL3V5.js.map → chunk-2JCDEC32.js.map} +0 -0
- /package/libs/{chunk-IRLFZ3OL.js.map → chunk-3XJC4XUG.js.map} +0 -0
- /package/libs/{chunk-E4OSROCA.cjs.map → chunk-5QSNJQVH.cjs.map} +0 -0
- /package/libs/{chunk-O3JIHC5M.cjs.map → chunk-6BUJZ4DJ.cjs.map} +0 -0
- /package/libs/{chunk-WXBFBWYF.cjs.map → chunk-AFINOD2L.cjs.map} +0 -0
- /package/libs/{chunk-HRRHPLER.js.map → chunk-AWZLSWDO.js.map} +0 -0
- /package/libs/{chunk-CWRNJA4P.js.map → chunk-DIJBIOFE.js.map} +0 -0
- /package/libs/{chunk-GUJSMQ3V.cjs.map → chunk-EKJYOCLY.cjs.map} +0 -0
- /package/libs/{chunk-X5RKCLDC.cjs.map → chunk-F64GE6RG.cjs.map} +0 -0
- /package/libs/{chunk-5RAWNUVD.js.map → chunk-IBUTNPTQ.js.map} +0 -0
- /package/libs/{chunk-ZFJ4U45S.js.map → chunk-KDMX3FAW.js.map} +0 -0
- /package/libs/{chunk-DYFAUAB7.cjs.map → chunk-LXODKKA3.cjs.map} +0 -0
- /package/libs/{chunk-IQ76HGVP.js.map → chunk-MBWI67UT.js.map} +0 -0
- /package/libs/{chunk-O5XAJ7BY.cjs.map → chunk-NCGVF2QS.cjs.map} +0 -0
- /package/libs/{chunk-W2UIN7EV.cjs.map → chunk-NPWHQVYB.cjs.map} +0 -0
- /package/libs/{chunk-43TK2ICH.js.map → chunk-PMWL5XZ4.js.map} +0 -0
- /package/libs/{chunk-KVKQLRJG.js.map → chunk-TF3GQKOY.js.map} +0 -0
- /package/libs/{chunk-IEB64SWY.js.map → chunk-U5VA34SU.js.map} +0 -0
- /package/libs/{chunk-MGPWZRBX.cjs.map → chunk-URBGDUFN.cjs.map} +0 -0
- /package/libs/{chunk-QKHPHMG2.js.map → chunk-ZF6Y7W57.js.map} +0 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { Stack } from "./stack";
|
|
4
|
+
|
|
5
|
+
describe("Stack", () => {
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Rendering Tests
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
it("renders with default props", () => {
|
|
11
|
+
render(<Stack>Content</Stack>);
|
|
12
|
+
expect(screen.getByText("Content")).toBeInTheDocument();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("renders children correctly", () => {
|
|
16
|
+
render(
|
|
17
|
+
<Stack>
|
|
18
|
+
<span>Child 1</span>
|
|
19
|
+
<span>Child 2</span>
|
|
20
|
+
</Stack>
|
|
21
|
+
);
|
|
22
|
+
expect(screen.getByText("Child 1")).toBeInTheDocument();
|
|
23
|
+
expect(screen.getByText("Child 2")).toBeInTheDocument();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("renders as div by default", () => {
|
|
27
|
+
render(<Stack data-testid="stack">Content</Stack>);
|
|
28
|
+
const stack = screen.getByTestId("stack");
|
|
29
|
+
expect(stack.tagName).toBe("DIV");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("always has base stack class", () => {
|
|
33
|
+
render(<Stack data-testid="stack">Content</Stack>);
|
|
34
|
+
const stack = screen.getByTestId("stack");
|
|
35
|
+
expect(stack).toHaveClass("stack");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Polymorphic Rendering Tests
|
|
40
|
+
// ============================================================================
|
|
41
|
+
|
|
42
|
+
it("renders as different elements via as prop", () => {
|
|
43
|
+
render(<Stack as="section" data-testid="stack">Content</Stack>);
|
|
44
|
+
const stack = screen.getByTestId("stack");
|
|
45
|
+
expect(stack.tagName).toBe("SECTION");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("renders as article", () => {
|
|
49
|
+
render(<Stack as="article" data-testid="stack">Content</Stack>);
|
|
50
|
+
const stack = screen.getByTestId("stack");
|
|
51
|
+
expect(stack.tagName).toBe("ARTICLE");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("renders as nav", () => {
|
|
55
|
+
render(<Stack as="nav" data-testid="stack">Content</Stack>);
|
|
56
|
+
const stack = screen.getByTestId("stack");
|
|
57
|
+
expect(stack.tagName).toBe("NAV");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("renders as ul", () => {
|
|
61
|
+
render(<Stack as="ul" data-testid="stack">Content</Stack>);
|
|
62
|
+
const stack = screen.getByTestId("stack");
|
|
63
|
+
expect(stack.tagName).toBe("UL");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("renders as ol", () => {
|
|
67
|
+
render(<Stack as="ol" data-testid="stack">Content</Stack>);
|
|
68
|
+
const stack = screen.getByTestId("stack");
|
|
69
|
+
expect(stack.tagName).toBe("OL");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Direction Class Tests
|
|
74
|
+
// ============================================================================
|
|
75
|
+
|
|
76
|
+
it("applies vertical direction class by default", () => {
|
|
77
|
+
render(<Stack data-testid="stack">Content</Stack>);
|
|
78
|
+
const stack = screen.getByTestId("stack");
|
|
79
|
+
expect(stack).toHaveClass("stack-vertical");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("applies vertical direction class explicitly", () => {
|
|
83
|
+
render(<Stack direction="vertical" data-testid="stack">Content</Stack>);
|
|
84
|
+
const stack = screen.getByTestId("stack");
|
|
85
|
+
expect(stack).toHaveClass("stack-vertical");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("applies horizontal direction class", () => {
|
|
89
|
+
render(<Stack direction="horizontal" data-testid="stack">Content</Stack>);
|
|
90
|
+
const stack = screen.getByTestId("stack");
|
|
91
|
+
expect(stack).toHaveClass("stack-horizontal");
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Gap Class Tests
|
|
96
|
+
// ============================================================================
|
|
97
|
+
|
|
98
|
+
it("applies gap-0 class", () => {
|
|
99
|
+
render(<Stack gap="0" data-testid="stack">Content</Stack>);
|
|
100
|
+
const stack = screen.getByTestId("stack");
|
|
101
|
+
expect(stack).toHaveClass("stack-gap-0");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("applies gap-xs class", () => {
|
|
105
|
+
render(<Stack gap="xs" data-testid="stack">Content</Stack>);
|
|
106
|
+
const stack = screen.getByTestId("stack");
|
|
107
|
+
expect(stack).toHaveClass("stack-gap-xs");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("applies gap-sm class", () => {
|
|
111
|
+
render(<Stack gap="sm" data-testid="stack">Content</Stack>);
|
|
112
|
+
const stack = screen.getByTestId("stack");
|
|
113
|
+
expect(stack).toHaveClass("stack-gap-sm");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("applies gap-md class", () => {
|
|
117
|
+
render(<Stack gap="md" data-testid="stack">Content</Stack>);
|
|
118
|
+
const stack = screen.getByTestId("stack");
|
|
119
|
+
expect(stack).toHaveClass("stack-gap-md");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("applies gap-lg class", () => {
|
|
123
|
+
render(<Stack gap="lg" data-testid="stack">Content</Stack>);
|
|
124
|
+
const stack = screen.getByTestId("stack");
|
|
125
|
+
expect(stack).toHaveClass("stack-gap-lg");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("applies gap-xl class", () => {
|
|
129
|
+
render(<Stack gap="xl" data-testid="stack">Content</Stack>);
|
|
130
|
+
const stack = screen.getByTestId("stack");
|
|
131
|
+
expect(stack).toHaveClass("stack-gap-xl");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ============================================================================
|
|
135
|
+
// Align Class Tests (Cross-Axis)
|
|
136
|
+
// ============================================================================
|
|
137
|
+
|
|
138
|
+
it("applies align-start class", () => {
|
|
139
|
+
render(<Stack align="start" data-testid="stack">Content</Stack>);
|
|
140
|
+
const stack = screen.getByTestId("stack");
|
|
141
|
+
expect(stack).toHaveClass("stack-align-start");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("applies align-center class", () => {
|
|
145
|
+
render(<Stack align="center" data-testid="stack">Content</Stack>);
|
|
146
|
+
const stack = screen.getByTestId("stack");
|
|
147
|
+
expect(stack).toHaveClass("stack-align-center");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("applies align-end class", () => {
|
|
151
|
+
render(<Stack align="end" data-testid="stack">Content</Stack>);
|
|
152
|
+
const stack = screen.getByTestId("stack");
|
|
153
|
+
expect(stack).toHaveClass("stack-align-end");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("applies align-stretch class", () => {
|
|
157
|
+
render(<Stack align="stretch" data-testid="stack">Content</Stack>);
|
|
158
|
+
const stack = screen.getByTestId("stack");
|
|
159
|
+
expect(stack).toHaveClass("stack-align-stretch");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// ============================================================================
|
|
163
|
+
// Justify Class Tests (Main-Axis)
|
|
164
|
+
// ============================================================================
|
|
165
|
+
|
|
166
|
+
it("applies justify-start class", () => {
|
|
167
|
+
render(<Stack justify="start" data-testid="stack">Content</Stack>);
|
|
168
|
+
const stack = screen.getByTestId("stack");
|
|
169
|
+
expect(stack).toHaveClass("stack-justify-start");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("applies justify-center class", () => {
|
|
173
|
+
render(<Stack justify="center" data-testid="stack">Content</Stack>);
|
|
174
|
+
const stack = screen.getByTestId("stack");
|
|
175
|
+
expect(stack).toHaveClass("stack-justify-center");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it("applies justify-end class", () => {
|
|
179
|
+
render(<Stack justify="end" data-testid="stack">Content</Stack>);
|
|
180
|
+
const stack = screen.getByTestId("stack");
|
|
181
|
+
expect(stack).toHaveClass("stack-justify-end");
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("applies justify-between class", () => {
|
|
185
|
+
render(<Stack justify="between" data-testid="stack">Content</Stack>);
|
|
186
|
+
const stack = screen.getByTestId("stack");
|
|
187
|
+
expect(stack).toHaveClass("stack-justify-between");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// ============================================================================
|
|
191
|
+
// Wrap Class Tests
|
|
192
|
+
// ============================================================================
|
|
193
|
+
|
|
194
|
+
it("applies wrap class", () => {
|
|
195
|
+
render(<Stack wrap="wrap" data-testid="stack">Content</Stack>);
|
|
196
|
+
const stack = screen.getByTestId("stack");
|
|
197
|
+
expect(stack).toHaveClass("stack-wrap");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("applies nowrap class", () => {
|
|
201
|
+
render(<Stack wrap="nowrap" data-testid="stack">Content</Stack>);
|
|
202
|
+
const stack = screen.getByTestId("stack");
|
|
203
|
+
expect(stack).toHaveClass("stack-nowrap");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// ============================================================================
|
|
207
|
+
// Multiple Props Tests
|
|
208
|
+
// ============================================================================
|
|
209
|
+
|
|
210
|
+
it("applies multiple utility classes", () => {
|
|
211
|
+
render(
|
|
212
|
+
<Stack
|
|
213
|
+
direction="horizontal"
|
|
214
|
+
gap="lg"
|
|
215
|
+
align="center"
|
|
216
|
+
justify="between"
|
|
217
|
+
wrap="wrap"
|
|
218
|
+
data-testid="stack"
|
|
219
|
+
>
|
|
220
|
+
Content
|
|
221
|
+
</Stack>
|
|
222
|
+
);
|
|
223
|
+
const stack = screen.getByTestId("stack");
|
|
224
|
+
expect(stack).toHaveClass("stack");
|
|
225
|
+
expect(stack).toHaveClass("stack-horizontal");
|
|
226
|
+
expect(stack).toHaveClass("stack-gap-lg");
|
|
227
|
+
expect(stack).toHaveClass("stack-align-center");
|
|
228
|
+
expect(stack).toHaveClass("stack-justify-between");
|
|
229
|
+
expect(stack).toHaveClass("stack-wrap");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("combines vertical direction with other props", () => {
|
|
233
|
+
render(
|
|
234
|
+
<Stack
|
|
235
|
+
direction="vertical"
|
|
236
|
+
gap="md"
|
|
237
|
+
align="start"
|
|
238
|
+
justify="center"
|
|
239
|
+
data-testid="stack"
|
|
240
|
+
>
|
|
241
|
+
Content
|
|
242
|
+
</Stack>
|
|
243
|
+
);
|
|
244
|
+
const stack = screen.getByTestId("stack");
|
|
245
|
+
expect(stack).toHaveClass("stack-vertical");
|
|
246
|
+
expect(stack).toHaveClass("stack-gap-md");
|
|
247
|
+
expect(stack).toHaveClass("stack-align-start");
|
|
248
|
+
expect(stack).toHaveClass("stack-justify-center");
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// ============================================================================
|
|
252
|
+
// Custom Class Tests
|
|
253
|
+
// ============================================================================
|
|
254
|
+
|
|
255
|
+
it("merges custom className with utility classes", () => {
|
|
256
|
+
render(
|
|
257
|
+
<Stack gap="md" className="custom-class" data-testid="stack">
|
|
258
|
+
Content
|
|
259
|
+
</Stack>
|
|
260
|
+
);
|
|
261
|
+
const stack = screen.getByTestId("stack");
|
|
262
|
+
expect(stack).toHaveClass("stack");
|
|
263
|
+
expect(stack).toHaveClass("stack-vertical");
|
|
264
|
+
expect(stack).toHaveClass("stack-gap-md");
|
|
265
|
+
expect(stack).toHaveClass("custom-class");
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it("merges custom classes prop with utility classes", () => {
|
|
269
|
+
render(
|
|
270
|
+
<Stack gap="md" classes="legacy-class" data-testid="stack">
|
|
271
|
+
Content
|
|
272
|
+
</Stack>
|
|
273
|
+
);
|
|
274
|
+
const stack = screen.getByTestId("stack");
|
|
275
|
+
expect(stack).toHaveClass("stack");
|
|
276
|
+
expect(stack).toHaveClass("stack-gap-md");
|
|
277
|
+
expect(stack).toHaveClass("legacy-class");
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("merges both className and classes with utility classes", () => {
|
|
281
|
+
render(
|
|
282
|
+
<Stack
|
|
283
|
+
gap="md"
|
|
284
|
+
className="custom-class"
|
|
285
|
+
classes="legacy-class"
|
|
286
|
+
data-testid="stack"
|
|
287
|
+
>
|
|
288
|
+
Content
|
|
289
|
+
</Stack>
|
|
290
|
+
);
|
|
291
|
+
const stack = screen.getByTestId("stack");
|
|
292
|
+
expect(stack).toHaveClass("stack");
|
|
293
|
+
expect(stack).toHaveClass("stack-gap-md");
|
|
294
|
+
expect(stack).toHaveClass("custom-class");
|
|
295
|
+
expect(stack).toHaveClass("legacy-class");
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// ============================================================================
|
|
299
|
+
// Inline Styles Tests
|
|
300
|
+
// ============================================================================
|
|
301
|
+
|
|
302
|
+
it("applies custom styles", () => {
|
|
303
|
+
render(
|
|
304
|
+
<Stack
|
|
305
|
+
gap="md"
|
|
306
|
+
styles={{ backgroundColor: "red", color: "white" }}
|
|
307
|
+
data-testid="stack"
|
|
308
|
+
>
|
|
309
|
+
Content
|
|
310
|
+
</Stack>
|
|
311
|
+
);
|
|
312
|
+
const stack = screen.getByTestId("stack");
|
|
313
|
+
expect(stack).toHaveStyle({ backgroundColor: "rgb(255, 0, 0)" });
|
|
314
|
+
expect(stack).toHaveStyle({ color: "rgb(255, 255, 255)" });
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it("accepts CSS custom properties in styles", () => {
|
|
318
|
+
render(
|
|
319
|
+
<Stack
|
|
320
|
+
gap="md"
|
|
321
|
+
styles={{ "--spacing-md": "2rem" } as React.CSSProperties}
|
|
322
|
+
data-testid="stack"
|
|
323
|
+
>
|
|
324
|
+
Content
|
|
325
|
+
</Stack>
|
|
326
|
+
);
|
|
327
|
+
const stack = screen.getByTestId("stack");
|
|
328
|
+
expect(stack).toHaveAttribute("style");
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// Ref Forwarding Tests
|
|
333
|
+
// ============================================================================
|
|
334
|
+
|
|
335
|
+
it("forwards ref correctly", () => {
|
|
336
|
+
const ref = React.createRef<HTMLDivElement>();
|
|
337
|
+
render(
|
|
338
|
+
<Stack ref={ref} data-testid="stack">
|
|
339
|
+
Content
|
|
340
|
+
</Stack>
|
|
341
|
+
);
|
|
342
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it("forwards ref with polymorphic as prop", () => {
|
|
346
|
+
const ref = React.createRef<HTMLElement>();
|
|
347
|
+
render(
|
|
348
|
+
<Stack as="section" ref={ref} data-testid="stack">
|
|
349
|
+
Content
|
|
350
|
+
</Stack>
|
|
351
|
+
);
|
|
352
|
+
expect(ref.current).toBeInstanceOf(HTMLElement);
|
|
353
|
+
expect(ref.current?.tagName).toBe("SECTION");
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// ============================================================================
|
|
357
|
+
// Accessibility Tests
|
|
358
|
+
// ============================================================================
|
|
359
|
+
|
|
360
|
+
it("forwards ARIA attributes", () => {
|
|
361
|
+
render(
|
|
362
|
+
<Stack aria-label="Test Stack" role="region" data-testid="stack">
|
|
363
|
+
Content
|
|
364
|
+
</Stack>
|
|
365
|
+
);
|
|
366
|
+
const stack = screen.getByTestId("stack");
|
|
367
|
+
expect(stack).toHaveAttribute("aria-label", "Test Stack");
|
|
368
|
+
expect(stack).toHaveAttribute("role", "region");
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it("forwards data attributes", () => {
|
|
372
|
+
render(
|
|
373
|
+
<Stack data-testid="stack" data-custom="value">
|
|
374
|
+
Content
|
|
375
|
+
</Stack>
|
|
376
|
+
);
|
|
377
|
+
const stack = screen.getByTestId("stack");
|
|
378
|
+
expect(stack).toHaveAttribute("data-custom", "value");
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// ============================================================================
|
|
382
|
+
// Edge Cases
|
|
383
|
+
// ============================================================================
|
|
384
|
+
|
|
385
|
+
it("handles empty children", () => {
|
|
386
|
+
render(<Stack data-testid="stack" />);
|
|
387
|
+
const stack = screen.getByTestId("stack");
|
|
388
|
+
expect(stack).toBeInTheDocument();
|
|
389
|
+
expect(stack).toBeEmptyDOMElement();
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it("handles no optional props gracefully", () => {
|
|
393
|
+
render(<Stack data-testid="stack">Content</Stack>);
|
|
394
|
+
const stack = screen.getByTestId("stack");
|
|
395
|
+
expect(stack).toBeInTheDocument();
|
|
396
|
+
expect(stack).toHaveClass("stack");
|
|
397
|
+
expect(stack).toHaveClass("stack-vertical");
|
|
398
|
+
expect(stack.tagName).toBe("DIV");
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("handles only direction prop", () => {
|
|
402
|
+
render(<Stack direction="horizontal" data-testid="stack">Content</Stack>);
|
|
403
|
+
const stack = screen.getByTestId("stack");
|
|
404
|
+
expect(stack).toHaveClass("stack");
|
|
405
|
+
expect(stack).toHaveClass("stack-horizontal");
|
|
406
|
+
// Should not have gap, align, justify, or wrap classes when not provided
|
|
407
|
+
expect(stack.className.split(" ").length).toBe(2); // only "stack" and "stack-horizontal"
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// ============================================================================
|
|
411
|
+
// Layout Behavior Tests
|
|
412
|
+
// ============================================================================
|
|
413
|
+
|
|
414
|
+
it("creates vertical flex container by default", () => {
|
|
415
|
+
render(<Stack data-testid="stack">Content</Stack>);
|
|
416
|
+
const stack = screen.getByTestId("stack");
|
|
417
|
+
// Base stack class ensures display: flex is applied
|
|
418
|
+
expect(stack).toHaveClass("stack");
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it("creates horizontal flex container when direction is horizontal", () => {
|
|
422
|
+
render(<Stack direction="horizontal" data-testid="stack">Content</Stack>);
|
|
423
|
+
const stack = screen.getByTestId("stack");
|
|
424
|
+
expect(stack).toHaveClass("stack-horizontal");
|
|
425
|
+
});
|
|
426
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import UI from "../ui";
|
|
3
|
+
import type { StackProps } from "./stack.types";
|
|
4
|
+
|
|
5
|
+
// Re-export types for convenience
|
|
6
|
+
export type { StackProps } from "./stack.types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Stack - A simplified layout primitive for vertical or horizontal spacing between children.
|
|
10
|
+
*
|
|
11
|
+
* The Stack component provides an easy-to-use flexbox-based layout for creating vertical or
|
|
12
|
+
* horizontal arrangements with consistent gap spacing. It's designed to be simpler than the
|
|
13
|
+
* full Flex component, focusing on the most common stacking patterns.
|
|
14
|
+
*
|
|
15
|
+
* ## Key Features
|
|
16
|
+
* - **Simple API**: Fewer props than Flex for common use cases
|
|
17
|
+
* - **Fluid Spacing**: Responsive gap using CSS clamp()
|
|
18
|
+
* - **Flexbox-Based**: Reliable cross-browser layout
|
|
19
|
+
* - **Polymorphic**: Render as any semantic HTML element
|
|
20
|
+
* - **Type-Safe**: Full TypeScript support
|
|
21
|
+
*
|
|
22
|
+
* ## Accessibility
|
|
23
|
+
* - Uses semantic HTML elements when appropriate via `as` prop
|
|
24
|
+
* - Supports all ARIA attributes via spread props
|
|
25
|
+
* - Proper focus order maintained (visual order matches DOM order)
|
|
26
|
+
*
|
|
27
|
+
* ## Use Cases
|
|
28
|
+
* - Vertical spacing between content sections
|
|
29
|
+
* - Horizontal button groups
|
|
30
|
+
* - Navigation menus
|
|
31
|
+
* - Form layouts
|
|
32
|
+
* - Centered content (vertical/horizontal)
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* // Vertical stack with medium gap (default)
|
|
36
|
+
* <Stack gap="md">
|
|
37
|
+
* <h1>Title</h1>
|
|
38
|
+
* <p>Paragraph 1</p>
|
|
39
|
+
* <p>Paragraph 2</p>
|
|
40
|
+
* </Stack>
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Horizontal button group
|
|
44
|
+
* <Stack direction="horizontal" gap="sm">
|
|
45
|
+
* <Button>Cancel</Button>
|
|
46
|
+
* <Button variant="primary">Submit</Button>
|
|
47
|
+
* </Stack>
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* // Centered vertical stack
|
|
51
|
+
* <Stack
|
|
52
|
+
* gap="lg"
|
|
53
|
+
* align="center"
|
|
54
|
+
* justify="center"
|
|
55
|
+
* style={{ minHeight: '100vh' }}
|
|
56
|
+
* >
|
|
57
|
+
* <Logo />
|
|
58
|
+
* <h1>Welcome</h1>
|
|
59
|
+
* <Button>Get Started</Button>
|
|
60
|
+
* </Stack>
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Navigation with horizontal layout
|
|
64
|
+
* <Stack
|
|
65
|
+
* as="nav"
|
|
66
|
+
* direction="horizontal"
|
|
67
|
+
* gap="md"
|
|
68
|
+
* justify="between"
|
|
69
|
+
* align="center"
|
|
70
|
+
* >
|
|
71
|
+
* <Logo />
|
|
72
|
+
* <Stack direction="horizontal" gap="sm">
|
|
73
|
+
* <a href="/about">About</a>
|
|
74
|
+
* <a href="/contact">Contact</a>
|
|
75
|
+
* </Stack>
|
|
76
|
+
* </Stack>
|
|
77
|
+
*
|
|
78
|
+
* @see {@link StackProps} for complete props documentation
|
|
79
|
+
*/
|
|
80
|
+
export const Stack = React.forwardRef<HTMLElement, StackProps>(
|
|
81
|
+
(
|
|
82
|
+
{
|
|
83
|
+
gap,
|
|
84
|
+
direction = "vertical",
|
|
85
|
+
align,
|
|
86
|
+
justify,
|
|
87
|
+
wrap,
|
|
88
|
+
as = "div",
|
|
89
|
+
className,
|
|
90
|
+
classes,
|
|
91
|
+
children,
|
|
92
|
+
...props
|
|
93
|
+
},
|
|
94
|
+
ref
|
|
95
|
+
) => {
|
|
96
|
+
// Build utility classes array based on props
|
|
97
|
+
const utilityClasses: string[] = ["stack"];
|
|
98
|
+
|
|
99
|
+
// Direction utilities (default is vertical/column)
|
|
100
|
+
if (direction === "horizontal") {
|
|
101
|
+
utilityClasses.push("stack-horizontal");
|
|
102
|
+
} else {
|
|
103
|
+
utilityClasses.push("stack-vertical");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Gap utilities
|
|
107
|
+
if (gap) {
|
|
108
|
+
utilityClasses.push(`stack-gap-${gap}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Align utilities (cross-axis)
|
|
112
|
+
if (align) {
|
|
113
|
+
utilityClasses.push(`stack-align-${align}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Justify utilities (main-axis)
|
|
117
|
+
if (justify) {
|
|
118
|
+
utilityClasses.push(`stack-justify-${justify}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Wrap utilities
|
|
122
|
+
if (wrap) {
|
|
123
|
+
utilityClasses.push(`stack-${wrap}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Merge all classes: utility classes, className prop, and classes prop
|
|
127
|
+
const allClasses = [...utilityClasses, className, classes]
|
|
128
|
+
.filter(Boolean)
|
|
129
|
+
.join(" ");
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<UI as={as} ref={ref} classes={allClasses} {...props}>
|
|
133
|
+
{children}
|
|
134
|
+
</UI>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
Stack.displayName = "Stack";
|
|
140
|
+
|
|
141
|
+
export default Stack;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { ComponentProps } from "../../types/component-props";
|
|
2
|
+
import type { SpacingScale, StackElement } from "../../types/layout-primitives";
|
|
3
|
+
import type React from "react";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Props for the Stack component - a simplified layout primitive for vertical or horizontal spacing.
|
|
7
|
+
*
|
|
8
|
+
* Stack provides an easy-to-use flexbox-based layout for creating vertical or horizontal arrangements
|
|
9
|
+
* with consistent spacing between children. It's simpler than the full Flex component, ideal for
|
|
10
|
+
* common stacking patterns.
|
|
11
|
+
*
|
|
12
|
+
* ## Design Principles
|
|
13
|
+
* - **Simplified API**: Fewer props than Flex for common use cases
|
|
14
|
+
* - **Fluid Spacing**: Uses unified spacing scale with responsive values
|
|
15
|
+
* - **Flexbox-Based**: Built on CSS flexbox for reliable layouts
|
|
16
|
+
* - **Semantic HTML**: Defaults to `div` but supports semantic elements
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Vertical stack (default)
|
|
20
|
+
* <Stack gap="md">
|
|
21
|
+
* <h1>Title</h1>
|
|
22
|
+
* <p>Paragraph 1</p>
|
|
23
|
+
* <p>Paragraph 2</p>
|
|
24
|
+
* </Stack>
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Horizontal stack for buttons
|
|
28
|
+
* <Stack direction="horizontal" gap="sm">
|
|
29
|
+
* <Button>Cancel</Button>
|
|
30
|
+
* <Button variant="primary">Submit</Button>
|
|
31
|
+
* </Stack>
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Centered vertical stack
|
|
35
|
+
* <Stack
|
|
36
|
+
* gap="lg"
|
|
37
|
+
* align="center"
|
|
38
|
+
* justify="center"
|
|
39
|
+
* style={{ minHeight: '100vh' }}
|
|
40
|
+
* >
|
|
41
|
+
* <Logo />
|
|
42
|
+
* <h1>Welcome</h1>
|
|
43
|
+
* </Stack>
|
|
44
|
+
*/
|
|
45
|
+
export interface StackProps
|
|
46
|
+
extends Partial<ComponentProps>,
|
|
47
|
+
Omit<React.HTMLAttributes<HTMLElement>, "className"> {
|
|
48
|
+
/**
|
|
49
|
+
* Gap between children.
|
|
50
|
+
* Uses unified spacing scale: '0' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
|
51
|
+
* Maps to CSS custom properties (--spacing-*)
|
|
52
|
+
* @default 'md'
|
|
53
|
+
* @example
|
|
54
|
+
* <Stack gap="lg">Content</Stack>
|
|
55
|
+
*/
|
|
56
|
+
gap?: SpacingScale;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Layout direction.
|
|
60
|
+
* - 'vertical': Stack children vertically (column)
|
|
61
|
+
* - 'horizontal': Stack children horizontally (row)
|
|
62
|
+
* @default 'vertical'
|
|
63
|
+
* @example
|
|
64
|
+
* <Stack direction="horizontal" gap="sm">
|
|
65
|
+
* <Button>Cancel</Button>
|
|
66
|
+
* <Button>Submit</Button>
|
|
67
|
+
* </Stack>
|
|
68
|
+
*/
|
|
69
|
+
direction?: "vertical" | "horizontal";
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Alignment on cross axis.
|
|
73
|
+
* - 'start': Align items to start (left in horizontal, top in vertical)
|
|
74
|
+
* - 'center': Center items
|
|
75
|
+
* - 'end': Align items to end (right in horizontal, bottom in vertical)
|
|
76
|
+
* - 'stretch': Stretch items to fill cross axis
|
|
77
|
+
* @default 'stretch'
|
|
78
|
+
* @example
|
|
79
|
+
* <Stack align="center">Centered items</Stack>
|
|
80
|
+
*/
|
|
81
|
+
align?: "start" | "center" | "end" | "stretch";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Alignment on main axis.
|
|
85
|
+
* - 'start': Items at start
|
|
86
|
+
* - 'center': Items centered
|
|
87
|
+
* - 'end': Items at end
|
|
88
|
+
* - 'between': Space between items
|
|
89
|
+
* @example
|
|
90
|
+
* <Stack justify="between">
|
|
91
|
+
* <Header />
|
|
92
|
+
* <Footer />
|
|
93
|
+
* </Stack>
|
|
94
|
+
*/
|
|
95
|
+
justify?: "start" | "center" | "end" | "between";
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Allow items to wrap to next line/column.
|
|
99
|
+
* - 'wrap': Items wrap when they exceed container
|
|
100
|
+
* - 'nowrap': Items stay on single line/column (default)
|
|
101
|
+
* @default 'nowrap'
|
|
102
|
+
* @example
|
|
103
|
+
* <Stack direction="horizontal" wrap="wrap">
|
|
104
|
+
* {items.map(item => <Item key={item.id} />)}
|
|
105
|
+
* </Stack>
|
|
106
|
+
*/
|
|
107
|
+
wrap?: "wrap" | "nowrap";
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Polymorphic element type to render.
|
|
111
|
+
* Defaults to 'div' but supports semantic HTML elements.
|
|
112
|
+
* @default 'div'
|
|
113
|
+
* @example
|
|
114
|
+
* <Stack as="nav" direction="horizontal" gap="md">
|
|
115
|
+
* <a href="/">Home</a>
|
|
116
|
+
* <a href="/about">About</a>
|
|
117
|
+
* </Stack>
|
|
118
|
+
*/
|
|
119
|
+
as?: StackElement;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Additional CSS classes to apply.
|
|
123
|
+
* Merged with generated utility classes.
|
|
124
|
+
* @example
|
|
125
|
+
* <Stack className="custom-stack" gap="md">Content</Stack>
|
|
126
|
+
*/
|
|
127
|
+
className?: string;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Children elements to render inside the Stack.
|
|
131
|
+
*/
|
|
132
|
+
children?: React.ReactNode;
|
|
133
|
+
}
|