@syscore/ui-library 1.27.3 → 2.0.0-beta-publish-workflow-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/client/App.tsx +0 -2
  2. package/client/assets/alert/icon-clear.svg +4 -0
  3. package/client/assets/alert/icon-done.svg +3 -0
  4. package/client/assets/avatar-identity/photo.png +0 -0
  5. package/client/assets/avatar-identity/placeholder-icon.svg +8 -0
  6. package/client/assets/breadcrumb/icon-ellipsis.svg +5 -0
  7. package/client/assets/breadcrumb/icon-home.svg +3 -0
  8. package/client/assets/breadcrumb/icon-separator.svg +3 -0
  9. package/client/assets/button-v01/icon-back.svg +4 -0
  10. package/client/assets/button-v01/icon-check.svg +3 -0
  11. package/client/assets/button-v01/icon-close.svg +4 -0
  12. package/client/assets/button-v01/icon-delete.svg +3 -0
  13. package/client/assets/button-v01/icon-device.svg +3 -0
  14. package/client/assets/dropdown/icon-carrot-contract.svg +3 -0
  15. package/client/assets/dropdown/icon-carrot-expand.svg +3 -0
  16. package/client/assets/dropdown/icon-clear.svg +4 -0
  17. package/client/assets/dropdown/icon-enter.svg +3 -0
  18. package/client/components/icons/UtilityChangeType.tsx +21 -0
  19. package/client/components/ui/alert-dialog-panel.tsx +246 -0
  20. package/client/components/ui/alert-v02.tsx +214 -0
  21. package/client/components/ui/app-bar.tsx +299 -0
  22. package/client/components/ui/avatar-identity.tsx +122 -0
  23. package/client/components/ui/banner.tsx +108 -0
  24. package/client/components/ui/bottom-navigation.tsx +223 -0
  25. package/client/components/ui/breadcrumb-trail.tsx +170 -0
  26. package/client/components/ui/button-v01.tsx +238 -0
  27. package/client/components/ui/button.tsx +2 -0
  28. package/client/components/ui/card.tsx +108 -26
  29. package/client/components/ui/code-badge.tsx +62 -0
  30. package/client/components/ui/date-picker.tsx +188 -0
  31. package/client/components/ui/dropdown.tsx +448 -0
  32. package/client/components/ui/empty-state.tsx +197 -0
  33. package/client/components/ui/file-upload.tsx +214 -0
  34. package/client/components/ui/footer.tsx +179 -0
  35. package/client/components/ui/layout.tsx +1182 -0
  36. package/client/components/ui/pagination-v01.tsx +157 -0
  37. package/client/components/ui/password-field-v01.tsx +67 -0
  38. package/client/components/ui/search-field-v01.tsx +192 -0
  39. package/client/components/ui/section-heading.tsx +49 -0
  40. package/client/components/ui/sidebar.tsx +2 -3
  41. package/client/components/ui/standard-navigation.tsx +8 -2
  42. package/client/components/ui/stepper.tsx +148 -0
  43. package/client/components/ui/switch-v01.tsx +71 -0
  44. package/client/components/ui/system-bar.tsx +119 -0
  45. package/client/components/ui/table-v01.tsx +230 -0
  46. package/client/components/ui/tabs-v01.tsx +99 -0
  47. package/client/components/ui/tag-v02.tsx +113 -0
  48. package/client/components/ui/text-area-v01.tsx +33 -0
  49. package/client/components/ui/text-field-v01.tsx +108 -0
  50. package/client/components/ui/timeline.tsx +181 -0
  51. package/client/components/ui/toast-v01.tsx +206 -0
  52. package/client/components/ui/tooltip.tsx +264 -71
  53. package/client/global.css +9565 -4378
  54. package/client/storybook.css +125 -0
  55. package/client/ui/Accordion.stories.tsx +1 -1
  56. package/client/ui/AlertDialogPanel/AlertDialogPanel.stories.tsx +150 -0
  57. package/client/ui/AlertV02/AlertV02.stories.tsx +188 -0
  58. package/client/ui/AppBar/app-bar.stories.tsx +280 -0
  59. package/client/ui/AspectRatio.stories.tsx +1 -1
  60. package/client/ui/AvatarIdentity/AvatarIdentity.stories.tsx +77 -0
  61. package/client/ui/Banner/banner.stories.tsx +238 -0
  62. package/client/ui/BottomNavigation/bottom-navigation.stories.tsx +285 -0
  63. package/client/ui/BreadcrumbTrail/BreadcrumbTrail.stories.tsx +232 -0
  64. package/client/ui/Button.stories.tsx +1 -1
  65. package/client/ui/ButtonV01/ButtonV01.stories.tsx +417 -0
  66. package/client/ui/Calendar/Calendar.stories.tsx +1 -1
  67. package/client/ui/Card.stories.tsx +285 -168
  68. package/client/ui/Carousel/Carousel.stories.tsx +1 -1
  69. package/client/ui/Chart/Chart.stories.tsx +1 -1
  70. package/client/ui/Checkbox.stories.tsx +1 -1
  71. package/client/ui/Collapsible/Collapsible.stories.tsx +1 -1
  72. package/client/ui/Colors.stories.tsx +1 -1
  73. package/client/ui/Command/Command.stories.tsx +1 -1
  74. package/client/ui/ContextMenu/ContextMenu.stories.tsx +1 -1
  75. package/client/ui/DatePicker/DatePicker.stories.tsx +293 -0
  76. package/client/ui/Dialog.stories.tsx +1 -1
  77. package/client/ui/Drawer/Drawer.stories.tsx +1 -1
  78. package/client/ui/Dropdown/Dropdown.stories.tsx +205 -0
  79. package/client/ui/EmptyState/empty-state.stories.tsx +251 -0
  80. package/client/ui/FileUpload/FileUpload.stories.tsx +218 -0
  81. package/client/ui/Footer/footer.stories.tsx +194 -0
  82. package/client/ui/Form/Form.stories.tsx +1 -1
  83. package/client/ui/Hero.stories.tsx +1 -1
  84. package/client/ui/HoverCard/HoverCard.stories.tsx +1 -1
  85. package/client/ui/Icons.stories.tsx +1 -1
  86. package/client/ui/Input.stories.tsx +1 -1
  87. package/client/ui/InputOTP/InputOTP.stories.tsx +1 -1
  88. package/client/ui/Label.stories.tsx +1 -1
  89. package/client/ui/Layout/Center.stories.tsx +100 -0
  90. package/client/ui/Layout/Columns.stories.tsx +136 -0
  91. package/client/ui/Layout/Container.stories.tsx +104 -0
  92. package/client/ui/Layout/FormLayout.stories.tsx +144 -0
  93. package/client/ui/Layout/Grid.stories.tsx +158 -0
  94. package/client/ui/Layout/GridSpan.stories.tsx +75 -0
  95. package/client/ui/Layout/HStack.stories.tsx +128 -0
  96. package/client/ui/Layout/Layout.stories.tsx +287 -0
  97. package/client/ui/Layout/LayoutContent.stories.tsx +91 -0
  98. package/client/ui/Layout/LayoutFooter.stories.tsx +77 -0
  99. package/client/ui/Layout/LayoutHeader.stories.tsx +104 -0
  100. package/client/ui/Layout/LayoutPanel.stories.tsx +143 -0
  101. package/client/ui/Layout/Positioned.stories.tsx +113 -0
  102. package/client/ui/Layout/Section.stories.tsx +84 -0
  103. package/client/ui/Layout/ShowHide.stories.tsx +99 -0
  104. package/client/ui/Layout/Spacer.stories.tsx +149 -0
  105. package/client/ui/Layout/Stack.stories.tsx +69 -0
  106. package/client/ui/Layout/StackItem.stories.tsx +124 -0
  107. package/client/ui/Layout/VStack.stories.tsx +101 -0
  108. package/client/ui/Layout/controls.ts +33 -0
  109. package/client/ui/Layout/demo.tsx +37 -0
  110. package/client/ui/Menubar/Menubar.stories.tsx +1 -1
  111. package/client/ui/MobileNav.stories.tsx +1 -1
  112. package/client/ui/Navigation.stories.tsx +1 -1
  113. package/client/ui/NavigationMenu/NavigationMenu.stories.tsx +1 -1
  114. package/client/ui/PageHeader.stories.tsx +13 -13
  115. package/client/ui/Pagination/Pagination.stories.tsx +178 -98
  116. package/client/ui/Pagination/PaginationLegacy.stories.tsx +121 -0
  117. package/client/ui/Panel.stories.tsx +1 -1
  118. package/client/ui/Popover/Popover.stories.tsx +1 -1
  119. package/client/ui/Progress/Progress.stories.tsx +1 -1
  120. package/client/ui/RadioGroup/RadioGroup.stories.tsx +1 -1
  121. package/client/ui/Resizable/Resizable.stories.tsx +1 -1
  122. package/client/ui/ScrollArea/ScrollArea.stories.tsx +1 -1
  123. package/client/ui/SearchField/SearchField.stories.tsx +153 -0
  124. package/client/ui/{SearchField.stories.tsx → SearchField/SearchFieldLegacy.stories.tsx} +2 -2
  125. package/client/ui/SectionBadge.stories.tsx +1 -1
  126. package/client/ui/Select.stories.tsx +1 -1
  127. package/client/ui/Separator/Separator.stories.tsx +1 -1
  128. package/client/ui/Sheet/Sheet.stories.tsx +1 -1
  129. package/client/ui/Sidebar/Sidebar.stories.tsx +57 -8
  130. package/client/ui/Skeleton/Skeleton.stories.tsx +1 -1
  131. package/client/ui/Slider/Slider.stories.tsx +1 -1
  132. package/client/ui/StandardNavigation.stories.tsx +1 -1
  133. package/client/ui/Stepper/Stepper.stories.tsx +344 -0
  134. package/client/ui/Switch.stories.tsx +1 -1
  135. package/client/ui/SwitchV01/SwitchV01.stories.tsx +152 -0
  136. package/client/ui/SystemBar/system-bar.stories.tsx +179 -0
  137. package/client/ui/Table/TableV01.stories.tsx +256 -0
  138. package/client/ui/Tabs.stories.tsx +1 -1
  139. package/client/ui/TabsV01/TabsV01.stories.tsx +144 -0
  140. package/client/ui/Tag.stories.tsx +1 -1
  141. package/client/ui/TagV02/TagStatusV02.stories.tsx +132 -0
  142. package/client/ui/TagV02/TagV02.stories.tsx +142 -0
  143. package/client/ui/TextAreaV01/TextAreaV01.stories.tsx +146 -0
  144. package/client/ui/TextFieldV01/PasswordFieldV01.stories.tsx +161 -0
  145. package/client/ui/TextFieldV01/TextFieldV01.stories.tsx +160 -0
  146. package/client/ui/Textarea.stories.tsx +1 -1
  147. package/client/ui/Timeline/timeline.stories.tsx +404 -0
  148. package/client/ui/Toast/Toast.stories.tsx +1 -1
  149. package/client/ui/ToastV01/ToastV01.stories.tsx +201 -0
  150. package/client/ui/Toaster/Toaster.stories.tsx +1 -1
  151. package/client/ui/Toggle.stories.tsx +1 -1
  152. package/client/ui/Tooltip.stories.tsx +287 -114
  153. package/client/ui/Typography.stories.tsx +1 -1
  154. package/dist/index.cjs.js +1 -1
  155. package/dist/index.d.ts +649 -13
  156. package/dist/index.es.js +4405 -653
  157. package/package.json +1 -1
  158. package/client/components/ui/badge.tsx +0 -33
  159. package/client/components/ui/sonner.tsx +0 -26
  160. package/client/components/ui/toggle-group.tsx +0 -76
  161. package/client/ui/Alert/Alert.stories.tsx +0 -82
  162. package/client/ui/AlertDialog/AlertDialog.stories.tsx +0 -106
  163. package/client/ui/Avatar/Avatar.stories.tsx +0 -94
  164. package/client/ui/Badge/Badge.stories.tsx +0 -60
  165. package/client/ui/Breadcrumb/Breadcrumb.stories.tsx +0 -97
  166. package/client/ui/DropdownMenu/DropdownMenu.stories.tsx +0 -139
  167. package/client/ui/Sonner/Sonner.stories.tsx +0 -48
  168. package/client/ui/Table/Table.stories.tsx +0 -135
  169. package/client/ui/ToggleGroup/ToggleGroup.stories.tsx +0 -88
