@checkstack/ui 1.8.0 → 1.8.1
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/main.ts +22 -0
- package/.storybook/manager-head.html +2 -0
- package/.storybook/mock-access-api.ts +5 -0
- package/.storybook/preview.css +5 -0
- package/.storybook/preview.tsx +73 -0
- package/CHANGELOG.md +8 -0
- package/package.json +22 -8
- package/postcss.config.js +6 -0
- package/stories/AccessDenied.stories.tsx +17 -0
- package/stories/AccessGate.stories.tsx +49 -0
- package/stories/Accordion.stories.tsx +56 -0
- package/stories/Alert.stories.tsx +88 -0
- package/stories/AmbientBackground.stories.tsx +28 -0
- package/stories/AnimatedCounter.stories.tsx +41 -0
- package/stories/AnimatedNumber.stories.tsx +39 -0
- package/stories/BackLink.stories.tsx +32 -0
- package/stories/Badge.stories.tsx +37 -0
- package/stories/Button.stories.tsx +57 -0
- package/stories/Card.stories.tsx +39 -0
- package/stories/Checkbox.stories.tsx +45 -0
- package/stories/CodeEditor.stories.tsx +67 -0
- package/stories/ColorPicker.stories.tsx +24 -0
- package/stories/CommandPalette.stories.tsx +36 -0
- package/stories/ConfirmationModal.stories.tsx +40 -0
- package/stories/DateRangeFilter.stories.tsx +30 -0
- package/stories/DateTimePicker.stories.tsx +26 -0
- package/stories/Dialog.stories.tsx +62 -0
- package/stories/DynamicForm.stories.tsx +83 -0
- package/stories/DynamicIcon.stories.tsx +52 -0
- package/stories/EditableText.stories.tsx +29 -0
- package/stories/Feedback.stories.tsx +45 -0
- package/stories/IDELayout.stories.tsx +70 -0
- package/stories/InfoBanner.stories.tsx +41 -0
- package/stories/Input.stories.tsx +29 -0
- package/stories/InstanceScopeBanner.stories.tsx +35 -0
- package/stories/Introduction.mdx +50 -0
- package/stories/Label.stories.tsx +21 -0
- package/stories/LinksEditor.stories.tsx +37 -0
- package/stories/Markdown.stories.tsx +35 -0
- package/stories/Menu.stories.tsx +35 -0
- package/stories/MetricTile.stories.tsx +31 -0
- package/stories/NavItem.stories.tsx +29 -0
- package/stories/NotFound.stories.tsx +17 -0
- package/stories/Page.stories.tsx +29 -0
- package/stories/PageLayout.stories.tsx +59 -0
- package/stories/PaginatedList.stories.tsx +44 -0
- package/stories/Pagination.stories.tsx +31 -0
- package/stories/PerformanceProvider.stories.tsx +33 -0
- package/stories/PluginConfigForm.stories.tsx +64 -0
- package/stories/Popover.stories.tsx +30 -0
- package/stories/SectionHeader.stories.tsx +20 -0
- package/stories/Select.stories.tsx +36 -0
- package/stories/Sheet.stories.tsx +59 -0
- package/stories/Slider.stories.tsx +24 -0
- package/stories/StatusCard.stories.tsx +30 -0
- package/stories/StatusUpdateTimeline.stories.tsx +77 -0
- package/stories/StrategyConfigCard.stories.tsx +57 -0
- package/stories/SubscribeButton.stories.tsx +27 -0
- package/stories/Table.stories.tsx +56 -0
- package/stories/Tabs.stories.tsx +40 -0
- package/stories/TerminalFeed.stories.tsx +47 -0
- package/stories/Textarea.stories.tsx +25 -0
- package/stories/ThemeProvider.stories.tsx +38 -0
- package/stories/Toast.stories.tsx +32 -0
- package/stories/Toggle.stories.tsx +43 -0
- package/stories/Tooltip.stories.tsx +20 -0
- package/stories/UserMenu.stories.tsx +35 -0
- package/tailwind.config.js +74 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StorybookConfig } from "@storybook/react-vite";
|
|
2
|
+
|
|
3
|
+
const config: StorybookConfig = {
|
|
4
|
+
stories: [
|
|
5
|
+
"../stories/**/*.mdx",
|
|
6
|
+
"../stories/**/*.stories.@(ts|tsx)",
|
|
7
|
+
],
|
|
8
|
+
addons: [
|
|
9
|
+
"@storybook/addon-docs",
|
|
10
|
+
"@storybook/addon-themes",
|
|
11
|
+
"@storybook/addon-a11y",
|
|
12
|
+
],
|
|
13
|
+
framework: {
|
|
14
|
+
name: "@storybook/react-vite",
|
|
15
|
+
options: {},
|
|
16
|
+
},
|
|
17
|
+
typescript: {
|
|
18
|
+
reactDocgen: "react-docgen",
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default config;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Preview } from "@storybook/react";
|
|
2
|
+
import { withThemeByClassName } from "@storybook/addon-themes";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { MemoryRouter } from "react-router-dom";
|
|
5
|
+
import {
|
|
6
|
+
ApiRegistryBuilder,
|
|
7
|
+
ApiProvider,
|
|
8
|
+
accessApiRef,
|
|
9
|
+
} from "@checkstack/frontend-api";
|
|
10
|
+
import { ThemeProvider } from "../src/components/ThemeProvider";
|
|
11
|
+
import { ToastProvider } from "../src/components/ToastProvider";
|
|
12
|
+
import { PerformanceProvider } from "../src/components/PerformanceProvider";
|
|
13
|
+
import { mockAccessApi } from "./mock-access-api";
|
|
14
|
+
import "./preview.css";
|
|
15
|
+
|
|
16
|
+
const apiRegistry = new ApiRegistryBuilder()
|
|
17
|
+
.register(accessApiRef, mockAccessApi)
|
|
18
|
+
.build();
|
|
19
|
+
|
|
20
|
+
const preview: Preview = {
|
|
21
|
+
parameters: {
|
|
22
|
+
controls: {
|
|
23
|
+
matchers: {
|
|
24
|
+
color: /(background|color)$/i,
|
|
25
|
+
date: /Date$/i,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
backgrounds: {
|
|
29
|
+
default: "app",
|
|
30
|
+
values: [
|
|
31
|
+
{ name: "app", value: "hsl(0 0% 100%)" },
|
|
32
|
+
{ name: "app-dark", value: "hsl(240 10% 4%)" },
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
layout: "padded",
|
|
36
|
+
options: {
|
|
37
|
+
storySort: {
|
|
38
|
+
order: [
|
|
39
|
+
"Introduction",
|
|
40
|
+
"Foundations",
|
|
41
|
+
"Components",
|
|
42
|
+
["Inputs", "Display", "Feedback", "Navigation", "Overlays", "Forms", "Layout", "Data"],
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
decorators: [
|
|
48
|
+
withThemeByClassName({
|
|
49
|
+
themes: {
|
|
50
|
+
light: "light",
|
|
51
|
+
dark: "dark",
|
|
52
|
+
},
|
|
53
|
+
defaultTheme: "light",
|
|
54
|
+
}),
|
|
55
|
+
(Story) => (
|
|
56
|
+
<MemoryRouter>
|
|
57
|
+
<ApiProvider registry={apiRegistry}>
|
|
58
|
+
<ThemeProvider defaultTheme="light" storageKey="checkstack-storybook-theme">
|
|
59
|
+
<ToastProvider>
|
|
60
|
+
<PerformanceProvider>
|
|
61
|
+
<div className="bg-background text-foreground p-4">
|
|
62
|
+
<Story />
|
|
63
|
+
</div>
|
|
64
|
+
</PerformanceProvider>
|
|
65
|
+
</ToastProvider>
|
|
66
|
+
</ThemeProvider>
|
|
67
|
+
</ApiProvider>
|
|
68
|
+
</MemoryRouter>
|
|
69
|
+
),
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default preview;
|
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/ui",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@checkstack/common": "0.
|
|
9
|
-
"@checkstack/frontend-api": "0.
|
|
8
|
+
"@checkstack/common": "0.9.0",
|
|
9
|
+
"@checkstack/frontend-api": "0.5.0",
|
|
10
10
|
"@monaco-editor/react": "^4.7.0",
|
|
11
11
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
12
12
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
@@ -23,26 +23,40 @@
|
|
|
23
23
|
"monaco-editor": "^0.55.1",
|
|
24
24
|
"react": "^18.2.0",
|
|
25
25
|
"react-day-picker": "^9.13.0",
|
|
26
|
-
"react-dom": "^
|
|
26
|
+
"react-dom": "^18.2.0",
|
|
27
27
|
"react-markdown": "^10.1.0",
|
|
28
28
|
"react-router-dom": "^6.20.0",
|
|
29
29
|
"recharts": "^3.6.0",
|
|
30
30
|
"tailwind-merge": "^2.2.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@checkstack/scripts": "0.3.
|
|
33
|
+
"@checkstack/scripts": "0.3.1",
|
|
34
34
|
"@checkstack/test-utils-frontend": "0.0.5",
|
|
35
35
|
"@checkstack/tsconfig": "0.0.7",
|
|
36
|
+
"@storybook/addon-a11y": "^10.3.6",
|
|
37
|
+
"@storybook/addon-docs": "^10.3.6",
|
|
38
|
+
"@storybook/addon-themes": "^10.3.6",
|
|
39
|
+
"@storybook/react": "^10.3.6",
|
|
40
|
+
"@storybook/react-vite": "^10.3.6",
|
|
36
41
|
"@testing-library/react": "^16.0.0",
|
|
37
42
|
"@types/react": "^18.2.0",
|
|
38
|
-
"@types/react-dom": "^
|
|
39
|
-
"
|
|
43
|
+
"@types/react-dom": "^18.2.0",
|
|
44
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
45
|
+
"autoprefixer": "^10.4.18",
|
|
46
|
+
"postcss": "^8.4.35",
|
|
47
|
+
"storybook": "^10.3.6",
|
|
48
|
+
"tailwindcss": "^3.4.1",
|
|
49
|
+
"tailwindcss-animate": "^1.0.7",
|
|
50
|
+
"typescript": "^5.0.0",
|
|
51
|
+
"vite": "^8.0.8"
|
|
40
52
|
},
|
|
41
53
|
"scripts": {
|
|
42
54
|
"typecheck": "tsgo -b",
|
|
43
55
|
"lint": "bun run lint:code",
|
|
44
56
|
"lint:code": "eslint . --max-warnings 0",
|
|
45
|
-
"test": "bun test"
|
|
57
|
+
"test": "bun test",
|
|
58
|
+
"storybook": "storybook dev -p 6006",
|
|
59
|
+
"storybook:build": "storybook build -o storybook-static"
|
|
46
60
|
},
|
|
47
61
|
"checkstack": {
|
|
48
62
|
"type": "tooling"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { AccessDenied } from "../src/components/AccessDenied";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof AccessDenied> = {
|
|
5
|
+
title: "Components/Feedback/AccessDenied",
|
|
6
|
+
component: AccessDenied,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof AccessDenied>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {};
|
|
14
|
+
|
|
15
|
+
export const CustomMessage: Story = {
|
|
16
|
+
args: { message: "You need 'catalog.manage' to view this page." },
|
|
17
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { AccessGate } from "../src/components/AccessGate";
|
|
3
|
+
|
|
4
|
+
const allowed = () => ({ loading: false, allowed: true });
|
|
5
|
+
const denied = () => ({ loading: false, allowed: false });
|
|
6
|
+
const loading = () => ({ loading: true, allowed: false });
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof AccessGate> = {
|
|
9
|
+
title: "Components/Feedback/AccessGate",
|
|
10
|
+
component: AccessGate,
|
|
11
|
+
tags: ["autodocs"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof AccessGate>;
|
|
16
|
+
|
|
17
|
+
export const Allowed: Story = {
|
|
18
|
+
args: {
|
|
19
|
+
accessRuleId: "demo.read",
|
|
20
|
+
useAccess: allowed,
|
|
21
|
+
children: <p className="text-sm">Gated content visible.</p>,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const Hidden: Story = {
|
|
26
|
+
args: {
|
|
27
|
+
accessRuleId: "demo.read",
|
|
28
|
+
useAccess: denied,
|
|
29
|
+
children: <p className="text-sm">You should not see this.</p>,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const ShowDenied: Story = {
|
|
34
|
+
args: {
|
|
35
|
+
accessRuleId: "demo.read",
|
|
36
|
+
useAccess: denied,
|
|
37
|
+
showDenied: true,
|
|
38
|
+
deniedMessage: "Demo access denied.",
|
|
39
|
+
children: <p>Hidden</p>,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const Loading: Story = {
|
|
44
|
+
args: {
|
|
45
|
+
accessRuleId: "demo.read",
|
|
46
|
+
useAccess: loading,
|
|
47
|
+
children: <p>Resolves once access loads.</p>,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import {
|
|
3
|
+
Accordion,
|
|
4
|
+
AccordionContent,
|
|
5
|
+
AccordionItem,
|
|
6
|
+
AccordionTrigger,
|
|
7
|
+
} from "../src/components/Accordion";
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof Accordion> = {
|
|
10
|
+
title: "Components/Display/Accordion",
|
|
11
|
+
component: Accordion,
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof Accordion>;
|
|
17
|
+
|
|
18
|
+
export const Single: Story = {
|
|
19
|
+
render: () => (
|
|
20
|
+
<Accordion type="single" collapsible className="max-w-md">
|
|
21
|
+
<AccordionItem value="a">
|
|
22
|
+
<AccordionTrigger>What is a health check?</AccordionTrigger>
|
|
23
|
+
<AccordionContent>
|
|
24
|
+
A periodic probe that asserts a system property and reports a status.
|
|
25
|
+
</AccordionContent>
|
|
26
|
+
</AccordionItem>
|
|
27
|
+
<AccordionItem value="b">
|
|
28
|
+
<AccordionTrigger>What is a strategy?</AccordionTrigger>
|
|
29
|
+
<AccordionContent>
|
|
30
|
+
A pluggable provider that defines how a check is executed.
|
|
31
|
+
</AccordionContent>
|
|
32
|
+
</AccordionItem>
|
|
33
|
+
<AccordionItem value="c">
|
|
34
|
+
<AccordionTrigger>What is a satellite?</AccordionTrigger>
|
|
35
|
+
<AccordionContent>
|
|
36
|
+
A standalone agent that runs checks from a remote network location.
|
|
37
|
+
</AccordionContent>
|
|
38
|
+
</AccordionItem>
|
|
39
|
+
</Accordion>
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const Multiple: Story = {
|
|
44
|
+
render: () => (
|
|
45
|
+
<Accordion type="multiple" className="max-w-md">
|
|
46
|
+
<AccordionItem value="a">
|
|
47
|
+
<AccordionTrigger>Section one</AccordionTrigger>
|
|
48
|
+
<AccordionContent>Content one.</AccordionContent>
|
|
49
|
+
</AccordionItem>
|
|
50
|
+
<AccordionItem value="b">
|
|
51
|
+
<AccordionTrigger>Section two</AccordionTrigger>
|
|
52
|
+
<AccordionContent>Content two.</AccordionContent>
|
|
53
|
+
</AccordionItem>
|
|
54
|
+
</Accordion>
|
|
55
|
+
),
|
|
56
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { CircleAlert, CircleCheck, Info, TriangleAlert } from "lucide-react";
|
|
3
|
+
import {
|
|
4
|
+
Alert,
|
|
5
|
+
AlertContent,
|
|
6
|
+
AlertDescription,
|
|
7
|
+
AlertIcon,
|
|
8
|
+
AlertTitle,
|
|
9
|
+
} from "../src/components/Alert";
|
|
10
|
+
|
|
11
|
+
const meta: Meta<typeof Alert> = {
|
|
12
|
+
title: "Components/Feedback/Alert",
|
|
13
|
+
component: Alert,
|
|
14
|
+
tags: ["autodocs"],
|
|
15
|
+
argTypes: {
|
|
16
|
+
variant: {
|
|
17
|
+
control: "select",
|
|
18
|
+
options: ["default", "success", "warning", "error", "info"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof Alert>;
|
|
25
|
+
|
|
26
|
+
export const Default: Story = {
|
|
27
|
+
args: { variant: "default" },
|
|
28
|
+
render: (args) => (
|
|
29
|
+
<Alert {...args}>
|
|
30
|
+
<AlertIcon>
|
|
31
|
+
<Info className="h-4 w-4" />
|
|
32
|
+
</AlertIcon>
|
|
33
|
+
<AlertContent>
|
|
34
|
+
<AlertTitle>Heads up</AlertTitle>
|
|
35
|
+
<AlertDescription>
|
|
36
|
+
This is an informational alert for plugin developers.
|
|
37
|
+
</AlertDescription>
|
|
38
|
+
</AlertContent>
|
|
39
|
+
</Alert>
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const Success: Story = {
|
|
44
|
+
args: { variant: "success" },
|
|
45
|
+
render: (args) => (
|
|
46
|
+
<Alert {...args}>
|
|
47
|
+
<AlertIcon>
|
|
48
|
+
<CircleCheck className="h-4 w-4" />
|
|
49
|
+
</AlertIcon>
|
|
50
|
+
<AlertContent>
|
|
51
|
+
<AlertTitle>Saved</AlertTitle>
|
|
52
|
+
<AlertDescription>Plugin configuration was saved.</AlertDescription>
|
|
53
|
+
</AlertContent>
|
|
54
|
+
</Alert>
|
|
55
|
+
),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Warning: Story = {
|
|
59
|
+
args: { variant: "warning" },
|
|
60
|
+
render: (args) => (
|
|
61
|
+
<Alert {...args}>
|
|
62
|
+
<AlertIcon>
|
|
63
|
+
<TriangleAlert className="h-4 w-4" />
|
|
64
|
+
</AlertIcon>
|
|
65
|
+
<AlertContent>
|
|
66
|
+
<AlertTitle>Heads up</AlertTitle>
|
|
67
|
+
<AlertDescription>
|
|
68
|
+
The satellite token will expire in 24 hours.
|
|
69
|
+
</AlertDescription>
|
|
70
|
+
</AlertContent>
|
|
71
|
+
</Alert>
|
|
72
|
+
),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const Error: Story = {
|
|
76
|
+
args: { variant: "error" },
|
|
77
|
+
render: (args) => (
|
|
78
|
+
<Alert {...args}>
|
|
79
|
+
<AlertIcon>
|
|
80
|
+
<CircleAlert className="h-4 w-4" />
|
|
81
|
+
</AlertIcon>
|
|
82
|
+
<AlertContent>
|
|
83
|
+
<AlertTitle>Something went wrong</AlertTitle>
|
|
84
|
+
<AlertDescription>The health check failed to start.</AlertDescription>
|
|
85
|
+
</AlertContent>
|
|
86
|
+
</Alert>
|
|
87
|
+
),
|
|
88
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { AmbientBackground } from "../src/components/AmbientBackground";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof AmbientBackground> = {
|
|
5
|
+
title: "Components/Layout/AmbientBackground",
|
|
6
|
+
component: AmbientBackground,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: "fullscreen",
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default meta;
|
|
14
|
+
type Story = StoryObj<typeof AmbientBackground>;
|
|
15
|
+
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
render: () => (
|
|
18
|
+
<AmbientBackground>
|
|
19
|
+
<div className="max-w-3xl mx-auto py-24 px-6">
|
|
20
|
+
<h1 className="text-4xl font-bold tracking-tight">Inverse glow grid</h1>
|
|
21
|
+
<p className="mt-4 text-muted-foreground">
|
|
22
|
+
Aurora blobs and a grid mask, with automatic graceful degradation when{" "}
|
|
23
|
+
<code>usePerformance().isLowPower</code> is true.
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
26
|
+
</AmbientBackground>
|
|
27
|
+
),
|
|
28
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { AnimatedCounter } from "../src/components/AnimatedCounter";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof AnimatedCounter> = {
|
|
6
|
+
title: "Components/Display/AnimatedCounter",
|
|
7
|
+
component: AnimatedCounter,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof AnimatedCounter>;
|
|
13
|
+
|
|
14
|
+
const Demo = () => {
|
|
15
|
+
const [value, setValue] = useState(0);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const id = setInterval(
|
|
18
|
+
() => setValue((v) => (v >= 1000 ? 0 : v + Math.floor(Math.random() * 200))),
|
|
19
|
+
1500,
|
|
20
|
+
);
|
|
21
|
+
return () => clearInterval(id);
|
|
22
|
+
}, []);
|
|
23
|
+
return (
|
|
24
|
+
<div className="text-4xl font-bold">
|
|
25
|
+
<AnimatedCounter value={value} />
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const TickingUp: Story = {
|
|
31
|
+
render: () => <Demo />,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const StaticValue: Story = {
|
|
35
|
+
args: { value: 1042 },
|
|
36
|
+
render: (args) => (
|
|
37
|
+
<span className="text-3xl font-bold">
|
|
38
|
+
<AnimatedCounter {...args} />
|
|
39
|
+
</span>
|
|
40
|
+
),
|
|
41
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { AnimatedNumber } from "../src/components/AnimatedNumber";
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof AnimatedNumber> = {
|
|
6
|
+
title: "Components/Display/AnimatedNumber",
|
|
7
|
+
component: AnimatedNumber,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
type Story = StoryObj<typeof AnimatedNumber>;
|
|
13
|
+
|
|
14
|
+
const Demo = () => {
|
|
15
|
+
const [value, setValue] = useState(99.95);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const id = setInterval(
|
|
18
|
+
() => setValue(95 + Math.random() * 5),
|
|
19
|
+
1500,
|
|
20
|
+
);
|
|
21
|
+
return () => clearInterval(id);
|
|
22
|
+
}, []);
|
|
23
|
+
return (
|
|
24
|
+
<div className="text-3xl font-bold text-success tabular-nums">
|
|
25
|
+
<AnimatedNumber value={value} suffix="%" decimals={2} />
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const Uptime: Story = { render: () => <Demo /> };
|
|
31
|
+
|
|
32
|
+
export const NA: Story = {
|
|
33
|
+
args: { value: undefined },
|
|
34
|
+
render: (args) => (
|
|
35
|
+
<span className="text-2xl font-bold">
|
|
36
|
+
<AnimatedNumber {...args} />
|
|
37
|
+
</span>
|
|
38
|
+
),
|
|
39
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { BackLink } from "../src/components/BackLink";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof BackLink> = {
|
|
5
|
+
title: "Components/Navigation/BackLink",
|
|
6
|
+
component: BackLink,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof BackLink>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
onClick: () => {
|
|
16
|
+
/* navigate back */
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const CustomLabel: Story = {
|
|
22
|
+
args: {
|
|
23
|
+
children: "Back to systems",
|
|
24
|
+
onClick: () => {
|
|
25
|
+
/* navigate back */
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const AsLink: Story = {
|
|
31
|
+
args: { to: "/catalog" },
|
|
32
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Badge } from "../src/components/Badge";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Badge> = {
|
|
5
|
+
title: "Components/Display/Badge",
|
|
6
|
+
component: Badge,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
argTypes: {
|
|
9
|
+
variant: {
|
|
10
|
+
control: "select",
|
|
11
|
+
options: ["default", "secondary", "destructive", "outline", "success", "warning", "info"],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
children: "Badge",
|
|
16
|
+
variant: "default",
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<typeof Badge>;
|
|
22
|
+
|
|
23
|
+
export const Default: Story = {};
|
|
24
|
+
|
|
25
|
+
export const Variants: Story = {
|
|
26
|
+
render: () => (
|
|
27
|
+
<div className="flex flex-wrap gap-2">
|
|
28
|
+
<Badge variant="default">Default</Badge>
|
|
29
|
+
<Badge variant="secondary">Secondary</Badge>
|
|
30
|
+
<Badge variant="destructive">Destructive</Badge>
|
|
31
|
+
<Badge variant="outline">Outline</Badge>
|
|
32
|
+
<Badge variant="success">Success</Badge>
|
|
33
|
+
<Badge variant="warning">Warning</Badge>
|
|
34
|
+
<Badge variant="info">Info</Badge>
|
|
35
|
+
</div>
|
|
36
|
+
),
|
|
37
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { Button } from "../src/components/Button";
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Button> = {
|
|
5
|
+
title: "Components/Inputs/Button",
|
|
6
|
+
component: Button,
|
|
7
|
+
tags: ["autodocs"],
|
|
8
|
+
argTypes: {
|
|
9
|
+
variant: {
|
|
10
|
+
control: "select",
|
|
11
|
+
options: ["primary", "secondary", "outline", "ghost", "destructive", "link"],
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
control: "select",
|
|
15
|
+
options: ["default", "sm", "lg", "icon"],
|
|
16
|
+
},
|
|
17
|
+
disabled: { control: "boolean" },
|
|
18
|
+
},
|
|
19
|
+
args: {
|
|
20
|
+
children: "Click me",
|
|
21
|
+
variant: "primary",
|
|
22
|
+
size: "default",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof Button>;
|
|
28
|
+
|
|
29
|
+
export const Primary: Story = {};
|
|
30
|
+
|
|
31
|
+
export const Secondary: Story = { args: { variant: "secondary" } };
|
|
32
|
+
|
|
33
|
+
export const Outline: Story = { args: { variant: "outline" } };
|
|
34
|
+
|
|
35
|
+
export const Ghost: Story = { args: { variant: "ghost" } };
|
|
36
|
+
|
|
37
|
+
export const Destructive: Story = { args: { variant: "destructive" } };
|
|
38
|
+
|
|
39
|
+
export const Link: Story = { args: { variant: "link" } };
|
|
40
|
+
|
|
41
|
+
export const AllSizes: Story = {
|
|
42
|
+
render: (args) => (
|
|
43
|
+
<div className="flex items-center gap-3">
|
|
44
|
+
<Button {...args} size="sm">
|
|
45
|
+
Small
|
|
46
|
+
</Button>
|
|
47
|
+
<Button {...args} size="default">
|
|
48
|
+
Default
|
|
49
|
+
</Button>
|
|
50
|
+
<Button {...args} size="lg">
|
|
51
|
+
Large
|
|
52
|
+
</Button>
|
|
53
|
+
</div>
|
|
54
|
+
),
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const Disabled: Story = { args: { disabled: true } };
|