@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.
Files changed (68) hide show
  1. package/.storybook/main.ts +22 -0
  2. package/.storybook/manager-head.html +2 -0
  3. package/.storybook/mock-access-api.ts +5 -0
  4. package/.storybook/preview.css +5 -0
  5. package/.storybook/preview.tsx +73 -0
  6. package/CHANGELOG.md +8 -0
  7. package/package.json +22 -8
  8. package/postcss.config.js +6 -0
  9. package/stories/AccessDenied.stories.tsx +17 -0
  10. package/stories/AccessGate.stories.tsx +49 -0
  11. package/stories/Accordion.stories.tsx +56 -0
  12. package/stories/Alert.stories.tsx +88 -0
  13. package/stories/AmbientBackground.stories.tsx +28 -0
  14. package/stories/AnimatedCounter.stories.tsx +41 -0
  15. package/stories/AnimatedNumber.stories.tsx +39 -0
  16. package/stories/BackLink.stories.tsx +32 -0
  17. package/stories/Badge.stories.tsx +37 -0
  18. package/stories/Button.stories.tsx +57 -0
  19. package/stories/Card.stories.tsx +39 -0
  20. package/stories/Checkbox.stories.tsx +45 -0
  21. package/stories/CodeEditor.stories.tsx +67 -0
  22. package/stories/ColorPicker.stories.tsx +24 -0
  23. package/stories/CommandPalette.stories.tsx +36 -0
  24. package/stories/ConfirmationModal.stories.tsx +40 -0
  25. package/stories/DateRangeFilter.stories.tsx +30 -0
  26. package/stories/DateTimePicker.stories.tsx +26 -0
  27. package/stories/Dialog.stories.tsx +62 -0
  28. package/stories/DynamicForm.stories.tsx +83 -0
  29. package/stories/DynamicIcon.stories.tsx +52 -0
  30. package/stories/EditableText.stories.tsx +29 -0
  31. package/stories/Feedback.stories.tsx +45 -0
  32. package/stories/IDELayout.stories.tsx +70 -0
  33. package/stories/InfoBanner.stories.tsx +41 -0
  34. package/stories/Input.stories.tsx +29 -0
  35. package/stories/InstanceScopeBanner.stories.tsx +35 -0
  36. package/stories/Introduction.mdx +50 -0
  37. package/stories/Label.stories.tsx +21 -0
  38. package/stories/LinksEditor.stories.tsx +37 -0
  39. package/stories/Markdown.stories.tsx +35 -0
  40. package/stories/Menu.stories.tsx +35 -0
  41. package/stories/MetricTile.stories.tsx +31 -0
  42. package/stories/NavItem.stories.tsx +29 -0
  43. package/stories/NotFound.stories.tsx +17 -0
  44. package/stories/Page.stories.tsx +29 -0
  45. package/stories/PageLayout.stories.tsx +59 -0
  46. package/stories/PaginatedList.stories.tsx +44 -0
  47. package/stories/Pagination.stories.tsx +31 -0
  48. package/stories/PerformanceProvider.stories.tsx +33 -0
  49. package/stories/PluginConfigForm.stories.tsx +64 -0
  50. package/stories/Popover.stories.tsx +30 -0
  51. package/stories/SectionHeader.stories.tsx +20 -0
  52. package/stories/Select.stories.tsx +36 -0
  53. package/stories/Sheet.stories.tsx +59 -0
  54. package/stories/Slider.stories.tsx +24 -0
  55. package/stories/StatusCard.stories.tsx +30 -0
  56. package/stories/StatusUpdateTimeline.stories.tsx +77 -0
  57. package/stories/StrategyConfigCard.stories.tsx +57 -0
  58. package/stories/SubscribeButton.stories.tsx +27 -0
  59. package/stories/Table.stories.tsx +56 -0
  60. package/stories/Tabs.stories.tsx +40 -0
  61. package/stories/TerminalFeed.stories.tsx +47 -0
  62. package/stories/Textarea.stories.tsx +25 -0
  63. package/stories/ThemeProvider.stories.tsx +38 -0
  64. package/stories/Toast.stories.tsx +32 -0
  65. package/stories/Toggle.stories.tsx +43 -0
  66. package/stories/Tooltip.stories.tsx +20 -0
  67. package/stories/UserMenu.stories.tsx +35 -0
  68. 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,2 @@
1
+ <title>Checkstack UI — Component Library</title>
2
+ <meta name="description" content="Component library for Checkstack plugin developers." />
@@ -0,0 +1,5 @@
1
+ import type { AccessApi } from "@checkstack/frontend-api";
2
+
3
+ export const mockAccessApi: AccessApi = {
4
+ useAccess: () => ({ loading: false, allowed: true }),
5
+ };
@@ -0,0 +1,5 @@
1
+ @import "../src/themes.css";
2
+
3
+ @tailwind base;
4
+ @tailwind components;
5
+ @tailwind utilities;
@@ -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
@@ -1,5 +1,13 @@
1
1
  # @checkstack/ui
2
2
 
3
+ ## 1.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [9016526]
8
+ - @checkstack/common@0.10.0
9
+ - @checkstack/frontend-api@0.5.1
10
+
3
11
  ## 1.8.0
4
12
 
5
13
  ### Minor Changes
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@checkstack/ui",
3
- "version": "1.8.0",
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.8.0",
9
- "@checkstack/frontend-api": "0.4.2",
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": "^19.2.5",
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.0",
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": "^19.2.3",
39
- "typescript": "^5.0.0"
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,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -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 } };