@@ -93,7 +93,7 @@ import {
93
93
  } from "../components/icons/achievement-badges";
94
94
 
95
95
  const meta = {
96
- title: "Review/Icons",
96
+ title: "Components/Icons",
97
97
  tags: ["autodocs"],
98
98
  parameters: {
99
99
  layout: "padded",
@@ -5,7 +5,7 @@ import { Button } from "../components/ui/button";
5
5
  import { Search, Copy } from "lucide-react";
6
6
 
7
7
  const meta = {
8
- title: "Review/Input",
8
+ title: "Components/Input",
9
9
  component: Input,
10
10
  tags: ["autodocs"],
11
11
  parameters: {
@@ -8,7 +8,7 @@ import {
8
8
  import { useState } from "react";
9
9
 
10
10
  const meta = {
11
- title: "UI/InputOTP",
11
+ title: "Draft/InputOTP",
12
12
  component: InputOTP,
13
13
  tags: ["autodocs"],
14
14
  parameters: {
@@ -4,7 +4,7 @@ import { Input } from "../components/ui/input";
4
4
  import { Textarea } from "../components/ui/textarea";
5
5
 
6
6
  const meta = {
7
- title: "Review/Label",
7
+ title: "Components/Label",
8
8
  component: Label,
9
9
  tags: ["autodocs"],
10
10
  parameters: {
@@ -0,0 +1,100 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Center, VStack } from "../../components/ui/layout";
3
+ import { Card } from "../../components/ui/card";
4
+ import { Text } from "../../components/ui/typography";
5
+ import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
6
+ import { hiddenArgs, spaceControl } from "./controls";
7
+
8
+ const meta = {
9
+ title: "Components/Layout/Center",
10
+ component: Center,
11
+ tags: ["autodocs"],
12
+ parameters: {
13
+ layout: "padded",
14
+ docs: {
15
+ description: {
16
+ component: [
17
+ "Centers children on one or both axes. Use for empty states, login cards, and spinners.",
18
+ "",
19
+ LAYOUT_DOCS_RULE,
20
+ "",
21
+ "```tsx",
22
+ `import { Center } from "@syscore/ui-library"`,
23
+ "",
24
+ '<Center axis="both" height={320}>',
25
+ " <EmptyState />",
26
+ "</Center>",
27
+ "```",
28
+ "",
29
+ "Set `height` when centering vertically — Center needs a defined height to center within.",
30
+ "",
31
+ "| `axis` | Effect |",
32
+ "|--------|--------|",
33
+ "| `both` (default) | Horizontal and vertical |",
34
+ "| `horizontal` | `justify-content: center` only |",
35
+ "| `vertical` | `align-items: center` only |",
36
+ "",
37
+ "`isInline` swaps `display: flex` for `inline-flex` so the box hugs its content instead of filling the row.",
38
+ ].join("\n"),
39
+ },
40
+ },
41
+ },
42
+ argTypes: {
43
+ ...hiddenArgs,
44
+ axis: {
45
+ control: "inline-radio",
46
+ options: ["both", "horizontal", "vertical"],
47
+ },
48
+ padding: spaceControl,
49
+ isInline: { control: "boolean" },
50
+ },
51
+ args: {
52
+ axis: "both",
53
+ height: 240,
54
+ },
55
+ } satisfies Meta<typeof Center>;
56
+
57
+ export default meta;
58
+ type Story = StoryObj<typeof meta>;
59
+
60
+ export const Default: Story = {
61
+ render: (args) => (
62
+ <Center {...args} className="sb-outline">
63
+ <DemoBox label="Centered" />
64
+ </Center>
65
+ ),
66
+ };
67
+
68
+ export const Horizontal: Story = {
69
+ args: { axis: "horizontal", height: 120 },
70
+ parameters: {
71
+ docs: {
72
+ description: {
73
+ story:
74
+ "Horizontal only — the child sits at the top, centred left to right.",
75
+ },
76
+ },
77
+ },
78
+ render: (args) => (
79
+ <Center {...args} className="sb-outline">
80
+ <DemoBox label="Horizontal only" />
81
+ </Center>
82
+ ),
83
+ };
84
+
85
+ export const CenteredCard: Story = {
86
+ name: "Centered card",
87
+ args: { axis: "both", height: 320, padding: "xl" },
88
+ render: (args) => (
89
+ <Center {...args}>
90
+ <Card variant="outlined">
91
+ <VStack gap="xs" align="center" maxWidth={320}>
92
+ <Text variant="heading-xxsmall">Sign in</Text>
93
+ <Text variant="body-small">
94
+ Use Center for empty and auth screens.
95
+ </Text>
96
+ </VStack>
97
+ </Card>
98
+ </Center>
99
+ ),
100
+ };
@@ -0,0 +1,136 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Columns } from "../../components/ui/layout";
3
+ import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
4
+ import { hiddenArgs, spaceControl } from "./controls";
5
+
6
+ const meta = {
7
+ title: "Components/Layout/Columns",
8
+ component: Columns,
9
+ tags: ["autodocs"],
10
+ parameters: {
11
+ layout: "padded",
12
+ docs: {
13
+ description: {
14
+ component: [
15
+ "Two-column grid with **unequal** widths — a sidebar beside content, or a 1:2 split. For equal columns use `Grid`; for a whole page shell use `Layout` + `LayoutPanel`.",
16
+ "",
17
+ LAYOUT_DOCS_RULE,
18
+ "",
19
+ "```tsx",
20
+ `import { Columns } from "@syscore/ui-library"`,
21
+ "",
22
+ '<Columns preset="sidebar" gap="xl" collapse="md">',
23
+ " <Nav />",
24
+ " <Main />",
25
+ "</Columns>",
26
+ "```",
27
+ "",
28
+ "| `preset` | Template |",
29
+ "|----------|----------|",
30
+ "| `sidebar` | panel width + rest |",
31
+ "| `sidebar-right` | rest + panel width |",
32
+ "| `wide-sidebar` / `narrow-sidebar` | wide / narrow panel width + rest |",
33
+ "| `split` (default) | `1fr 1fr` |",
34
+ "| `1-2` `2-1` `1-3` `3-1` | proportional splits |",
35
+ "",
36
+ "Sidebar presets read the same `--layout-panel-width-*` variables as `LayoutPanel`, so a sidebar here and a panel there stay the same width.",
37
+ "",
38
+ "`collapse` picks the breakpoint below which the columns stack into one.",
39
+ ].join("\n"),
40
+ },
41
+ },
42
+ },
43
+ argTypes: {
44
+ ...hiddenArgs,
45
+ preset: {
46
+ control: "select",
47
+ options: [
48
+ "sidebar",
49
+ "sidebar-right",
50
+ "wide-sidebar",
51
+ "narrow-sidebar",
52
+ "split",
53
+ "1-2",
54
+ "2-1",
55
+ "1-3",
56
+ "3-1",
57
+ ],
58
+ },
59
+ collapse: {
60
+ control: "inline-radio",
61
+ options: [undefined, "sm", "md", "lg"],
62
+ },
63
+ gap: spaceControl,
64
+ rowGap: spaceControl,
65
+ columnGap: spaceControl,
66
+ template: { control: "text" },
67
+ },
68
+ args: {
69
+ preset: "sidebar",
70
+ gap: "xl",
71
+ collapse: "md",
72
+ },
73
+ } satisfies Meta<typeof Columns>;
74
+
75
+ export default meta;
76
+ type Story = StoryObj<typeof meta>;
77
+
78
+ export const Default: Story = {
79
+ name: "Sidebar",
80
+ render: (args) => (
81
+ <Columns {...args}>
82
+ <DemoBox label="Sidebar" tall />
83
+ <DemoBox label="Content" tall />
84
+ </Columns>
85
+ ),
86
+ };
87
+
88
+ export const Split: Story = {
89
+ args: { preset: "split" },
90
+ parameters: {
91
+ docs: { description: { story: "Two equal halves." } },
92
+ },
93
+ render: (args) => (
94
+ <Columns {...args}>
95
+ <DemoBox label="Left" tall />
96
+ <DemoBox label="Right" tall />
97
+ </Columns>
98
+ ),
99
+ };
100
+
101
+ export const Proportional: Story = {
102
+ args: { preset: "1-3" },
103
+ parameters: {
104
+ docs: {
105
+ description: {
106
+ story: "`1-3` gives the second column three times the width.",
107
+ },
108
+ },
109
+ },
110
+ render: (args) => (
111
+ <Columns {...args}>
112
+ <DemoBox label="1fr" tall />
113
+ <DemoBox label="3fr" tall />
114
+ </Columns>
115
+ ),
116
+ };
117
+
118
+ export const CustomTemplate: Story = {
119
+ name: "Custom template",
120
+ args: { preset: undefined, template: "1fr 2fr 1fr" },
121
+ parameters: {
122
+ docs: {
123
+ description: {
124
+ story:
125
+ "`template` accepts any `grid-template-columns` value and overrides `preset`. Reach for it only when no preset fits — a literal here is a value the design system can no longer change.",
126
+ },
127
+ },
128
+ },
129
+ render: (args) => (
130
+ <Columns {...args}>
131
+ <DemoBox label="1fr" />
132
+ <DemoBox label="2fr" />
133
+ <DemoBox label="1fr" />
134
+ </Columns>
135
+ ),
136
+ };
@@ -0,0 +1,104 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Container, VStack } from "../../components/ui/layout";
3
+ import { Text } from "../../components/ui/typography";
4
+ import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
5
+ import { hiddenArgs } from "./controls";
6
+
7
+ const meta = {
8
+ title: "Components/Layout/Container",
9
+ component: Container,
10
+ tags: ["autodocs"],
11
+ parameters: {
12
+ layout: "fullscreen",
13
+ docs: {
14
+ description: {
15
+ component: [
16
+ "Max-width wrapper that centers a page column. Inside a `Layout`, prefer `contentWidth` on `Layout` — this is for pages that are not built on the shell.",
17
+ "",
18
+ LAYOUT_DOCS_RULE,
19
+ "",
20
+ "```tsx",
21
+ `import { Container } from "@syscore/ui-library"`,
22
+ "",
23
+ '<Container size="lg">',
24
+ " <Article />",
25
+ "</Container>",
26
+ "```",
27
+ "",
28
+ "| `size` | Max width |",
29
+ "|--------|-----------|",
30
+ "| `sm` | 640px |",
31
+ "| `md` | 768px |",
32
+ "| `lg` | 1024px |",
33
+ "| `xl` (default) | 1280px |",
34
+ "| `2xl` | 1536px |",
35
+ "| `full` | 100% |",
36
+ "",
37
+ "`center` (default on) applies the auto margins; `padded` (default on) adds the responsive side gutter.",
38
+ ].join("\n"),
39
+ },
40
+ },
41
+ },
42
+ argTypes: {
43
+ ...hiddenArgs,
44
+ size: {
45
+ control: "select",
46
+ options: ["sm", "md", "lg", "xl", "2xl", "full"],
47
+ },
48
+ center: { control: "boolean" },
49
+ padded: { control: "boolean" },
50
+ },
51
+ args: { size: "lg", center: true, padded: true },
52
+ } satisfies Meta<typeof Container>;
53
+
54
+ export default meta;
55
+ type Story = StoryObj<typeof meta>;
56
+
57
+ export const Default: Story = {
58
+ render: (args) => (
59
+ <Container {...args}>
60
+ <VStack gap="md">
61
+ <Text variant="heading-xsmall">Contained column</Text>
62
+ <DemoBox label="Container child" tall />
63
+ </VStack>
64
+ </Container>
65
+ ),
66
+ };
67
+
68
+ export const Sizes: Story = {
69
+ name: "All sizes",
70
+ parameters: {
71
+ controls: { disable: true },
72
+ docs: {
73
+ description: {
74
+ story:
75
+ "Each step against the same viewport. Widen the canvas to separate them.",
76
+ },
77
+ },
78
+ },
79
+ render: () => (
80
+ <VStack gap="sm" width="100%">
81
+ {(["sm", "md", "lg", "xl", "2xl"] as const).map((size) => (
82
+ <Container key={size} size={size}>
83
+ <DemoBox label={`size="${size}"`} />
84
+ </Container>
85
+ ))}
86
+ </VStack>
87
+ ),
88
+ };
89
+
90
+ export const Unpadded: Story = {
91
+ args: { padded: false },
92
+ parameters: {
93
+ docs: {
94
+ description: {
95
+ story: "Turn `padded` off when the child brings its own inset.",
96
+ },
97
+ },
98
+ },
99
+ render: (args) => (
100
+ <Container {...args}>
101
+ <DemoBox label="No side gutter" tall />
102
+ </Container>
103
+ ),
104
+ };
@@ -0,0 +1,144 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { FormLayout, HStack, VStack } from "../../components/ui/layout";
3
+ import { ButtonV01 } from "../../components/ui/button-v01";
4
+ import { Input } from "../../components/ui/input";
5
+ import { Label } from "../../components/ui/label";
6
+ import { Textarea } from "../../components/ui/textarea";
7
+ import { LAYOUT_DOCS_RULE } from "./demo";
8
+ import { hiddenArgs, spaceControl } from "./controls";
9
+
10
+ const meta = {
11
+ title: "Components/Layout/FormLayout",
12
+ component: FormLayout,
13
+ tags: ["autodocs"],
14
+ parameters: {
15
+ layout: "padded",
16
+ docs: {
17
+ description: {
18
+ component: [
19
+ "Arranges form fields. Layout only — wrap in a `<form>` for submit.",
20
+ "",
21
+ LAYOUT_DOCS_RULE,
22
+ "",
23
+ "```tsx",
24
+ `import { FormLayout } from "@syscore/ui-library"`,
25
+ "",
26
+ "<FormLayout>",
27
+ " <Label>Name</Label>",
28
+ " <Input />",
29
+ "</FormLayout>",
30
+ "```",
31
+ "",
32
+ "| `direction` | Effect |",
33
+ "|-------------|--------|",
34
+ "| `vertical` (default) | Fields stack top to bottom |",
35
+ "| `horizontal` | Equal-width columns |",
36
+ "| `horizontal-labels` | Label left, control right (stacks below 480px) |",
37
+ ].join("\n"),
38
+ },
39
+ },
40
+ },
41
+ argTypes: {
42
+ ...hiddenArgs,
43
+ direction: {
44
+ control: "inline-radio",
45
+ options: ["vertical", "horizontal", "horizontal-labels"],
46
+ },
47
+ gap: spaceControl,
48
+ },
49
+ args: {
50
+ direction: "vertical",
51
+ maxWidth: 480,
52
+ width: "100%",
53
+ },
54
+ } satisfies Meta<typeof FormLayout>;
55
+
56
+ export default meta;
57
+ type Story = StoryObj<typeof meta>;
58
+
59
+ export const Default: Story = {
60
+ name: "Vertical",
61
+ render: (args) => (
62
+ <FormLayout {...args}>
63
+ <VStack gap="xs">
64
+ <Label>Project name</Label>
65
+ <Input placeholder="My project" />
66
+ </VStack>
67
+ <VStack gap="xs">
68
+ <Label>Description</Label>
69
+ <Textarea placeholder="Describe your project" />
70
+ </VStack>
71
+ <HStack gap="sm" justify="end">
72
+ <ButtonV01
73
+ typeVariant="utility"
74
+ appearance="solid"
75
+ hierarchy="secondary"
76
+ size="medium"
77
+ >
78
+ Cancel
79
+ </ButtonV01>
80
+ <ButtonV01
81
+ typeVariant="utility"
82
+ appearance="solid"
83
+ context="confirm"
84
+ size="medium"
85
+ >
86
+ Create
87
+ </ButtonV01>
88
+ </HStack>
89
+ </FormLayout>
90
+ ),
91
+ };
92
+
93
+ export const Horizontal: Story = {
94
+ args: { maxWidth: 640 },
95
+ parameters: {
96
+ docs: {
97
+ description: {
98
+ story:
99
+ "Pair related fields (first + last name). Nest inside a vertical FormLayout for the rest of the form.",
100
+ },
101
+ },
102
+ },
103
+ render: (args) => (
104
+ <FormLayout {...args}>
105
+ <FormLayout direction="horizontal">
106
+ <VStack gap="xs">
107
+ <Label>First name</Label>
108
+ <Input placeholder="Ada" />
109
+ </VStack>
110
+ <VStack gap="xs">
111
+ <Label>Last name</Label>
112
+ <Input placeholder="Lovelace" />
113
+ </VStack>
114
+ </FormLayout>
115
+ <VStack gap="xs">
116
+ <Label>Email</Label>
117
+ <Input placeholder="ada@example.com" />
118
+ </VStack>
119
+ </FormLayout>
120
+ ),
121
+ };
122
+
123
+ export const HorizontalLabels: Story = {
124
+ name: "Horizontal labels",
125
+ args: { direction: "horizontal-labels", maxWidth: 560 },
126
+ parameters: {
127
+ docs: {
128
+ description: {
129
+ story:
130
+ "Settings-style: label on the left, control on the right. Pass Label then Input as siblings.",
131
+ },
132
+ },
133
+ },
134
+ render: (args) => (
135
+ <FormLayout {...args}>
136
+ <Label>Name</Label>
137
+ <Input placeholder="Ada Lovelace" />
138
+ <Label>Email</Label>
139
+ <Input placeholder="ada@example.com" />
140
+ <Label>Role</Label>
141
+ <Input placeholder="Engineer" />
142
+ </FormLayout>
143
+ ),
144
+ };
@@ -0,0 +1,158 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Grid } from "../../components/ui/layout";
3
+ import { Card } from "../../components/ui/card";
4
+ import { Text } from "../../components/ui/typography";
5
+ import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
6
+ import { hiddenArgs, spaceControl } from "./controls";
7
+
8
+ const meta = {
9
+ title: "Components/Layout/Grid",
10
+ component: Grid,
11
+ tags: ["autodocs"],
12
+ parameters: {
13
+ layout: "padded",
14
+ docs: {
15
+ description: {
16
+ component: [
17
+ "Equal-width CSS grid. Use for cards, galleries, and metric rows.",
18
+ "",
19
+ LAYOUT_DOCS_RULE,
20
+ "",
21
+ "```tsx",
22
+ `import { Grid } from "@syscore/ui-library"`,
23
+ "",
24
+ '<Grid columns={3} gap="xl">',
25
+ " <Card />",
26
+ " <Card />",
27
+ " <Card />",
28
+ "</Grid>",
29
+ "```",
30
+ "",
31
+ "| `columns` | Effect |",
32
+ "|-----------|--------|",
33
+ "| `3` | Always three columns, mobile included |",
34
+ "| `{ minWidth: 280 }` | Auto-fills as many columns as fit — no breakpoint props |",
35
+ "",
36
+ "Unequal widths (sidebar + main) belong on `Columns`, or on `Layout` + `LayoutPanel` for a page shell.",
37
+ ].join("\n"),
38
+ },
39
+ },
40
+ },
41
+ argTypes: {
42
+ ...hiddenArgs,
43
+ columns: { control: "select", options: [1, 2, 3, 4, 6, 12] },
44
+ gap: spaceControl,
45
+ rowGap: spaceControl,
46
+ columnGap: spaceControl,
47
+ align: {
48
+ control: "select",
49
+ options: ["start", "center", "end", "stretch"],
50
+ },
51
+ justify: {
52
+ control: "select",
53
+ options: ["start", "center", "end", "stretch"],
54
+ },
55
+ },
56
+ args: {
57
+ columns: 3,
58
+ gap: "md",
59
+ width: "100%",
60
+ },
61
+ } satisfies Meta<typeof Grid>;
62
+
63
+ export default meta;
64
+ type Story = StoryObj<typeof meta>;
65
+
66
+ export const Default: Story = {
67
+ name: "Three columns",
68
+ render: (args) => (
69
+ <Grid {...args}>
70
+ {["1", "2", "3", "4", "5", "6"].map((n) => (
71
+ <DemoBox key={n} label={n} tall />
72
+ ))}
73
+ </Grid>
74
+ ),
75
+ };
76
+
77
+ export const TwoColumns: Story = {
78
+ name: "Two columns",
79
+ args: { columns: 2 },
80
+ render: (args) => (
81
+ <Grid {...args}>
82
+ {["One", "Two", "Three", "Four"].map((n) => (
83
+ <DemoBox key={n} label={n} tall />
84
+ ))}
85
+ </Grid>
86
+ ),
87
+ };
88
+
89
+ export const FourColumns: Story = {
90
+ name: "Four columns",
91
+ args: { columns: 4 },
92
+ render: (args) => (
93
+ <Grid {...args}>
94
+ {["Q1", "Q2", "Q3", "Q4"].map((n) => (
95
+ <DemoBox key={n} label={n} />
96
+ ))}
97
+ </Grid>
98
+ ),
99
+ };
100
+
101
+ export const Fluid: Story = {
102
+ name: "Fluid min width",
103
+ args: { columns: { minWidth: 200 } },
104
+ parameters: {
105
+ docs: {
106
+ description: {
107
+ story:
108
+ "Columns reflow from available width. Not a breakpoint table — resize the canvas.",
109
+ },
110
+ },
111
+ },
112
+ render: (args) => (
113
+ <Grid {...args}>
114
+ {["A", "B", "C", "D", "E", "F"].map((n) => (
115
+ <DemoBox key={n} label={n} tall />
116
+ ))}
117
+ </Grid>
118
+ ),
119
+ };
120
+
121
+ export const UnevenGaps: Story = {
122
+ name: "Row and column gap",
123
+ args: { columns: 3, rowGap: "2xl", columnGap: "xs" },
124
+ parameters: {
125
+ docs: {
126
+ description: {
127
+ story: "`rowGap` and `columnGap` override `gap` on one axis.",
128
+ },
129
+ },
130
+ },
131
+ render: (args) => (
132
+ <Grid {...args}>
133
+ {["1", "2", "3", "4", "5", "6"].map((n) => (
134
+ <DemoBox key={n} label={n} />
135
+ ))}
136
+ </Grid>
137
+ ),
138
+ };
139
+
140
+ export const EqualWidthCards: Story = {
141
+ name: "Equal-width cards",
142
+ args: { columns: 4, gap: "md" },
143
+ render: (args) => (
144
+ <Grid {...args}>
145
+ {[
146
+ { label: "Total projects", value: "2,847" },
147
+ { label: "Compliance score", value: "94%" },
148
+ { label: "Open issues", value: "18" },
149
+ { label: "Active users", value: "1,204" },
150
+ ].map((item) => (
151
+ <Card key={item.label} variant="outlined">
152
+ <Text variant="overline-small">{item.label}</Text>
153
+ <Text variant="number-large">{item.value}</Text>
154
+ </Card>
155
+ ))}
156
+ </Grid>
157
+ ),
158
+ };