@recursica/adapter-mantine-v8 1.3.4 → 1.3.5
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/.storybook/commonArgTypes.ts +148 -0
- package/CHANGELOG.md +6 -0
- package/package.json +2 -2
- package/src/Introduction.stories.tsx +149 -0
- package/src/components/Accordion/Accordion.stories.tsx +189 -0
- package/src/components/AssistiveElement/AssistiveElement.stories.tsx +68 -0
- package/src/components/AutoComplete/AutoComplete.stories.tsx +336 -0
- package/src/components/Avatar/Avatar.stories.tsx +92 -0
- package/src/components/Badge/Badge.stories.tsx +78 -0
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +114 -0
- package/src/components/Button/Button.stories.tsx +192 -0
- package/src/components/Card/Card.stories.tsx +76 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +97 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +139 -0
- package/src/components/Chip/Chip.stories.tsx +128 -0
- package/src/components/Container/Container.stories.tsx +118 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +158 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +252 -0
- package/src/components/FileInput/FileInput.stories.tsx +313 -0
- package/src/components/FileUpload/FileUpload.stories.tsx +362 -0
- package/src/components/Flex/Flex.stories.tsx +128 -0
- package/src/components/FormControlLayout/FormControlLayout.stories.tsx +118 -0
- package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +129 -0
- package/src/components/Group/Group.stories.tsx +120 -0
- package/src/components/Heading/Heading.stories.tsx +112 -0
- package/src/components/HoverCard/HoverCard.stories.tsx +172 -0
- package/src/components/Label/Label.stories.tsx +131 -0
- package/src/components/LayoutGrid/LayoutGrid.stories.tsx +61 -0
- package/src/components/Link/Link.stories.tsx +58 -0
- package/src/components/Loader/Loader.stories.tsx +123 -0
- package/src/components/Menu/Menu.stories.tsx +370 -0
- package/src/components/Modal/Modal.stories.tsx +105 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +96 -0
- package/src/components/Pagination/Pagination.stories.tsx +48 -0
- package/src/components/Panel/Panel.stories.tsx +219 -0
- package/src/components/Popover/Popover.stories.tsx +133 -0
- package/src/components/Radio/Radio.stories.tsx +93 -0
- package/src/components/Radio/RadioGroup.stories.tsx +117 -0
- package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +163 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +106 -0
- package/src/components/Slider/Slider.stories.tsx +282 -0
- package/src/components/Stack/Stack.stories.tsx +108 -0
- package/src/components/Stepper/Stepper.stories.tsx +148 -0
- package/src/components/Switch/Switch.stories.tsx +114 -0
- package/src/components/Switch/SwitchGroup.stories.tsx +132 -0
- package/src/components/Table/Table.stories.tsx +140 -0
- package/src/components/Tabs/Tabs.stories.tsx +154 -0
- package/src/components/Text/Text.stories.tsx +148 -0
- package/src/components/TextArea/TextArea.stories.tsx +94 -0
- package/src/components/TextField/TextField.stories.tsx +162 -0
- package/src/components/TimePicker/TimePicker.stories.tsx +141 -0
- package/src/components/Timeline/Timeline.stories.tsx +128 -0
- package/src/components/Toast/Toast.stories.tsx +67 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +165 -0
- package/src/components/TransferList/TransferList.stories.tsx +121 -0
- package/src/components/Tree/Tree.stories.tsx +104 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Flex } from "./Flex";
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Text } from "../Text/Text";
|
|
6
|
+
|
|
7
|
+
type FlexStoryProps = React.ComponentProps<typeof Flex>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<FlexStoryProps> = {
|
|
10
|
+
title: "UI-Kit/Flex",
|
|
11
|
+
component: Flex,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
"Flex is a bare-metal flex container that maps directly to Mantine's Flex component, providing unopinionated control over direction, alignment, and wrapping.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
gap: "rec-default",
|
|
23
|
+
align: "center",
|
|
24
|
+
justify: "flex-start",
|
|
25
|
+
direction: "row",
|
|
26
|
+
wrap: "wrap",
|
|
27
|
+
},
|
|
28
|
+
argTypes: {
|
|
29
|
+
gap: {
|
|
30
|
+
control: "select",
|
|
31
|
+
options: [
|
|
32
|
+
"rec-none",
|
|
33
|
+
"rec-sm",
|
|
34
|
+
"rec-default",
|
|
35
|
+
"rec-md",
|
|
36
|
+
"rec-lg",
|
|
37
|
+
"rec-xl",
|
|
38
|
+
"rec-2xl",
|
|
39
|
+
"xs",
|
|
40
|
+
"sm",
|
|
41
|
+
"md",
|
|
42
|
+
"lg",
|
|
43
|
+
"xl",
|
|
44
|
+
],
|
|
45
|
+
description: "Gap between elements",
|
|
46
|
+
},
|
|
47
|
+
direction: {
|
|
48
|
+
control: "select",
|
|
49
|
+
options: ["row", "column", "row-reverse", "column-reverse"],
|
|
50
|
+
description: "Flex-direction property",
|
|
51
|
+
},
|
|
52
|
+
align: {
|
|
53
|
+
control: "select",
|
|
54
|
+
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
55
|
+
description: "Align-items property",
|
|
56
|
+
},
|
|
57
|
+
justify: {
|
|
58
|
+
control: "select",
|
|
59
|
+
options: [
|
|
60
|
+
"flex-start",
|
|
61
|
+
"center",
|
|
62
|
+
"flex-end",
|
|
63
|
+
"space-between",
|
|
64
|
+
"space-around",
|
|
65
|
+
],
|
|
66
|
+
description: "Justify-content property",
|
|
67
|
+
},
|
|
68
|
+
wrap: {
|
|
69
|
+
control: "select",
|
|
70
|
+
options: ["wrap", "nowrap", "wrap-reverse"],
|
|
71
|
+
description: "Flex-wrap property",
|
|
72
|
+
},
|
|
73
|
+
defaultChecked: {
|
|
74
|
+
table: { disable: true },
|
|
75
|
+
},
|
|
76
|
+
rowGap: {
|
|
77
|
+
table: { disable: true },
|
|
78
|
+
},
|
|
79
|
+
columnGap: {
|
|
80
|
+
table: { disable: true },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default meta;
|
|
86
|
+
|
|
87
|
+
type Story = StoryObj<FlexStoryProps>;
|
|
88
|
+
|
|
89
|
+
export const Default: Story = {
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
91
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
92
|
+
<Flex {...args}>
|
|
93
|
+
<Button variant="solid">Block A</Button>
|
|
94
|
+
<Button variant="outline">Block B</Button>
|
|
95
|
+
<Text>Text inside Flex</Text>
|
|
96
|
+
</Flex>
|
|
97
|
+
),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const StaticGapSmallColumn: Story = {
|
|
101
|
+
args: {
|
|
102
|
+
gap: "rec-sm",
|
|
103
|
+
direction: "column",
|
|
104
|
+
},
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
106
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
107
|
+
<Flex {...args}>
|
|
108
|
+
<Button variant="solid">Item 1</Button>
|
|
109
|
+
<Button variant="solid">Item 2</Button>
|
|
110
|
+
<Button variant="solid">Item 3</Button>
|
|
111
|
+
</Flex>
|
|
112
|
+
),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const StaticGapLargeRow: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
gap: "rec-xl",
|
|
118
|
+
direction: "row",
|
|
119
|
+
},
|
|
120
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
121
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
122
|
+
<Flex {...args}>
|
|
123
|
+
<Button variant="solid">Item 1</Button>
|
|
124
|
+
<Button variant="solid">Item 2</Button>
|
|
125
|
+
<Button variant="solid">Item 3</Button>
|
|
126
|
+
</Flex>
|
|
127
|
+
),
|
|
128
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { FormControlLayout } from "./FormControlLayout";
|
|
3
|
+
import { Switch } from "../Switch/Switch";
|
|
4
|
+
import { Label } from "../Label/Label";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof FormControlLayout> = {
|
|
7
|
+
title: "UI-Kit/FormControlLayout",
|
|
8
|
+
component: FormControlLayout,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "padded",
|
|
11
|
+
docs: {
|
|
12
|
+
description: {
|
|
13
|
+
component:
|
|
14
|
+
"A layout component used to correctly position form inputs alongside their labels.\n\n**When to use this:**\nTypically, you should use `FormControlWrapper` instead, which uses this component under the hood to handle layout automatically.\n\nHowever, this component is useful when you need to align standalone inputs (like a `Switch` or `Checkbox` without a label) so they perfectly match the spacing and alignment of your other form fields in a `side-by-side` layout.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
tags: ["autodocs"],
|
|
19
|
+
argTypes: {
|
|
20
|
+
formLayout: {
|
|
21
|
+
control: "radio",
|
|
22
|
+
options: ["stacked", "side-by-side"],
|
|
23
|
+
},
|
|
24
|
+
labelSize: {
|
|
25
|
+
control: "radio",
|
|
26
|
+
options: ["default", "small"],
|
|
27
|
+
description: "Dictates the physical width of the left column.",
|
|
28
|
+
},
|
|
29
|
+
children: {
|
|
30
|
+
table: { disable: true },
|
|
31
|
+
},
|
|
32
|
+
leftSection: {
|
|
33
|
+
table: { disable: true },
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default meta;
|
|
39
|
+
type Story = StoryObj<typeof FormControlLayout>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The Default layout demonstrates wrapping a standalone primitive without a Label.
|
|
43
|
+
* In a stacked layout, an omitted leftSection naturally results in no structural padding.
|
|
44
|
+
*/
|
|
45
|
+
export const Default: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
formLayout: "stacked",
|
|
48
|
+
labelSize: "default",
|
|
49
|
+
leftSection: (
|
|
50
|
+
<div
|
|
51
|
+
style={{ padding: 8, border: "1px dashed #ccc", background: "#fafafa" }}
|
|
52
|
+
>
|
|
53
|
+
Left Section Boundary
|
|
54
|
+
</div>
|
|
55
|
+
),
|
|
56
|
+
children: <Switch label="Input area content" />,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Demonstrates the stacked layout without a left section.
|
|
62
|
+
* The input should natively pull flush to the top left since there is no left column.
|
|
63
|
+
*/
|
|
64
|
+
export const StackedLayout: Story = {
|
|
65
|
+
args: {
|
|
66
|
+
formLayout: "stacked",
|
|
67
|
+
labelSize: "default",
|
|
68
|
+
children: <Switch label="Flush stacked switch" />,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Demonstrates how a naked boolean primitive perfectly aligns in a side-by-side layout
|
|
74
|
+
* by utilizing the layout wrapper. The left column maintains its precise design system width
|
|
75
|
+
* even when `leftSection` is undefined, forcing the component into the correct form column!
|
|
76
|
+
*/
|
|
77
|
+
export const SideBySideLayout: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
formLayout: "side-by-side",
|
|
80
|
+
labelSize: "default",
|
|
81
|
+
children: <Switch label="Offset switch aligning with grid" />,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A real Label (not a placeholder) in a stacked layout, at `labelSize="default"`. Even
|
|
87
|
+
* though the label sits above the field rather than beside it, its own column still caps
|
|
88
|
+
* to the design system's stacked-layout width (224px) rather than stretching to the full
|
|
89
|
+
* container — long label text wraps instead of spanning edge-to-edge.
|
|
90
|
+
*/
|
|
91
|
+
export const StackedLayoutWithLabelDefault: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
formLayout: "stacked",
|
|
94
|
+
labelSize: "default",
|
|
95
|
+
leftSection: (
|
|
96
|
+
<Label labelSize="default">
|
|
97
|
+
A fairly long label to show the stacked-layout width cap in action
|
|
98
|
+
</Label>
|
|
99
|
+
),
|
|
100
|
+
children: <Switch label="Input area content" />,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Same as above, at `labelSize="small"` — the stacked-layout width cap is narrower (80px).
|
|
106
|
+
*/
|
|
107
|
+
export const StackedLayoutWithLabelSmall: Story = {
|
|
108
|
+
args: {
|
|
109
|
+
formLayout: "stacked",
|
|
110
|
+
labelSize: "small",
|
|
111
|
+
leftSection: (
|
|
112
|
+
<Label labelSize="small">
|
|
113
|
+
A fairly long label to show the stacked-layout width cap in action
|
|
114
|
+
</Label>
|
|
115
|
+
),
|
|
116
|
+
children: <Switch label="Input area content" />,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
FormControlWrapper,
|
|
4
|
+
type FormControlWrapperProps,
|
|
5
|
+
} from "./FormControlWrapper";
|
|
6
|
+
import { TextField } from "../TextField/TextField";
|
|
7
|
+
import { formControlArgTypes } from "../../../.storybook/commonArgTypes";
|
|
8
|
+
|
|
9
|
+
type WrapperStoryProps = FormControlWrapperProps;
|
|
10
|
+
|
|
11
|
+
const meta: Meta<WrapperStoryProps> = {
|
|
12
|
+
title: "UI-Kit/FormControlWrapper",
|
|
13
|
+
component: FormControlWrapper,
|
|
14
|
+
tags: ["autodocs"],
|
|
15
|
+
parameters: {
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
component:
|
|
19
|
+
"The `FormControlWrapper` is the ultimate structural replacement for Mantine's built-in `Input.Wrapper`. By abandoning Mantine's opinionated wrappers entirely, we centralize all label tracking, error rendering, ARIA generation, and grid layouts natively inside this single component.\n\n### Usage with Naked Primitives\nThis component wraps 'naked' elements like `<Input>` directly. The demonstration stories below utilize `<TextField>` as a native display vehicle, since `<TextField>` natively pipes all its properties structurally back into this wrapper.",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
argTypes: {
|
|
24
|
+
...formControlArgTypes,
|
|
25
|
+
error: {
|
|
26
|
+
control: "text",
|
|
27
|
+
description:
|
|
28
|
+
"Error string driving native assistive component and validation markers.",
|
|
29
|
+
},
|
|
30
|
+
assistiveText: {
|
|
31
|
+
control: "text",
|
|
32
|
+
description:
|
|
33
|
+
"Helper instructions safely dynamically anchored below the input box.",
|
|
34
|
+
},
|
|
35
|
+
assistiveWithIcon: {
|
|
36
|
+
control: "boolean",
|
|
37
|
+
},
|
|
38
|
+
required: {
|
|
39
|
+
control: "boolean",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default meta;
|
|
45
|
+
|
|
46
|
+
type Story = StoryObj<WrapperStoryProps>;
|
|
47
|
+
|
|
48
|
+
const renderWithTextField = (args: WrapperStoryProps) => (
|
|
49
|
+
// We explicitly cast args to 'any' here because Mantine enforces strict anatomy types for
|
|
50
|
+
// 'classNames', 'styles', and 'attributes'. WrapperStoryProps defines these for the Wrapper anatomy,
|
|
51
|
+
// but TextField expects them for the full TextInput anatomy, causing a TS intersection mismatch.
|
|
52
|
+
<TextField
|
|
53
|
+
placeholder="Form Control primitive mapped..."
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
{...(args as any)}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const Default: Story = {
|
|
60
|
+
args: {
|
|
61
|
+
label: "Account Username",
|
|
62
|
+
formLayout: "stacked",
|
|
63
|
+
assistiveText: "Validation occurs immediately natively.",
|
|
64
|
+
},
|
|
65
|
+
render: renderWithTextField,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const VisualErrorState: Story = {
|
|
69
|
+
args: {
|
|
70
|
+
label: "Encryption Protocol",
|
|
71
|
+
formLayout: "stacked",
|
|
72
|
+
error: "Strict validation limits reached. Handshake rejected securely.",
|
|
73
|
+
},
|
|
74
|
+
render: renderWithTextField,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const RequiredArchitecture: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
label: "Root Password",
|
|
80
|
+
formLayout: "side-by-side",
|
|
81
|
+
required: true,
|
|
82
|
+
assistiveText: "Bypass string structure required to initiate protocol.",
|
|
83
|
+
},
|
|
84
|
+
render: renderWithTextField,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const WithoutAssistiveIcons: Story = {
|
|
88
|
+
args: {
|
|
89
|
+
label: "Server Domain",
|
|
90
|
+
assistiveText:
|
|
91
|
+
"A standard text boundary without default native icon parameters bounding.",
|
|
92
|
+
assistiveWithIcon: false,
|
|
93
|
+
},
|
|
94
|
+
render: renderWithTextField,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const NativeChildrenDirectly: Story = {
|
|
98
|
+
parameters: {
|
|
99
|
+
docs: {
|
|
100
|
+
description: {
|
|
101
|
+
story:
|
|
102
|
+
"Bypassing the TextField map to show exactly how native `<input>` hooks execute inside the raw wrapper natively perfectly.",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
args: {
|
|
107
|
+
label: "Raw HTML Checkbox",
|
|
108
|
+
formLayout: "side-by-side",
|
|
109
|
+
assistiveText: "This wraps a raw HTML input tag mapping correctly.",
|
|
110
|
+
},
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
112
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
113
|
+
<div
|
|
114
|
+
style={{
|
|
115
|
+
display: "flex",
|
|
116
|
+
gap: "10px",
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
{/* We can cleanly wrap even un-styled HTML primitives! */}
|
|
121
|
+
<FormControlWrapper {...args}>
|
|
122
|
+
<input
|
|
123
|
+
type="checkbox"
|
|
124
|
+
style={{ margin: 0, width: "16px", height: "16px" }}
|
|
125
|
+
/>
|
|
126
|
+
</FormControlWrapper>
|
|
127
|
+
</div>
|
|
128
|
+
),
|
|
129
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Group } from "./Group";
|
|
4
|
+
import { Button } from "../Button";
|
|
5
|
+
import { Text } from "../Text/Text";
|
|
6
|
+
|
|
7
|
+
type GroupStoryProps = React.ComponentProps<typeof Group>;
|
|
8
|
+
|
|
9
|
+
const meta: Meta<GroupStoryProps> = {
|
|
10
|
+
title: "UI-Kit/Group",
|
|
11
|
+
component: Group,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
"Group is a flex horizontal layout container that maps directly to Mantine's Group component allowing safe layout property passing.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
gap: "rec-default",
|
|
23
|
+
align: "center",
|
|
24
|
+
justify: "flex-start",
|
|
25
|
+
wrap: "wrap",
|
|
26
|
+
},
|
|
27
|
+
argTypes: {
|
|
28
|
+
gap: {
|
|
29
|
+
control: "select",
|
|
30
|
+
options: [
|
|
31
|
+
"rec-none",
|
|
32
|
+
"rec-sm",
|
|
33
|
+
"rec-default",
|
|
34
|
+
"rec-md",
|
|
35
|
+
"rec-lg",
|
|
36
|
+
"rec-xl",
|
|
37
|
+
"rec-2xl",
|
|
38
|
+
"xs",
|
|
39
|
+
"sm",
|
|
40
|
+
"md",
|
|
41
|
+
"lg",
|
|
42
|
+
"xl",
|
|
43
|
+
],
|
|
44
|
+
description: "Gap between elements",
|
|
45
|
+
},
|
|
46
|
+
align: {
|
|
47
|
+
control: "select",
|
|
48
|
+
options: ["flex-start", "center", "flex-end", "stretch"],
|
|
49
|
+
description: "Align-items property",
|
|
50
|
+
},
|
|
51
|
+
justify: {
|
|
52
|
+
control: "select",
|
|
53
|
+
options: [
|
|
54
|
+
"flex-start",
|
|
55
|
+
"center",
|
|
56
|
+
"flex-end",
|
|
57
|
+
"space-between",
|
|
58
|
+
"space-around",
|
|
59
|
+
],
|
|
60
|
+
description: "Justify-content property",
|
|
61
|
+
},
|
|
62
|
+
wrap: {
|
|
63
|
+
control: "select",
|
|
64
|
+
options: ["wrap", "nowrap", "wrap-reverse"],
|
|
65
|
+
description: "Flex-wrap property",
|
|
66
|
+
},
|
|
67
|
+
defaultChecked: {
|
|
68
|
+
table: { disable: true },
|
|
69
|
+
},
|
|
70
|
+
rowGap: {
|
|
71
|
+
table: { disable: true },
|
|
72
|
+
},
|
|
73
|
+
columnGap: {
|
|
74
|
+
table: { disable: true },
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export default meta;
|
|
80
|
+
|
|
81
|
+
type Story = StoryObj<GroupStoryProps>;
|
|
82
|
+
|
|
83
|
+
export const Default: Story = {
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
85
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
86
|
+
<Group {...args}>
|
|
87
|
+
<Button variant="solid">Primary</Button>
|
|
88
|
+
<Button variant="outline">Secondary</Button>
|
|
89
|
+
<Text>Text element within Group</Text>
|
|
90
|
+
</Group>
|
|
91
|
+
),
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export const StaticGapSmall: Story = {
|
|
95
|
+
args: {
|
|
96
|
+
gap: "rec-sm",
|
|
97
|
+
},
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
99
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
100
|
+
<Group {...args}>
|
|
101
|
+
<Button variant="solid">Item 1</Button>
|
|
102
|
+
<Button variant="solid">Item 2</Button>
|
|
103
|
+
<Button variant="solid">Item 3</Button>
|
|
104
|
+
</Group>
|
|
105
|
+
),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const StaticGapLarge: Story = {
|
|
109
|
+
args: {
|
|
110
|
+
gap: "rec-xl",
|
|
111
|
+
},
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
|
113
|
+
render: ({ withLayer, layer, ...args }: any) => (
|
|
114
|
+
<Group {...args}>
|
|
115
|
+
<Button variant="solid">Item 1</Button>
|
|
116
|
+
<Button variant="solid">Item 2</Button>
|
|
117
|
+
<Button variant="solid">Item 3</Button>
|
|
118
|
+
</Group>
|
|
119
|
+
),
|
|
120
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Heading } from "./Heading";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Heading> = {
|
|
5
|
+
title: "UI-Kit/Heading",
|
|
6
|
+
component: Heading,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
"The semantic `<Heading>` abstraction intrinsically links pure `h1-h6` tag generation with exact Recursica design boundaries to preserve SEO and screen reader trees uniformly globally.",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
order: {
|
|
18
|
+
control: "select",
|
|
19
|
+
options: [1, 2, 3, 4, 5, 6],
|
|
20
|
+
description:
|
|
21
|
+
"Controls the `h` tag and the resultant typographical weighting natively mapped to Recursica.",
|
|
22
|
+
},
|
|
23
|
+
color: {
|
|
24
|
+
control: "select",
|
|
25
|
+
options: ["default", "warning", "alert", "success"],
|
|
26
|
+
description:
|
|
27
|
+
"Semantic text color, bound to the active layer's text-element tokens via `data-color`.",
|
|
28
|
+
},
|
|
29
|
+
emphasis: {
|
|
30
|
+
control: "inline-radio",
|
|
31
|
+
options: ["high", "low"],
|
|
32
|
+
description:
|
|
33
|
+
"Emphasis level, bound to the theme's text-emphasis opacity tokens via `data-emphasis`.",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default meta;
|
|
39
|
+
|
|
40
|
+
type Story = StoryObj<typeof Heading>;
|
|
41
|
+
|
|
42
|
+
export const Default: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
order: 1,
|
|
45
|
+
children: "Semantic H1 Document Boundary",
|
|
46
|
+
},
|
|
47
|
+
render: ({ ...args }) => <Heading {...args} />,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const StaticVariations: Story = {
|
|
51
|
+
args: {},
|
|
52
|
+
render: () => (
|
|
53
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
54
|
+
<Heading order={1}>H1 Heading</Heading>
|
|
55
|
+
<Heading order={2}>H2 Heading</Heading>
|
|
56
|
+
<Heading order={3}>H3 Heading</Heading>
|
|
57
|
+
<Heading order={4}>H4 Heading</Heading>
|
|
58
|
+
<Heading order={5}>H5 Heading</Heading>
|
|
59
|
+
<Heading order={6}>H6 Heading</Heading>
|
|
60
|
+
</div>
|
|
61
|
+
),
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const Colors: Story = {
|
|
65
|
+
args: {},
|
|
66
|
+
parameters: {
|
|
67
|
+
docs: {
|
|
68
|
+
description: {
|
|
69
|
+
story:
|
|
70
|
+
"Semantic colors map to the active layer's text-element tokens. `default` follows the layer's base text color; `warning`, `alert`, and `success` pull their respective semantic tones.",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
render: () => (
|
|
75
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
|
|
76
|
+
<Heading order={2} color="default">
|
|
77
|
+
Default heading
|
|
78
|
+
</Heading>
|
|
79
|
+
<Heading order={2} color="warning">
|
|
80
|
+
Warning heading
|
|
81
|
+
</Heading>
|
|
82
|
+
<Heading order={2} color="alert">
|
|
83
|
+
Alert heading
|
|
84
|
+
</Heading>
|
|
85
|
+
<Heading order={2} color="success">
|
|
86
|
+
Success heading
|
|
87
|
+
</Heading>
|
|
88
|
+
</div>
|
|
89
|
+
),
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const Emphasis: Story = {
|
|
93
|
+
args: {},
|
|
94
|
+
parameters: {
|
|
95
|
+
docs: {
|
|
96
|
+
description: {
|
|
97
|
+
story:
|
|
98
|
+
"Emphasis controls text opacity via the theme's text-emphasis tokens. `high` (the default) is solid; `low` dims the heading for secondary content.",
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
render: () => (
|
|
103
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
|
|
104
|
+
<Heading order={2} emphasis="high">
|
|
105
|
+
High emphasis heading
|
|
106
|
+
</Heading>
|
|
107
|
+
<Heading order={2} emphasis="low">
|
|
108
|
+
Low emphasis heading
|
|
109
|
+
</Heading>
|
|
110
|
+
</div>
|
|
111
|
+
),
|
|
112
|
+
};
|