@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.
- package/client/App.tsx +0 -2
- package/client/assets/alert/icon-clear.svg +4 -0
- package/client/assets/alert/icon-done.svg +3 -0
- package/client/assets/avatar-identity/photo.png +0 -0
- package/client/assets/avatar-identity/placeholder-icon.svg +8 -0
- package/client/assets/breadcrumb/icon-ellipsis.svg +5 -0
- package/client/assets/breadcrumb/icon-home.svg +3 -0
- package/client/assets/breadcrumb/icon-separator.svg +3 -0
- package/client/assets/button-v01/icon-back.svg +4 -0
- package/client/assets/button-v01/icon-check.svg +3 -0
- package/client/assets/button-v01/icon-close.svg +4 -0
- package/client/assets/button-v01/icon-delete.svg +3 -0
- package/client/assets/button-v01/icon-device.svg +3 -0
- package/client/assets/dropdown/icon-carrot-contract.svg +3 -0
- package/client/assets/dropdown/icon-carrot-expand.svg +3 -0
- package/client/assets/dropdown/icon-clear.svg +4 -0
- package/client/assets/dropdown/icon-enter.svg +3 -0
- package/client/components/icons/UtilityChangeType.tsx +21 -0
- package/client/components/ui/alert-dialog-panel.tsx +246 -0
- package/client/components/ui/alert-v02.tsx +214 -0
- package/client/components/ui/app-bar.tsx +299 -0
- package/client/components/ui/avatar-identity.tsx +122 -0
- package/client/components/ui/banner.tsx +108 -0
- package/client/components/ui/bottom-navigation.tsx +223 -0
- package/client/components/ui/breadcrumb-trail.tsx +170 -0
- package/client/components/ui/button-v01.tsx +238 -0
- package/client/components/ui/button.tsx +2 -0
- package/client/components/ui/card.tsx +108 -26
- package/client/components/ui/code-badge.tsx +62 -0
- package/client/components/ui/date-picker.tsx +188 -0
- package/client/components/ui/dropdown.tsx +448 -0
- package/client/components/ui/empty-state.tsx +197 -0
- package/client/components/ui/file-upload.tsx +214 -0
- package/client/components/ui/footer.tsx +179 -0
- package/client/components/ui/layout.tsx +1182 -0
- package/client/components/ui/pagination-v01.tsx +157 -0
- package/client/components/ui/password-field-v01.tsx +67 -0
- package/client/components/ui/search-field-v01.tsx +192 -0
- package/client/components/ui/section-heading.tsx +49 -0
- package/client/components/ui/sidebar.tsx +2 -3
- package/client/components/ui/standard-navigation.tsx +8 -2
- package/client/components/ui/stepper.tsx +148 -0
- package/client/components/ui/switch-v01.tsx +71 -0
- package/client/components/ui/system-bar.tsx +119 -0
- package/client/components/ui/table-v01.tsx +230 -0
- package/client/components/ui/tabs-v01.tsx +99 -0
- package/client/components/ui/tag-v02.tsx +113 -0
- package/client/components/ui/text-area-v01.tsx +33 -0
- package/client/components/ui/text-field-v01.tsx +108 -0
- package/client/components/ui/timeline.tsx +181 -0
- package/client/components/ui/toast-v01.tsx +206 -0
- package/client/components/ui/tooltip.tsx +264 -71
- package/client/global.css +9565 -4378
- package/client/storybook.css +125 -0
- package/client/ui/Accordion.stories.tsx +1 -1
- package/client/ui/AlertDialogPanel/AlertDialogPanel.stories.tsx +150 -0
- package/client/ui/AlertV02/AlertV02.stories.tsx +188 -0
- package/client/ui/AppBar/app-bar.stories.tsx +280 -0
- package/client/ui/AspectRatio.stories.tsx +1 -1
- package/client/ui/AvatarIdentity/AvatarIdentity.stories.tsx +77 -0
- package/client/ui/Banner/banner.stories.tsx +238 -0
- package/client/ui/BottomNavigation/bottom-navigation.stories.tsx +285 -0
- package/client/ui/BreadcrumbTrail/BreadcrumbTrail.stories.tsx +232 -0
- package/client/ui/Button.stories.tsx +1 -1
- package/client/ui/ButtonV01/ButtonV01.stories.tsx +417 -0
- package/client/ui/Calendar/Calendar.stories.tsx +1 -1
- package/client/ui/Card.stories.tsx +285 -168
- package/client/ui/Carousel/Carousel.stories.tsx +1 -1
- package/client/ui/Chart/Chart.stories.tsx +1 -1
- package/client/ui/Checkbox.stories.tsx +1 -1
- package/client/ui/Collapsible/Collapsible.stories.tsx +1 -1
- package/client/ui/Colors.stories.tsx +1 -1
- package/client/ui/Command/Command.stories.tsx +1 -1
- package/client/ui/ContextMenu/ContextMenu.stories.tsx +1 -1
- package/client/ui/DatePicker/DatePicker.stories.tsx +293 -0
- package/client/ui/Dialog.stories.tsx +1 -1
- package/client/ui/Drawer/Drawer.stories.tsx +1 -1
- package/client/ui/Dropdown/Dropdown.stories.tsx +205 -0
- package/client/ui/EmptyState/empty-state.stories.tsx +251 -0
- package/client/ui/FileUpload/FileUpload.stories.tsx +218 -0
- package/client/ui/Footer/footer.stories.tsx +194 -0
- package/client/ui/Form/Form.stories.tsx +1 -1
- package/client/ui/Hero.stories.tsx +1 -1
- package/client/ui/HoverCard/HoverCard.stories.tsx +1 -1
- package/client/ui/Icons.stories.tsx +1 -1
- package/client/ui/Input.stories.tsx +1 -1
- package/client/ui/InputOTP/InputOTP.stories.tsx +1 -1
- package/client/ui/Label.stories.tsx +1 -1
- package/client/ui/Layout/Center.stories.tsx +100 -0
- package/client/ui/Layout/Columns.stories.tsx +136 -0
- package/client/ui/Layout/Container.stories.tsx +104 -0
- package/client/ui/Layout/FormLayout.stories.tsx +144 -0
- package/client/ui/Layout/Grid.stories.tsx +158 -0
- package/client/ui/Layout/GridSpan.stories.tsx +75 -0
- package/client/ui/Layout/HStack.stories.tsx +128 -0
- package/client/ui/Layout/Layout.stories.tsx +287 -0
- package/client/ui/Layout/LayoutContent.stories.tsx +91 -0
- package/client/ui/Layout/LayoutFooter.stories.tsx +77 -0
- package/client/ui/Layout/LayoutHeader.stories.tsx +104 -0
- package/client/ui/Layout/LayoutPanel.stories.tsx +143 -0
- package/client/ui/Layout/Positioned.stories.tsx +113 -0
- package/client/ui/Layout/Section.stories.tsx +84 -0
- package/client/ui/Layout/ShowHide.stories.tsx +99 -0
- package/client/ui/Layout/Spacer.stories.tsx +149 -0
- package/client/ui/Layout/Stack.stories.tsx +69 -0
- package/client/ui/Layout/StackItem.stories.tsx +124 -0
- package/client/ui/Layout/VStack.stories.tsx +101 -0
- package/client/ui/Layout/controls.ts +33 -0
- package/client/ui/Layout/demo.tsx +37 -0
- package/client/ui/Menubar/Menubar.stories.tsx +1 -1
- package/client/ui/MobileNav.stories.tsx +1 -1
- package/client/ui/Navigation.stories.tsx +1 -1
- package/client/ui/NavigationMenu/NavigationMenu.stories.tsx +1 -1
- package/client/ui/PageHeader.stories.tsx +13 -13
- package/client/ui/Pagination/Pagination.stories.tsx +178 -98
- package/client/ui/Pagination/PaginationLegacy.stories.tsx +121 -0
- package/client/ui/Panel.stories.tsx +1 -1
- package/client/ui/Popover/Popover.stories.tsx +1 -1
- package/client/ui/Progress/Progress.stories.tsx +1 -1
- package/client/ui/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/client/ui/Resizable/Resizable.stories.tsx +1 -1
- package/client/ui/ScrollArea/ScrollArea.stories.tsx +1 -1
- package/client/ui/SearchField/SearchField.stories.tsx +153 -0
- package/client/ui/{SearchField.stories.tsx → SearchField/SearchFieldLegacy.stories.tsx} +2 -2
- package/client/ui/SectionBadge.stories.tsx +1 -1
- package/client/ui/Select.stories.tsx +1 -1
- package/client/ui/Separator/Separator.stories.tsx +1 -1
- package/client/ui/Sheet/Sheet.stories.tsx +1 -1
- package/client/ui/Sidebar/Sidebar.stories.tsx +57 -8
- package/client/ui/Skeleton/Skeleton.stories.tsx +1 -1
- package/client/ui/Slider/Slider.stories.tsx +1 -1
- package/client/ui/StandardNavigation.stories.tsx +1 -1
- package/client/ui/Stepper/Stepper.stories.tsx +344 -0
- package/client/ui/Switch.stories.tsx +1 -1
- package/client/ui/SwitchV01/SwitchV01.stories.tsx +152 -0
- package/client/ui/SystemBar/system-bar.stories.tsx +179 -0
- package/client/ui/Table/TableV01.stories.tsx +256 -0
- package/client/ui/Tabs.stories.tsx +1 -1
- package/client/ui/TabsV01/TabsV01.stories.tsx +144 -0
- package/client/ui/Tag.stories.tsx +1 -1
- package/client/ui/TagV02/TagStatusV02.stories.tsx +132 -0
- package/client/ui/TagV02/TagV02.stories.tsx +142 -0
- package/client/ui/TextAreaV01/TextAreaV01.stories.tsx +146 -0
- package/client/ui/TextFieldV01/PasswordFieldV01.stories.tsx +161 -0
- package/client/ui/TextFieldV01/TextFieldV01.stories.tsx +160 -0
- package/client/ui/Textarea.stories.tsx +1 -1
- package/client/ui/Timeline/timeline.stories.tsx +404 -0
- package/client/ui/Toast/Toast.stories.tsx +1 -1
- package/client/ui/ToastV01/ToastV01.stories.tsx +201 -0
- package/client/ui/Toaster/Toaster.stories.tsx +1 -1
- package/client/ui/Toggle.stories.tsx +1 -1
- package/client/ui/Tooltip.stories.tsx +287 -114
- package/client/ui/Typography.stories.tsx +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +649 -13
- package/dist/index.es.js +4405 -653
- package/package.json +1 -1
- package/client/components/ui/badge.tsx +0 -33
- package/client/components/ui/sonner.tsx +0 -26
- package/client/components/ui/toggle-group.tsx +0 -76
- package/client/ui/Alert/Alert.stories.tsx +0 -82
- package/client/ui/AlertDialog/AlertDialog.stories.tsx +0 -106
- package/client/ui/Avatar/Avatar.stories.tsx +0 -94
- package/client/ui/Badge/Badge.stories.tsx +0 -60
- package/client/ui/Breadcrumb/Breadcrumb.stories.tsx +0 -97
- package/client/ui/DropdownMenu/DropdownMenu.stories.tsx +0 -139
- package/client/ui/Sonner/Sonner.stories.tsx +0 -48
- package/client/ui/Table/Table.stories.tsx +0 -135
- package/client/ui/ToggleGroup/ToggleGroup.stories.tsx +0 -88
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Grid, GridSpan } from "../../components/ui/layout";
|
|
3
|
+
import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
|
|
4
|
+
import { hiddenArgs } from "./controls";
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Components/Layout/GridSpan",
|
|
8
|
+
component: GridSpan,
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: "padded",
|
|
12
|
+
docs: {
|
|
13
|
+
description: {
|
|
14
|
+
component: [
|
|
15
|
+
"Direct child of `Grid`. Spans columns or rows without Tailwind `col-span-*`.",
|
|
16
|
+
"",
|
|
17
|
+
LAYOUT_DOCS_RULE,
|
|
18
|
+
"",
|
|
19
|
+
"```tsx",
|
|
20
|
+
`import { Grid, GridSpan } from "@syscore/ui-library"`,
|
|
21
|
+
"",
|
|
22
|
+
'<Grid columns={3} gap="md">',
|
|
23
|
+
" <GridSpan columns={2}>Wide</GridSpan>",
|
|
24
|
+
" <div>Narrow</div>",
|
|
25
|
+
' <GridSpan columns="full">Full row</GridSpan>',
|
|
26
|
+
"</Grid>",
|
|
27
|
+
"```",
|
|
28
|
+
"",
|
|
29
|
+
"Controls here drive the first cell of the grid below.",
|
|
30
|
+
].join("\n"),
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
argTypes: {
|
|
35
|
+
...hiddenArgs,
|
|
36
|
+
columns: { control: "select", options: [1, 2, 3, "full"] },
|
|
37
|
+
rows: { control: "select", options: [1, 2, 3] },
|
|
38
|
+
},
|
|
39
|
+
args: { columns: 2 },
|
|
40
|
+
} satisfies Meta<typeof GridSpan>;
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
type Story = StoryObj<typeof meta>;
|
|
44
|
+
|
|
45
|
+
export const Default: Story = {
|
|
46
|
+
name: "Column span",
|
|
47
|
+
render: (args) => (
|
|
48
|
+
<Grid columns={3} gap="md" width="100%">
|
|
49
|
+
<GridSpan {...args}>
|
|
50
|
+
<DemoBox label="Spanning cell" tall />
|
|
51
|
+
</GridSpan>
|
|
52
|
+
<DemoBox label="1" tall />
|
|
53
|
+
<DemoBox label="1" tall />
|
|
54
|
+
<GridSpan columns="full">
|
|
55
|
+
<DemoBox label="Full row" />
|
|
56
|
+
</GridSpan>
|
|
57
|
+
</Grid>
|
|
58
|
+
),
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const RowSpan: Story = {
|
|
62
|
+
name: "Row span",
|
|
63
|
+
args: { rows: 2, columns: 1 },
|
|
64
|
+
render: (args) => (
|
|
65
|
+
<Grid columns={3} gap="md" width="100%">
|
|
66
|
+
<GridSpan {...args}>
|
|
67
|
+
<DemoBox label="Spanning cell" tall />
|
|
68
|
+
</GridSpan>
|
|
69
|
+
<DemoBox label="A" />
|
|
70
|
+
<DemoBox label="B" />
|
|
71
|
+
<DemoBox label="C" />
|
|
72
|
+
<DemoBox label="D" />
|
|
73
|
+
</Grid>
|
|
74
|
+
),
|
|
75
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { HStack } from "../../components/ui/layout";
|
|
3
|
+
import { ButtonV01 } from "../../components/ui/button-v01";
|
|
4
|
+
import { Text } from "../../components/ui/typography";
|
|
5
|
+
import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
|
|
6
|
+
import {
|
|
7
|
+
alignControl,
|
|
8
|
+
hiddenArgs,
|
|
9
|
+
justifyControl,
|
|
10
|
+
spaceControl,
|
|
11
|
+
} from "./controls";
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: "Components/Layout/HStack",
|
|
15
|
+
component: HStack,
|
|
16
|
+
tags: ["autodocs"],
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "padded",
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component: [
|
|
22
|
+
"Horizontal stack. Arranges children left to right with a consistent gap.",
|
|
23
|
+
"",
|
|
24
|
+
LAYOUT_DOCS_RULE,
|
|
25
|
+
"",
|
|
26
|
+
"```tsx",
|
|
27
|
+
`import { HStack } from "@syscore/ui-library"`,
|
|
28
|
+
"",
|
|
29
|
+
'<HStack gap="md" align="center">',
|
|
30
|
+
" <Item />",
|
|
31
|
+
" <Item />",
|
|
32
|
+
"</HStack>",
|
|
33
|
+
"```",
|
|
34
|
+
"",
|
|
35
|
+
"`align` is the cross axis (vertical here), `justify` the main axis. Every prop is in the table below — try them in Controls.",
|
|
36
|
+
].join("\n"),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
argTypes: {
|
|
41
|
+
...hiddenArgs,
|
|
42
|
+
gap: spaceControl,
|
|
43
|
+
padding: spaceControl,
|
|
44
|
+
align: alignControl,
|
|
45
|
+
justify: justifyControl,
|
|
46
|
+
wrap: { control: "boolean" },
|
|
47
|
+
isScrollable: { control: "boolean" },
|
|
48
|
+
},
|
|
49
|
+
args: {
|
|
50
|
+
gap: "md",
|
|
51
|
+
align: "center",
|
|
52
|
+
},
|
|
53
|
+
} satisfies Meta<typeof HStack>;
|
|
54
|
+
|
|
55
|
+
export default meta;
|
|
56
|
+
type Story = StoryObj<typeof meta>;
|
|
57
|
+
|
|
58
|
+
export const Default: Story = {
|
|
59
|
+
render: (args) => (
|
|
60
|
+
<HStack {...args}>
|
|
61
|
+
<DemoBox label="Item 1" />
|
|
62
|
+
<DemoBox label="Item 2" />
|
|
63
|
+
<DemoBox label="Item 3" />
|
|
64
|
+
</HStack>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const SpaceBetween: Story = {
|
|
69
|
+
name: "Space between",
|
|
70
|
+
args: { justify: "between", align: "center", width: "100%", padding: "md" },
|
|
71
|
+
parameters: {
|
|
72
|
+
docs: {
|
|
73
|
+
description: {
|
|
74
|
+
story:
|
|
75
|
+
"The page-header pattern: title on the left, actions on the right.",
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
render: (args) => (
|
|
80
|
+
<HStack {...args}>
|
|
81
|
+
<Text variant="heading-xxsmall">Page title</Text>
|
|
82
|
+
<HStack gap="xs">
|
|
83
|
+
<ButtonV01
|
|
84
|
+
typeVariant="utility"
|
|
85
|
+
appearance="solid"
|
|
86
|
+
hierarchy="secondary"
|
|
87
|
+
size="medium"
|
|
88
|
+
>
|
|
89
|
+
Cancel
|
|
90
|
+
</ButtonV01>
|
|
91
|
+
<ButtonV01
|
|
92
|
+
typeVariant="utility"
|
|
93
|
+
appearance="solid"
|
|
94
|
+
context="confirm"
|
|
95
|
+
size="medium"
|
|
96
|
+
>
|
|
97
|
+
Save
|
|
98
|
+
</ButtonV01>
|
|
99
|
+
</HStack>
|
|
100
|
+
</HStack>
|
|
101
|
+
),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const Wrap: Story = {
|
|
105
|
+
args: { gap: "sm", wrap: true, maxWidth: 448 },
|
|
106
|
+
parameters: {
|
|
107
|
+
docs: {
|
|
108
|
+
description: {
|
|
109
|
+
story:
|
|
110
|
+
"With `wrap`, items flow onto a new line instead of overflowing.",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
render: (args) => (
|
|
115
|
+
<HStack {...args}>
|
|
116
|
+
{[
|
|
117
|
+
"Design",
|
|
118
|
+
"Engineering",
|
|
119
|
+
"Product",
|
|
120
|
+
"Marketing",
|
|
121
|
+
"Research",
|
|
122
|
+
"Data",
|
|
123
|
+
].map((tag) => (
|
|
124
|
+
<DemoBox key={tag} label={tag} />
|
|
125
|
+
))}
|
|
126
|
+
</HStack>
|
|
127
|
+
),
|
|
128
|
+
};
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
Grid,
|
|
4
|
+
HStack,
|
|
5
|
+
Layout,
|
|
6
|
+
LayoutContent,
|
|
7
|
+
LayoutFooter,
|
|
8
|
+
LayoutHeader,
|
|
9
|
+
LayoutPanel,
|
|
10
|
+
SPACE_NAMES,
|
|
11
|
+
VStack,
|
|
12
|
+
} from "../../components/ui/layout";
|
|
13
|
+
import { ButtonV01 } from "../../components/ui/button-v01";
|
|
14
|
+
import { Card } from "../../components/ui/card";
|
|
15
|
+
import { Text } from "../../components/ui/typography";
|
|
16
|
+
import { LAYOUT_DOCS_RULE, ShellFrame } from "./demo";
|
|
17
|
+
|
|
18
|
+
const meta = {
|
|
19
|
+
title: "Components/Layout/Layout",
|
|
20
|
+
component: Layout,
|
|
21
|
+
tags: ["autodocs"],
|
|
22
|
+
parameters: {
|
|
23
|
+
layout: "padded",
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component: [
|
|
27
|
+
"Page shell. Regions are children: `LayoutHeader`, `LayoutPanel`, `LayoutContent`, `LayoutFooter`.",
|
|
28
|
+
"",
|
|
29
|
+
LAYOUT_DOCS_RULE,
|
|
30
|
+
"",
|
|
31
|
+
"Use `HStack` / `VStack` / `Grid` *inside* slots. Do not use Layout for a simple row.",
|
|
32
|
+
"",
|
|
33
|
+
"`padding` (default `2xl`) is the horizontal inset for header and footer, and all-sides inset for content. Vertical chrome inset is `--layout-chrome-padding-block`. Panels carry their own `padding` (default `xl`).",
|
|
34
|
+
"",
|
|
35
|
+
'`height="fill"` (default) pins header and footer with the grid. `height="auto"` grows with content; the header is not sticky.',
|
|
36
|
+
"",
|
|
37
|
+
"`contentWidth` caps and centers the main column using `--layout-measure-*`. Below 768px, panels stack full-width above/below content.",
|
|
38
|
+
"",
|
|
39
|
+
"```tsx",
|
|
40
|
+
`import { Layout, LayoutHeader, LayoutPanel, LayoutContent, LayoutFooter } from "@syscore/ui-library"`,
|
|
41
|
+
"",
|
|
42
|
+
'<Layout padding="2xl">',
|
|
43
|
+
" <LayoutHeader>Title</LayoutHeader>",
|
|
44
|
+
" <LayoutPanel>Nav</LayoutPanel>",
|
|
45
|
+
" <LayoutContent>Main</LayoutContent>",
|
|
46
|
+
" <LayoutFooter>Status</LayoutFooter>",
|
|
47
|
+
"</Layout>",
|
|
48
|
+
"```",
|
|
49
|
+
"",
|
|
50
|
+
"Slots take no `className` or `style` — every dimension is a named prop backed by a `--layout-*` variable, so one change in the design system moves every app. Types and defaults are in the table below.",
|
|
51
|
+
].join("\n"),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
argTypes: {
|
|
56
|
+
padding: { control: "select", options: [...SPACE_NAMES] },
|
|
57
|
+
height: { control: "select", options: ["fill", "auto"] },
|
|
58
|
+
contentWidth: { control: "select", options: ["sm", "md", "lg", "full"] },
|
|
59
|
+
},
|
|
60
|
+
args: {
|
|
61
|
+
padding: "2xl",
|
|
62
|
+
height: "fill",
|
|
63
|
+
},
|
|
64
|
+
} satisfies Meta<typeof Layout>;
|
|
65
|
+
|
|
66
|
+
export default meta;
|
|
67
|
+
type Story = StoryObj<typeof meta>;
|
|
68
|
+
|
|
69
|
+
const nav = ["Dashboard", "Projects", "Reports", "Settings"];
|
|
70
|
+
|
|
71
|
+
export const Default: Story = {
|
|
72
|
+
render: (args) => (
|
|
73
|
+
<ShellFrame>
|
|
74
|
+
<Layout {...args}>
|
|
75
|
+
<LayoutHeader>
|
|
76
|
+
<HStack justify="between" align="center" width="100%">
|
|
77
|
+
<Text variant="heading-xxsmall">WELL App</Text>
|
|
78
|
+
<ButtonV01
|
|
79
|
+
typeVariant="utility"
|
|
80
|
+
appearance="solid"
|
|
81
|
+
context="confirm"
|
|
82
|
+
size="medium"
|
|
83
|
+
>
|
|
84
|
+
Sign in
|
|
85
|
+
</ButtonV01>
|
|
86
|
+
</HStack>
|
|
87
|
+
</LayoutHeader>
|
|
88
|
+
<LayoutPanel>
|
|
89
|
+
<VStack gap="sm">
|
|
90
|
+
{nav.map((item) => (
|
|
91
|
+
<Text key={item} variant="body-small">
|
|
92
|
+
{item}
|
|
93
|
+
</Text>
|
|
94
|
+
))}
|
|
95
|
+
</VStack>
|
|
96
|
+
</LayoutPanel>
|
|
97
|
+
<LayoutContent>
|
|
98
|
+
<VStack gap="xl">
|
|
99
|
+
<Text variant="heading-xsmall">Dashboard</Text>
|
|
100
|
+
<Grid columns={3} gap="lg">
|
|
101
|
+
{[
|
|
102
|
+
{ label: "Projects", value: "2,847" },
|
|
103
|
+
{ label: "Score", value: "94%" },
|
|
104
|
+
{ label: "Issues", value: "18" },
|
|
105
|
+
].map((item) => (
|
|
106
|
+
<Card key={item.label} variant="outlined">
|
|
107
|
+
<VStack gap="xs">
|
|
108
|
+
<Text variant="overline-small">{item.label}</Text>
|
|
109
|
+
<Text variant="heading-xsmall">{item.value}</Text>
|
|
110
|
+
</VStack>
|
|
111
|
+
</Card>
|
|
112
|
+
))}
|
|
113
|
+
</Grid>
|
|
114
|
+
</VStack>
|
|
115
|
+
</LayoutContent>
|
|
116
|
+
<LayoutFooter>
|
|
117
|
+
<HStack justify="between" align="center" width="100%">
|
|
118
|
+
<Text variant="body-small">Last saved 2 minutes ago</Text>
|
|
119
|
+
<Text variant="body-small">Ready</Text>
|
|
120
|
+
</HStack>
|
|
121
|
+
</LayoutFooter>
|
|
122
|
+
</Layout>
|
|
123
|
+
</ShellFrame>
|
|
124
|
+
),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const StartAndEnd: Story = {
|
|
128
|
+
name: "Start and end panels",
|
|
129
|
+
render: (args) => (
|
|
130
|
+
<ShellFrame>
|
|
131
|
+
<Layout {...args}>
|
|
132
|
+
<LayoutHeader>
|
|
133
|
+
<HStack justify="between" align="center" width="100%">
|
|
134
|
+
<Text variant="heading-xxsmall">Inspector layout</Text>
|
|
135
|
+
</HStack>
|
|
136
|
+
</LayoutHeader>
|
|
137
|
+
<LayoutPanel>
|
|
138
|
+
<VStack gap="sm">
|
|
139
|
+
{nav.map((item) => (
|
|
140
|
+
<Text key={item} variant="body-small">
|
|
141
|
+
{item}
|
|
142
|
+
</Text>
|
|
143
|
+
))}
|
|
144
|
+
</VStack>
|
|
145
|
+
</LayoutPanel>
|
|
146
|
+
<LayoutContent>
|
|
147
|
+
<VStack gap="sm">
|
|
148
|
+
<Text variant="heading-xsmall">Main content</Text>
|
|
149
|
+
<Text variant="body-small">
|
|
150
|
+
Select an item in the inspector to see details.
|
|
151
|
+
</Text>
|
|
152
|
+
</VStack>
|
|
153
|
+
</LayoutContent>
|
|
154
|
+
<LayoutPanel placement="end" width="narrow">
|
|
155
|
+
<VStack gap="sm">
|
|
156
|
+
<Text variant="overline-small">Inspector</Text>
|
|
157
|
+
<Text variant="body-small">Selected item details</Text>
|
|
158
|
+
</VStack>
|
|
159
|
+
</LayoutPanel>
|
|
160
|
+
</Layout>
|
|
161
|
+
</ShellFrame>
|
|
162
|
+
),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const HeaderAndContent: Story = {
|
|
166
|
+
name: "Header and content only",
|
|
167
|
+
render: (args) => (
|
|
168
|
+
<ShellFrame height={280}>
|
|
169
|
+
<Layout {...args}>
|
|
170
|
+
<LayoutHeader>
|
|
171
|
+
<HStack justify="between" align="center" width="100%">
|
|
172
|
+
<Text variant="heading-xxsmall">Settings</Text>
|
|
173
|
+
</HStack>
|
|
174
|
+
</LayoutHeader>
|
|
175
|
+
<LayoutContent>
|
|
176
|
+
<VStack gap="sm">
|
|
177
|
+
<Text variant="heading-xsmall">No sidebar</Text>
|
|
178
|
+
<Text variant="body-small">
|
|
179
|
+
Omit LayoutPanel when you do not need one. Content fills the
|
|
180
|
+
width.
|
|
181
|
+
</Text>
|
|
182
|
+
</VStack>
|
|
183
|
+
</LayoutContent>
|
|
184
|
+
</Layout>
|
|
185
|
+
</ShellFrame>
|
|
186
|
+
),
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export const CappedContent: Story = {
|
|
190
|
+
name: "Capped content",
|
|
191
|
+
args: { contentWidth: "sm" },
|
|
192
|
+
render: (args) => (
|
|
193
|
+
<ShellFrame height={280}>
|
|
194
|
+
<Layout {...args}>
|
|
195
|
+
<LayoutHeader>
|
|
196
|
+
<HStack justify="between" align="center" width="100%">
|
|
197
|
+
<Text variant="heading-xxsmall">Settings</Text>
|
|
198
|
+
</HStack>
|
|
199
|
+
</LayoutHeader>
|
|
200
|
+
<LayoutContent>
|
|
201
|
+
<VStack gap="sm">
|
|
202
|
+
<Text variant="heading-xsmall">Capped column</Text>
|
|
203
|
+
<Text variant="body-small">
|
|
204
|
+
contentWidth="sm" caps the main column at --layout-measure-sm and
|
|
205
|
+
centers it.
|
|
206
|
+
</Text>
|
|
207
|
+
</VStack>
|
|
208
|
+
</LayoutContent>
|
|
209
|
+
</Layout>
|
|
210
|
+
</ShellFrame>
|
|
211
|
+
),
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export const AutoHeight: Story = {
|
|
215
|
+
name: "Height auto",
|
|
216
|
+
args: { height: "auto" },
|
|
217
|
+
parameters: {
|
|
218
|
+
docs: {
|
|
219
|
+
description: {
|
|
220
|
+
story:
|
|
221
|
+
'`height="auto"` grows with content instead of filling its parent. Header and footer are no longer pinned — they scroll with the page, so use it for document-style pages, not app shells.',
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
render: (args) => (
|
|
226
|
+
<div style={{ height: 280, overflowY: "auto" }} className="sb-shell-frame">
|
|
227
|
+
<Layout {...args}>
|
|
228
|
+
<LayoutHeader>
|
|
229
|
+
<HStack justify="between" align="center" width="100%">
|
|
230
|
+
<Text variant="heading-xxsmall">Scrolls away</Text>
|
|
231
|
+
</HStack>
|
|
232
|
+
</LayoutHeader>
|
|
233
|
+
<LayoutContent isScrollable={false}>
|
|
234
|
+
<VStack gap="md">
|
|
235
|
+
{Array.from({ length: 8 }, (_, i) => (
|
|
236
|
+
<Text key={i} variant="body-small">
|
|
237
|
+
Paragraph {i + 1} — the whole page scrolls, header included.
|
|
238
|
+
</Text>
|
|
239
|
+
))}
|
|
240
|
+
</VStack>
|
|
241
|
+
</LayoutContent>
|
|
242
|
+
<LayoutFooter>
|
|
243
|
+
<Text variant="body-small">End of document</Text>
|
|
244
|
+
</LayoutFooter>
|
|
245
|
+
</Layout>
|
|
246
|
+
</div>
|
|
247
|
+
),
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
export const MobileCollapse: Story = {
|
|
251
|
+
name: "Mobile (panels stack)",
|
|
252
|
+
parameters: {
|
|
253
|
+
viewport: { defaultViewport: "mobile1" },
|
|
254
|
+
docs: {
|
|
255
|
+
description: {
|
|
256
|
+
story:
|
|
257
|
+
"Below 768px the three-column grid becomes one column: start panel, content, end panel, each full width. Panels cap at 40vh so content is always reachable.",
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
render: (args) => (
|
|
262
|
+
<ShellFrame height={520}>
|
|
263
|
+
<Layout {...args}>
|
|
264
|
+
<LayoutHeader>
|
|
265
|
+
<Text variant="heading-xxsmall">Narrow viewport</Text>
|
|
266
|
+
</LayoutHeader>
|
|
267
|
+
<LayoutPanel>
|
|
268
|
+
<VStack gap="sm">
|
|
269
|
+
{nav.map((item) => (
|
|
270
|
+
<Text key={item} variant="body-small">
|
|
271
|
+
{item}
|
|
272
|
+
</Text>
|
|
273
|
+
))}
|
|
274
|
+
</VStack>
|
|
275
|
+
</LayoutPanel>
|
|
276
|
+
<LayoutContent>
|
|
277
|
+
<Text variant="body-small">
|
|
278
|
+
The nav sits above this content instead of beside it.
|
|
279
|
+
</Text>
|
|
280
|
+
</LayoutContent>
|
|
281
|
+
<LayoutFooter>
|
|
282
|
+
<Text variant="body-small">Ready</Text>
|
|
283
|
+
</LayoutFooter>
|
|
284
|
+
</Layout>
|
|
285
|
+
</ShellFrame>
|
|
286
|
+
),
|
|
287
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
HStack,
|
|
4
|
+
Layout,
|
|
5
|
+
LayoutContent,
|
|
6
|
+
LayoutHeader,
|
|
7
|
+
VStack,
|
|
8
|
+
} from "../../components/ui/layout";
|
|
9
|
+
import { Text } from "../../components/ui/typography";
|
|
10
|
+
import { DemoBox, ShellFrame } from "./demo";
|
|
11
|
+
|
|
12
|
+
const meta = {
|
|
13
|
+
title: "Components/Layout/LayoutContent",
|
|
14
|
+
component: LayoutContent,
|
|
15
|
+
tags: ["autodocs"],
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: "padded",
|
|
18
|
+
docs: {
|
|
19
|
+
description: {
|
|
20
|
+
component: [
|
|
21
|
+
"Main region of `Layout`. Renders as `<main>`. All-sides inset comes from `Layout padding`.",
|
|
22
|
+
"",
|
|
23
|
+
'`isScrollable` (default `true`) scrolls this region only, so header and footer stay put when Layout `height="fill"`.',
|
|
24
|
+
"",
|
|
25
|
+
"```tsx",
|
|
26
|
+
"<LayoutContent isScrollable>",
|
|
27
|
+
' <VStack gap="md">…</VStack>',
|
|
28
|
+
"</LayoutContent>",
|
|
29
|
+
"```",
|
|
30
|
+
"",
|
|
31
|
+
"Takes no `className` or `style` — sizing comes from `Layout` and `--layout-*` variables, so a design-system change reaches every app.",
|
|
32
|
+
"",
|
|
33
|
+
].join("\n"),
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
argTypes: {
|
|
38
|
+
isScrollable: { control: "boolean" },
|
|
39
|
+
as: { control: "select", options: ["main", "div"] },
|
|
40
|
+
},
|
|
41
|
+
args: {
|
|
42
|
+
isScrollable: true,
|
|
43
|
+
},
|
|
44
|
+
} satisfies Meta<typeof LayoutContent>;
|
|
45
|
+
|
|
46
|
+
export default meta;
|
|
47
|
+
type Story = StoryObj<typeof meta>;
|
|
48
|
+
|
|
49
|
+
export const Default: Story = {
|
|
50
|
+
name: "Scrolls",
|
|
51
|
+
render: (args) => (
|
|
52
|
+
<ShellFrame height={320}>
|
|
53
|
+
<Layout>
|
|
54
|
+
<LayoutHeader>
|
|
55
|
+
<HStack justify="between" align="center" width="100%">
|
|
56
|
+
<Text variant="heading-xxsmall">Scroll the content</Text>
|
|
57
|
+
</HStack>
|
|
58
|
+
</LayoutHeader>
|
|
59
|
+
<LayoutContent {...args}>
|
|
60
|
+
<VStack gap="md">
|
|
61
|
+
{Array.from({ length: 8 }, (_, i) => (
|
|
62
|
+
<DemoBox key={i} label={`Block ${i + 1}`} />
|
|
63
|
+
))}
|
|
64
|
+
</VStack>
|
|
65
|
+
</LayoutContent>
|
|
66
|
+
</Layout>
|
|
67
|
+
</ShellFrame>
|
|
68
|
+
),
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const NotScrollable: Story = {
|
|
72
|
+
args: { isScrollable: false },
|
|
73
|
+
render: (args) => (
|
|
74
|
+
<ShellFrame height={320}>
|
|
75
|
+
<Layout>
|
|
76
|
+
<LayoutHeader>
|
|
77
|
+
<HStack justify="between" align="center" width="100%">
|
|
78
|
+
<Text variant="heading-xxsmall">No isolated scroll</Text>
|
|
79
|
+
</HStack>
|
|
80
|
+
</LayoutHeader>
|
|
81
|
+
<LayoutContent {...args}>
|
|
82
|
+
<VStack gap="md">
|
|
83
|
+
{Array.from({ length: 8 }, (_, i) => (
|
|
84
|
+
<DemoBox key={i} label={`Block ${i + 1}`} />
|
|
85
|
+
))}
|
|
86
|
+
</VStack>
|
|
87
|
+
</LayoutContent>
|
|
88
|
+
</Layout>
|
|
89
|
+
</ShellFrame>
|
|
90
|
+
),
|
|
91
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
HStack,
|
|
4
|
+
Layout,
|
|
5
|
+
LayoutContent,
|
|
6
|
+
LayoutFooter,
|
|
7
|
+
LayoutHeader,
|
|
8
|
+
VStack,
|
|
9
|
+
} from "../../components/ui/layout";
|
|
10
|
+
import { Text } from "../../components/ui/typography";
|
|
11
|
+
import { DemoBox, ShellFrame } from "./demo";
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: "Components/Layout/LayoutFooter",
|
|
15
|
+
component: LayoutFooter,
|
|
16
|
+
tags: ["autodocs"],
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "padded",
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component: [
|
|
22
|
+
"Bottom region of `Layout`. Put `HStack` inside for status and actions.",
|
|
23
|
+
"",
|
|
24
|
+
'Pinned by Layout’s grid while `height="fill"` and content is `isScrollable`. Not CSS `position: sticky`.',
|
|
25
|
+
"",
|
|
26
|
+
"Horizontal inset comes from `Layout padding`; vertical inset from `--layout-chrome-padding-block`. Height floor is `--layout-footer-min-height`.",
|
|
27
|
+
"",
|
|
28
|
+
"```tsx",
|
|
29
|
+
"<LayoutFooter>",
|
|
30
|
+
' <HStack justify="between" align="center" width="100%">',
|
|
31
|
+
" <Text>Status</Text>",
|
|
32
|
+
" </HStack>",
|
|
33
|
+
"</LayoutFooter>",
|
|
34
|
+
"```",
|
|
35
|
+
"",
|
|
36
|
+
"Takes no `className` or `style` — sizing comes from `Layout` and `--layout-*` variables, so a design-system change reaches every app.",
|
|
37
|
+
"",
|
|
38
|
+
].join("\n"),
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
argTypes: {
|
|
43
|
+
as: { control: "select", options: ["footer", "div"] },
|
|
44
|
+
},
|
|
45
|
+
} satisfies Meta<typeof LayoutFooter>;
|
|
46
|
+
|
|
47
|
+
export default meta;
|
|
48
|
+
type Story = StoryObj<typeof meta>;
|
|
49
|
+
|
|
50
|
+
export const Default: Story = {
|
|
51
|
+
name: "Pinned while content scrolls",
|
|
52
|
+
args: { as: "footer" },
|
|
53
|
+
render: (args) => (
|
|
54
|
+
<ShellFrame height={320}>
|
|
55
|
+
<Layout>
|
|
56
|
+
<LayoutHeader>
|
|
57
|
+
<HStack justify="between" align="center" width="100%">
|
|
58
|
+
<Text variant="heading-xxsmall">Project</Text>
|
|
59
|
+
</HStack>
|
|
60
|
+
</LayoutHeader>
|
|
61
|
+
<LayoutContent>
|
|
62
|
+
<VStack gap="md">
|
|
63
|
+
{Array.from({ length: 8 }, (_, i) => (
|
|
64
|
+
<DemoBox key={i} label={`Block ${i + 1}`} />
|
|
65
|
+
))}
|
|
66
|
+
</VStack>
|
|
67
|
+
</LayoutContent>
|
|
68
|
+
<LayoutFooter {...args}>
|
|
69
|
+
<HStack justify="between" align="center" width="100%">
|
|
70
|
+
<Text variant="body-small">Last saved 2 minutes ago</Text>
|
|
71
|
+
<Text variant="body-small">Ready</Text>
|
|
72
|
+
</HStack>
|
|
73
|
+
</LayoutFooter>
|
|
74
|
+
</Layout>
|
|
75
|
+
</ShellFrame>
|
|
76
|
+
),
|
|
77
|
+
};
|