@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,104 @@
|
|
|
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 { ButtonV01 } from "../../components/ui/button-v01";
|
|
10
|
+
import { Text } from "../../components/ui/typography";
|
|
11
|
+
import { ShellFrame } from "./demo";
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: "Components/Layout/LayoutHeader",
|
|
15
|
+
component: LayoutHeader,
|
|
16
|
+
tags: ["autodocs"],
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: "padded",
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component: [
|
|
22
|
+
"Top region of `Layout`. Put `HStack` inside for title + actions, or a `VStack` for a second row (breadcrumb, tabs).",
|
|
23
|
+
"",
|
|
24
|
+
'Pinned by Layout’s grid while `height="fill"`. Not CSS `position: sticky` — with `height="auto"` the header scrolls away.',
|
|
25
|
+
"",
|
|
26
|
+
"Horizontal inset comes from `Layout padding`; vertical inset from `--layout-chrome-padding-block`. Height floor is `--layout-header-min-height`.",
|
|
27
|
+
"",
|
|
28
|
+
"```tsx",
|
|
29
|
+
"<LayoutHeader>",
|
|
30
|
+
' <HStack justify="between" align="center" width="100%">',
|
|
31
|
+
" <Text>Title</Text>",
|
|
32
|
+
" </HStack>",
|
|
33
|
+
"</LayoutHeader>",
|
|
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: ["header", "div"] },
|
|
44
|
+
},
|
|
45
|
+
} satisfies Meta<typeof LayoutHeader>;
|
|
46
|
+
|
|
47
|
+
export default meta;
|
|
48
|
+
type Story = StoryObj<typeof meta>;
|
|
49
|
+
|
|
50
|
+
export const Default: Story = {
|
|
51
|
+
args: { as: "header" },
|
|
52
|
+
render: (args) => (
|
|
53
|
+
<ShellFrame height={280}>
|
|
54
|
+
<Layout>
|
|
55
|
+
<LayoutHeader {...args}>
|
|
56
|
+
<HStack justify="between" align="center" width="100%">
|
|
57
|
+
<Text variant="heading-xxsmall">Page title</Text>
|
|
58
|
+
<ButtonV01
|
|
59
|
+
typeVariant="utility"
|
|
60
|
+
appearance="solid"
|
|
61
|
+
hierarchy="secondary"
|
|
62
|
+
size="medium"
|
|
63
|
+
>
|
|
64
|
+
Edit
|
|
65
|
+
</ButtonV01>
|
|
66
|
+
</HStack>
|
|
67
|
+
</LayoutHeader>
|
|
68
|
+
<LayoutContent>
|
|
69
|
+
<Text variant="body-small">Main</Text>
|
|
70
|
+
</LayoutContent>
|
|
71
|
+
</Layout>
|
|
72
|
+
</ShellFrame>
|
|
73
|
+
),
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const TwoRows: Story = {
|
|
77
|
+
name: "Title and breadcrumb",
|
|
78
|
+
args: { as: "header" },
|
|
79
|
+
render: (args) => (
|
|
80
|
+
<ShellFrame height={280}>
|
|
81
|
+
<Layout>
|
|
82
|
+
<LayoutHeader {...args}>
|
|
83
|
+
<VStack gap="xs" width="100%">
|
|
84
|
+
<Text variant="body-small">Projects / North campus</Text>
|
|
85
|
+
<HStack justify="between" align="center" width="100%">
|
|
86
|
+
<Text variant="heading-xxsmall">Building audit</Text>
|
|
87
|
+
<ButtonV01
|
|
88
|
+
typeVariant="utility"
|
|
89
|
+
appearance="solid"
|
|
90
|
+
context="confirm"
|
|
91
|
+
size="medium"
|
|
92
|
+
>
|
|
93
|
+
Save
|
|
94
|
+
</ButtonV01>
|
|
95
|
+
</HStack>
|
|
96
|
+
</VStack>
|
|
97
|
+
</LayoutHeader>
|
|
98
|
+
<LayoutContent>
|
|
99
|
+
<Text variant="body-small">Main</Text>
|
|
100
|
+
</LayoutContent>
|
|
101
|
+
</Layout>
|
|
102
|
+
</ShellFrame>
|
|
103
|
+
),
|
|
104
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
HStack,
|
|
4
|
+
Layout,
|
|
5
|
+
LayoutContent,
|
|
6
|
+
LayoutHeader,
|
|
7
|
+
LayoutPanel,
|
|
8
|
+
SPACE_NAMES,
|
|
9
|
+
VStack,
|
|
10
|
+
} from "../../components/ui/layout";
|
|
11
|
+
import { Text } from "../../components/ui/typography";
|
|
12
|
+
import { ShellFrame } from "./demo";
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: "Components/Layout/LayoutPanel",
|
|
16
|
+
component: LayoutPanel,
|
|
17
|
+
tags: ["autodocs"],
|
|
18
|
+
parameters: {
|
|
19
|
+
layout: "padded",
|
|
20
|
+
docs: {
|
|
21
|
+
description: {
|
|
22
|
+
component: [
|
|
23
|
+
'Sidebar region of `Layout`. `placement="start"` is left in LTR; `"end"` is right.',
|
|
24
|
+
"",
|
|
25
|
+
"Padded by its own `padding` (default `xl`, `--layout-panel-padding`) — not by `Layout padding`.",
|
|
26
|
+
"",
|
|
27
|
+
"`width` is a named size backed by `--layout-panel-width-*`: `narrow` 12.5rem, `default` 17.5rem, `wide` 22.5rem. No px — change the variable and every panel in every app moves.",
|
|
28
|
+
"",
|
|
29
|
+
"Below 768px panels stack full-width above/below content.",
|
|
30
|
+
"",
|
|
31
|
+
"```tsx",
|
|
32
|
+
"<LayoutPanel>Nav</LayoutPanel>",
|
|
33
|
+
'<LayoutPanel placement="end" width="narrow">Inspector</LayoutPanel>',
|
|
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
|
+
"`width` and `padding` show no default in the table below because theirs live in CSS: `--layout-panel-width-default` and `--layout-panel-padding`. Leave them unset to inherit.",
|
|
39
|
+
"",
|
|
40
|
+
].join("\n"),
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
argTypes: {
|
|
45
|
+
placement: { control: "select", options: ["start", "end"] },
|
|
46
|
+
width: { control: "select", options: ["narrow", "default", "wide"] },
|
|
47
|
+
padding: { control: "select", options: [...SPACE_NAMES] },
|
|
48
|
+
isScrollable: { control: "boolean" },
|
|
49
|
+
as: { control: "select", options: ["aside", "nav", "div"] },
|
|
50
|
+
},
|
|
51
|
+
args: {
|
|
52
|
+
placement: "start",
|
|
53
|
+
isScrollable: true,
|
|
54
|
+
},
|
|
55
|
+
} satisfies Meta<typeof LayoutPanel>;
|
|
56
|
+
|
|
57
|
+
export default meta;
|
|
58
|
+
type Story = StoryObj<typeof meta>;
|
|
59
|
+
|
|
60
|
+
export const Default: Story = {
|
|
61
|
+
name: "Start",
|
|
62
|
+
render: (args) => (
|
|
63
|
+
<ShellFrame height={320}>
|
|
64
|
+
<Layout>
|
|
65
|
+
<LayoutHeader>
|
|
66
|
+
<HStack justify="between" align="center" width="100%">
|
|
67
|
+
<Text variant="heading-xxsmall">Start panel</Text>
|
|
68
|
+
</HStack>
|
|
69
|
+
</LayoutHeader>
|
|
70
|
+
<LayoutPanel {...args}>
|
|
71
|
+
<VStack gap="sm">
|
|
72
|
+
<Text variant="body-small">Dashboard</Text>
|
|
73
|
+
<Text variant="body-small">Projects</Text>
|
|
74
|
+
<Text variant="body-small">Settings</Text>
|
|
75
|
+
</VStack>
|
|
76
|
+
</LayoutPanel>
|
|
77
|
+
<LayoutContent>
|
|
78
|
+
<VStack gap="sm">
|
|
79
|
+
<Text variant="heading-xsmall">Main</Text>
|
|
80
|
+
<Text variant="body-small">
|
|
81
|
+
Nav sits in the start panel. Try width and padding in Controls.
|
|
82
|
+
</Text>
|
|
83
|
+
</VStack>
|
|
84
|
+
</LayoutContent>
|
|
85
|
+
</Layout>
|
|
86
|
+
</ShellFrame>
|
|
87
|
+
),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const End: Story = {
|
|
91
|
+
args: { placement: "end", width: "narrow" },
|
|
92
|
+
render: (args) => (
|
|
93
|
+
<ShellFrame height={320}>
|
|
94
|
+
<Layout>
|
|
95
|
+
<LayoutHeader>
|
|
96
|
+
<HStack justify="between" align="center" width="100%">
|
|
97
|
+
<Text variant="heading-xxsmall">End panel</Text>
|
|
98
|
+
</HStack>
|
|
99
|
+
</LayoutHeader>
|
|
100
|
+
<LayoutContent>
|
|
101
|
+
<VStack gap="sm">
|
|
102
|
+
<Text variant="heading-xsmall">Main</Text>
|
|
103
|
+
<Text variant="body-small">Inspector sits in the end panel.</Text>
|
|
104
|
+
</VStack>
|
|
105
|
+
</LayoutContent>
|
|
106
|
+
<LayoutPanel {...args}>
|
|
107
|
+
<VStack gap="sm">
|
|
108
|
+
<Text variant="overline-small">Inspector</Text>
|
|
109
|
+
<Text variant="body-small">Details</Text>
|
|
110
|
+
</VStack>
|
|
111
|
+
</LayoutPanel>
|
|
112
|
+
</Layout>
|
|
113
|
+
</ShellFrame>
|
|
114
|
+
),
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const LongNav: Story = {
|
|
118
|
+
name: "Long nav scrolls",
|
|
119
|
+
args: { isScrollable: true },
|
|
120
|
+
render: (args) => (
|
|
121
|
+
<ShellFrame height={320}>
|
|
122
|
+
<Layout>
|
|
123
|
+
<LayoutHeader>
|
|
124
|
+
<HStack justify="between" align="center" width="100%">
|
|
125
|
+
<Text variant="heading-xxsmall">Scrollable panel</Text>
|
|
126
|
+
</HStack>
|
|
127
|
+
</LayoutHeader>
|
|
128
|
+
<LayoutPanel {...args}>
|
|
129
|
+
<VStack gap="sm">
|
|
130
|
+
{Array.from({ length: 16 }, (_, i) => (
|
|
131
|
+
<Text key={i} variant="body-small">
|
|
132
|
+
Nav item {i + 1}
|
|
133
|
+
</Text>
|
|
134
|
+
))}
|
|
135
|
+
</VStack>
|
|
136
|
+
</LayoutPanel>
|
|
137
|
+
<LayoutContent>
|
|
138
|
+
<Text variant="body-small">The start panel scrolls on its own.</Text>
|
|
139
|
+
</LayoutContent>
|
|
140
|
+
</Layout>
|
|
141
|
+
</ShellFrame>
|
|
142
|
+
),
|
|
143
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Positioned, 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/Positioned",
|
|
9
|
+
component: Positioned,
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: "padded",
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component: [
|
|
16
|
+
"CSS positioning without Tailwind `absolute top-0`. Badges, overlays, sticky bars.",
|
|
17
|
+
"",
|
|
18
|
+
LAYOUT_DOCS_RULE,
|
|
19
|
+
"",
|
|
20
|
+
"```tsx",
|
|
21
|
+
`import { Positioned } from "@syscore/ui-library"`,
|
|
22
|
+
"",
|
|
23
|
+
'<Positioned position="relative">',
|
|
24
|
+
' <Positioned position="absolute" top={8} right={8}>',
|
|
25
|
+
" <Badge />",
|
|
26
|
+
" </Positioned>",
|
|
27
|
+
"</Positioned>",
|
|
28
|
+
"```",
|
|
29
|
+
"",
|
|
30
|
+
"`fill` is shorthand for `inset: 0` — an overlay covering its positioned parent. `inset` sets all four sides at once.",
|
|
31
|
+
"",
|
|
32
|
+
"Offsets are raw CSS lengths, not tokens: a number is treated as px. Keep them small and incidental — anything structural belongs on a stack or grid.",
|
|
33
|
+
].join("\n"),
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
argTypes: {
|
|
38
|
+
...hiddenArgs,
|
|
39
|
+
position: {
|
|
40
|
+
control: "inline-radio",
|
|
41
|
+
options: ["relative", "absolute", "fixed", "sticky"],
|
|
42
|
+
},
|
|
43
|
+
fill: { control: "boolean" },
|
|
44
|
+
zIndex: { control: "number" },
|
|
45
|
+
},
|
|
46
|
+
args: { position: "absolute", top: 8, right: 8 },
|
|
47
|
+
} satisfies Meta<typeof Positioned>;
|
|
48
|
+
|
|
49
|
+
export default meta;
|
|
50
|
+
type Story = StoryObj<typeof meta>;
|
|
51
|
+
|
|
52
|
+
export const Default: Story = {
|
|
53
|
+
name: "Corner badge",
|
|
54
|
+
render: (args) => (
|
|
55
|
+
<Positioned position="relative">
|
|
56
|
+
<DemoBox label="Positioned parent" tall />
|
|
57
|
+
<Positioned {...args}>
|
|
58
|
+
<Text variant="overline-small">NEW</Text>
|
|
59
|
+
</Positioned>
|
|
60
|
+
</Positioned>
|
|
61
|
+
),
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const Overlay: Story = {
|
|
65
|
+
args: { position: "absolute", fill: true, top: undefined, right: undefined },
|
|
66
|
+
parameters: {
|
|
67
|
+
docs: {
|
|
68
|
+
description: {
|
|
69
|
+
story:
|
|
70
|
+
"`fill` covers the positioned parent — loading and disabled states.",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
render: (args) => (
|
|
75
|
+
<Positioned position="relative">
|
|
76
|
+
<DemoBox label="Content underneath" tall />
|
|
77
|
+
<Positioned {...args}>
|
|
78
|
+
<VStack
|
|
79
|
+
align="center"
|
|
80
|
+
justify="center"
|
|
81
|
+
height="100%"
|
|
82
|
+
className="sb-fill"
|
|
83
|
+
>
|
|
84
|
+
<Text variant="body-small">Overlay</Text>
|
|
85
|
+
</VStack>
|
|
86
|
+
</Positioned>
|
|
87
|
+
</Positioned>
|
|
88
|
+
),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const Sticky: Story = {
|
|
92
|
+
args: { position: "sticky", top: 0, right: undefined, zIndex: 1 },
|
|
93
|
+
parameters: {
|
|
94
|
+
docs: {
|
|
95
|
+
description: {
|
|
96
|
+
story:
|
|
97
|
+
"A sticky bar inside a scrolling region. Scroll the box to pin it.",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
render: (args) => (
|
|
102
|
+
<VStack height={240} isScrollable gap="sm" width="100%" maxWidth={480}>
|
|
103
|
+
<Positioned {...args}>
|
|
104
|
+
<VStack className="sb-fill" padding="sm">
|
|
105
|
+
<Text variant="body-small">Sticky header</Text>
|
|
106
|
+
</VStack>
|
|
107
|
+
</Positioned>
|
|
108
|
+
{Array.from({ length: 10 }, (_, i) => (
|
|
109
|
+
<DemoBox key={i} label={`Row ${i + 1}`} />
|
|
110
|
+
))}
|
|
111
|
+
</VStack>
|
|
112
|
+
),
|
|
113
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Section, VStack } from "../../components/ui/layout";
|
|
3
|
+
import { Text } from "../../components/ui/typography";
|
|
4
|
+
import { LAYOUT_DOCS_RULE } from "./demo";
|
|
5
|
+
import { hiddenArgs } from "./controls";
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Components/Layout/Section",
|
|
9
|
+
component: Section,
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: "padded",
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component: [
|
|
16
|
+
"Vertical padding between page sections. Pair with `Center` or `Layout contentWidth` for max-width.",
|
|
17
|
+
"",
|
|
18
|
+
LAYOUT_DOCS_RULE,
|
|
19
|
+
"",
|
|
20
|
+
"```tsx",
|
|
21
|
+
`import { Section } from "@syscore/ui-library"`,
|
|
22
|
+
"",
|
|
23
|
+
'<Section padding="lg">',
|
|
24
|
+
" <h1>Features</h1>",
|
|
25
|
+
"</Section>",
|
|
26
|
+
"```",
|
|
27
|
+
"",
|
|
28
|
+
"Padding is responsive — it grows at 768px, so a section breathes on desktop without a breakpoint prop.",
|
|
29
|
+
"",
|
|
30
|
+
"| `padding` | Mobile | Desktop |",
|
|
31
|
+
"|-----------|--------|---------|",
|
|
32
|
+
"| `sm` | 2rem | 3rem |",
|
|
33
|
+
"| `md` | 3rem | 4rem |",
|
|
34
|
+
"| `lg` (default) | 4rem | 6rem |",
|
|
35
|
+
"| `xl` | 6rem | 8rem |",
|
|
36
|
+
"| `none` | 0 | 0 |",
|
|
37
|
+
].join("\n"),
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
argTypes: {
|
|
42
|
+
...hiddenArgs,
|
|
43
|
+
padding: {
|
|
44
|
+
control: "inline-radio",
|
|
45
|
+
options: ["none", "sm", "md", "lg", "xl"],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
args: { padding: "lg" },
|
|
49
|
+
} satisfies Meta<typeof Section>;
|
|
50
|
+
|
|
51
|
+
export default meta;
|
|
52
|
+
type Story = StoryObj<typeof meta>;
|
|
53
|
+
|
|
54
|
+
export const Default: Story = {
|
|
55
|
+
render: (args) => (
|
|
56
|
+
<Section {...args} className="sb-fill">
|
|
57
|
+
<Text variant="body-small">
|
|
58
|
+
Section padding="{args.padding}"
|
|
59
|
+
</Text>
|
|
60
|
+
</Section>
|
|
61
|
+
),
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const Scale: Story = {
|
|
65
|
+
name: "All sizes",
|
|
66
|
+
parameters: {
|
|
67
|
+
controls: { disable: true },
|
|
68
|
+
docs: {
|
|
69
|
+
description: {
|
|
70
|
+
story:
|
|
71
|
+
"Every step side by side. Resize past 768px to see each one grow.",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
render: () => (
|
|
76
|
+
<VStack gap="xs" width="100%">
|
|
77
|
+
{(["sm", "md", "lg", "xl"] as const).map((padding) => (
|
|
78
|
+
<Section key={padding} padding={padding} className="sb-fill">
|
|
79
|
+
<Text variant="body-small">padding="{padding}"</Text>
|
|
80
|
+
</Section>
|
|
81
|
+
))}
|
|
82
|
+
</VStack>
|
|
83
|
+
),
|
|
84
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Hide, Show, 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/ShowAndHide",
|
|
9
|
+
component: Show,
|
|
10
|
+
subcomponents: { Hide },
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
parameters: {
|
|
13
|
+
layout: "padded",
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component: [
|
|
17
|
+
"Responsive visibility without Tailwind `hidden md:block`. `Show` renders only inside the range; `Hide` renders everywhere except it.",
|
|
18
|
+
"",
|
|
19
|
+
LAYOUT_DOCS_RULE,
|
|
20
|
+
"",
|
|
21
|
+
"```tsx",
|
|
22
|
+
`import { Show, Hide } from "@syscore/ui-library"`,
|
|
23
|
+
"",
|
|
24
|
+
'<Show above="md"><DesktopNav /></Show>',
|
|
25
|
+
'<Hide above="md"><MenuButton /></Hide>',
|
|
26
|
+
"```",
|
|
27
|
+
"",
|
|
28
|
+
"| Breakpoint | Min width |",
|
|
29
|
+
"|------------|-----------|",
|
|
30
|
+
"| `sm` | 640px |",
|
|
31
|
+
"| `md` | 768px |",
|
|
32
|
+
"| `lg` | 1024px |",
|
|
33
|
+
"| `xl` | 1280px |",
|
|
34
|
+
"",
|
|
35
|
+
"**These toggle CSS `display`, they do not unmount.** The children still render and still run their effects — for genuinely mobile-only work, branch in JS instead.",
|
|
36
|
+
"",
|
|
37
|
+
"Resize the canvas to see the boxes below swap.",
|
|
38
|
+
].join("\n"),
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
argTypes: {
|
|
43
|
+
...hiddenArgs,
|
|
44
|
+
above: {
|
|
45
|
+
control: "inline-radio",
|
|
46
|
+
options: [undefined, "sm", "md", "lg", "xl"],
|
|
47
|
+
},
|
|
48
|
+
below: {
|
|
49
|
+
control: "inline-radio",
|
|
50
|
+
options: [undefined, "sm", "md", "lg", "xl"],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
args: { above: "md" },
|
|
54
|
+
} satisfies Meta<typeof Show>;
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
type Story = StoryObj<typeof meta>;
|
|
58
|
+
|
|
59
|
+
export const ShowAbove: Story = {
|
|
60
|
+
name: "Show above a breakpoint",
|
|
61
|
+
render: (args) => (
|
|
62
|
+
<Show {...args}>
|
|
63
|
+
<DemoBox label={`Visible above ${args.above ?? "—"}`} tall />
|
|
64
|
+
</Show>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const HideAbove: Story = {
|
|
69
|
+
name: "Hide above a breakpoint",
|
|
70
|
+
render: (args) => (
|
|
71
|
+
<Hide {...args}>
|
|
72
|
+
<DemoBox label={`Hidden above ${args.above ?? "—"}`} tall />
|
|
73
|
+
</Hide>
|
|
74
|
+
),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const SwapPair: Story = {
|
|
78
|
+
name: "Swap at a breakpoint",
|
|
79
|
+
parameters: {
|
|
80
|
+
controls: { disable: true },
|
|
81
|
+
docs: {
|
|
82
|
+
description: {
|
|
83
|
+
story:
|
|
84
|
+
"The usual pairing: a desktop treatment and a compact one, each wrapped so exactly one shows.",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
render: () => (
|
|
89
|
+
<VStack gap="sm" width="100%">
|
|
90
|
+
<Show above="md">
|
|
91
|
+
<DemoBox label="Wide layout (≥ 768px)" tall />
|
|
92
|
+
</Show>
|
|
93
|
+
<Hide above="md">
|
|
94
|
+
<DemoBox label="Compact layout (< 768px)" tall />
|
|
95
|
+
</Hide>
|
|
96
|
+
<Text variant="body-small">Drag the canvas edge across 768px.</Text>
|
|
97
|
+
</VStack>
|
|
98
|
+
),
|
|
99
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
HStack,
|
|
4
|
+
SPACE_NAMES,
|
|
5
|
+
SPACE_SCALE,
|
|
6
|
+
Spacer,
|
|
7
|
+
VStack,
|
|
8
|
+
type SpaceName,
|
|
9
|
+
} from "../../components/ui/layout";
|
|
10
|
+
import { DemoBox, LAYOUT_DOCS_RULE } from "./demo";
|
|
11
|
+
|
|
12
|
+
const meta = {
|
|
13
|
+
title: "Components/Layout/Spacer",
|
|
14
|
+
component: Spacer,
|
|
15
|
+
tags: ["autodocs"],
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: "padded",
|
|
18
|
+
docs: {
|
|
19
|
+
description: {
|
|
20
|
+
component: [
|
|
21
|
+
"Named empty space from the design-system scale. Change `--space-*` in CSS and every app updates.",
|
|
22
|
+
"Even spacing belongs on `HStack` / `VStack` `gap` — not a Spacer between every item.",
|
|
23
|
+
"",
|
|
24
|
+
LAYOUT_DOCS_RULE,
|
|
25
|
+
"",
|
|
26
|
+
"```tsx",
|
|
27
|
+
`import { Spacer, VStack, HStack } from "@syscore/ui-library"`,
|
|
28
|
+
"",
|
|
29
|
+
"<VStack gap={0}>",
|
|
30
|
+
" <Title />",
|
|
31
|
+
` <Spacer space="xl" />`,
|
|
32
|
+
" <Body />",
|
|
33
|
+
"</VStack>",
|
|
34
|
+
"",
|
|
35
|
+
'<HStack gap="md">',
|
|
36
|
+
" <Logo />",
|
|
37
|
+
" <Spacer flex />",
|
|
38
|
+
" <Actions />",
|
|
39
|
+
"</HStack>",
|
|
40
|
+
"```",
|
|
41
|
+
"",
|
|
42
|
+
"| Name | px |",
|
|
43
|
+
"|------|----|",
|
|
44
|
+
...SPACE_NAMES.map(
|
|
45
|
+
(name) => `| \`${name}\` | ${SPACE_SCALE[name]} |`,
|
|
46
|
+
),
|
|
47
|
+
"",
|
|
48
|
+
"`flex` ignores `space` and `axis` and grows to eat the leftover room in a stack — the way to push actions to the far end of a row.",
|
|
49
|
+
].join("\n"),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
argTypes: {
|
|
54
|
+
space: { control: "select", options: [...SPACE_NAMES] },
|
|
55
|
+
axis: { control: "inline-radio", options: ["vertical", "horizontal"] },
|
|
56
|
+
flex: { control: "boolean" },
|
|
57
|
+
size: { table: { disable: true } },
|
|
58
|
+
},
|
|
59
|
+
args: {
|
|
60
|
+
space: "md",
|
|
61
|
+
axis: "vertical",
|
|
62
|
+
flex: false,
|
|
63
|
+
},
|
|
64
|
+
} satisfies Meta<typeof Spacer>;
|
|
65
|
+
|
|
66
|
+
export default meta;
|
|
67
|
+
type Story = StoryObj<typeof meta>;
|
|
68
|
+
|
|
69
|
+
export const Default: Story = {
|
|
70
|
+
parameters: {
|
|
71
|
+
docs: {
|
|
72
|
+
source: {
|
|
73
|
+
code: `<VStack gap={0}>
|
|
74
|
+
<Item />
|
|
75
|
+
<Spacer space="xl" />
|
|
76
|
+
<Item />
|
|
77
|
+
</VStack>`,
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
render: (args) => (
|
|
82
|
+
<VStack gap={0} maxWidth={384}>
|
|
83
|
+
<DemoBox label="Above" />
|
|
84
|
+
<Spacer {...args} className="sb-spacer-fill" />
|
|
85
|
+
<DemoBox label="Below" />
|
|
86
|
+
</VStack>
|
|
87
|
+
),
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const Vertical: Story = {
|
|
91
|
+
args: { space: "2xl", axis: "vertical" },
|
|
92
|
+
render: (args) => (
|
|
93
|
+
<VStack gap={0} maxWidth={384}>
|
|
94
|
+
<DemoBox label="Title" />
|
|
95
|
+
<Spacer {...args} className="sb-spacer-fill" />
|
|
96
|
+
<DemoBox label="Body" />
|
|
97
|
+
</VStack>
|
|
98
|
+
),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const Horizontal: Story = {
|
|
102
|
+
args: { space: "xl", axis: "horizontal" },
|
|
103
|
+
render: (args) => (
|
|
104
|
+
<HStack gap={0} align="center">
|
|
105
|
+
<DemoBox label="Left" />
|
|
106
|
+
<Spacer
|
|
107
|
+
{...args}
|
|
108
|
+
className="sb-spacer-fill"
|
|
109
|
+
style={{ alignSelf: "stretch" }}
|
|
110
|
+
/>
|
|
111
|
+
<DemoBox label="Right" />
|
|
112
|
+
</HStack>
|
|
113
|
+
),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const Flex: Story = {
|
|
117
|
+
args: { flex: true },
|
|
118
|
+
render: (args) => (
|
|
119
|
+
<HStack gap="sm" width="100%" maxWidth={480}>
|
|
120
|
+
<DemoBox label="Logo" />
|
|
121
|
+
<Spacer {...args} className="sb-spacer-fill" />
|
|
122
|
+
<DemoBox label="Actions" />
|
|
123
|
+
</HStack>
|
|
124
|
+
),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const Scale: Story = {
|
|
128
|
+
name: "All spaces",
|
|
129
|
+
render: () => (
|
|
130
|
+
<VStack gap="md" maxWidth={480}>
|
|
131
|
+
{SPACE_NAMES.map((name: SpaceName) => (
|
|
132
|
+
<VStack key={name} gap="3xs">
|
|
133
|
+
<span className="sb-caption">
|
|
134
|
+
{name} · {SPACE_SCALE[name]}px
|
|
135
|
+
</span>
|
|
136
|
+
<Spacer space={name} axis="vertical" className="sb-spacer-fill" />
|
|
137
|
+
</VStack>
|
|
138
|
+
))}
|
|
139
|
+
</VStack>
|
|
140
|
+
),
|
|
141
|
+
parameters: {
|
|
142
|
+
controls: { disable: true },
|
|
143
|
+
docs: {
|
|
144
|
+
description: {
|
|
145
|
+
story: "Every step on the scale, rendered at true size.",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
};
|