feat(ui): add Storybook for @bytelyst/ui component library
- Storybook 8 with React Vite framework + a11y addon - Stories for Button (7 variants), Badge (6), Input (5), Card (4) - Dark/elevated/light background presets - Run: pnpm --filter @bytelyst/ui storybook
This commit is contained in:
parent
a5d1c5f0b9
commit
11a832e271
12
packages/ui/.storybook/main.ts
Normal file
12
packages/ui/.storybook/main.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type { StorybookConfig } from '@storybook/react-vite';
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../src/**/*.stories.@(ts|tsx)'],
|
||||
addons: ['@storybook/addon-essentials', '@storybook/addon-a11y'],
|
||||
framework: {
|
||||
name: '@storybook/react-vite',
|
||||
options: {},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
16
packages/ui/.storybook/preview.ts
Normal file
16
packages/ui/.storybook/preview.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import type { Preview } from '@storybook/react';
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
backgrounds: {
|
||||
default: 'dark',
|
||||
values: [
|
||||
{ name: 'dark', value: '#06070A' },
|
||||
{ name: 'elevated', value: '#0E1118' },
|
||||
{ name: 'light', value: '#F8F9FC' },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
@ -2,6 +2,10 @@
|
||||
"name": "@bytelyst/ui",
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"storybook": "storybook dev -p 6006",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./button": "./src/components/Button.tsx",
|
||||
@ -31,6 +35,12 @@
|
||||
"devDependencies": {
|
||||
"typescript": "^5.7.0",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-dom": "^19.0.0"
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"@storybook/react-vite": "^8.5.0",
|
||||
"@storybook/react": "^8.5.0",
|
||||
"@storybook/addon-essentials": "^8.5.0",
|
||||
"@storybook/addon-a11y": "^8.5.0",
|
||||
"storybook": "^8.5.0",
|
||||
"vite": "^6.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
22
packages/ui/src/components/Badge.stories.tsx
Normal file
22
packages/ui/src/components/Badge.stories.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Badge } from './Badge.js';
|
||||
|
||||
const meta: Meta<typeof Badge> = {
|
||||
title: 'Components/Badge',
|
||||
component: Badge,
|
||||
argTypes: {
|
||||
variant: { control: 'select', options: ['success', 'warning', 'error', 'info', 'neutral'] },
|
||||
size: { control: 'select', options: ['sm', 'md'] },
|
||||
dot: { control: 'boolean' },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Badge>;
|
||||
|
||||
export const Success: Story = { args: { children: 'Active', variant: 'success' } };
|
||||
export const Warning: Story = { args: { children: 'Pending', variant: 'warning' } };
|
||||
export const Error: Story = { args: { children: 'Failed', variant: 'error' } };
|
||||
export const Info: Story = { args: { children: 'Info', variant: 'info' } };
|
||||
export const Neutral: Story = { args: { children: 'Draft', variant: 'neutral' } };
|
||||
export const WithDot: Story = { args: { children: 'Online', variant: 'success', dot: true } };
|
||||
44
packages/ui/src/components/Button.stories.tsx
Normal file
44
packages/ui/src/components/Button.stories.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Button } from './Button.js';
|
||||
|
||||
const meta: Meta<typeof Button> = {
|
||||
title: 'Components/Button',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
variant: { control: 'select', options: ['primary', 'secondary', 'ghost', 'danger'] },
|
||||
size: { control: 'select', options: ['sm', 'md', 'lg'] },
|
||||
loading: { control: 'boolean' },
|
||||
disabled: { control: 'boolean' },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Button>;
|
||||
|
||||
export const Primary: Story = {
|
||||
args: { children: 'Primary Button', variant: 'primary' },
|
||||
};
|
||||
|
||||
export const Secondary: Story = {
|
||||
args: { children: 'Secondary Button', variant: 'secondary' },
|
||||
};
|
||||
|
||||
export const Ghost: Story = {
|
||||
args: { children: 'Ghost Button', variant: 'ghost' },
|
||||
};
|
||||
|
||||
export const Danger: Story = {
|
||||
args: { children: 'Danger Button', variant: 'danger' },
|
||||
};
|
||||
|
||||
export const Loading: Story = {
|
||||
args: { children: 'Loading...', variant: 'primary', loading: true },
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
args: { children: 'Small', variant: 'primary', size: 'sm' },
|
||||
};
|
||||
|
||||
export const Large: Story = {
|
||||
args: { children: 'Large', variant: 'primary', size: 'lg' },
|
||||
};
|
||||
38
packages/ui/src/components/Card.stories.tsx
Normal file
38
packages/ui/src/components/Card.stories.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Card, CardHeader, CardTitle, CardDescription } from './Card.js';
|
||||
|
||||
const meta: Meta<typeof Card> = {
|
||||
title: 'Components/Card',
|
||||
component: Card,
|
||||
argTypes: {
|
||||
padding: { control: 'select', options: ['none', 'sm', 'md', 'lg'] },
|
||||
hover: { control: 'boolean' },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Card>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: { children: 'Card content goes here' },
|
||||
};
|
||||
|
||||
export const WithHeader: Story = {
|
||||
render: args => (
|
||||
<Card {...args}>
|
||||
<CardHeader>
|
||||
<CardTitle>Card Title</CardTitle>
|
||||
<CardDescription>A short description of this card.</CardDescription>
|
||||
</CardHeader>
|
||||
<p style={{ color: 'var(--bl-text-secondary, #a0a0b0)', fontSize: 14 }}>Body content</p>
|
||||
</Card>
|
||||
),
|
||||
};
|
||||
|
||||
export const Hoverable: Story = {
|
||||
args: { hover: true, children: 'Hover me to see the border effect' },
|
||||
};
|
||||
|
||||
export const LargePadding: Story = {
|
||||
args: { padding: 'lg', children: 'Large padding card' },
|
||||
};
|
||||
20
packages/ui/src/components/Input.stories.tsx
Normal file
20
packages/ui/src/components/Input.stories.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { Input } from './Input.js';
|
||||
|
||||
const meta: Meta<typeof Input> = {
|
||||
title: 'Components/Input',
|
||||
component: Input,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Input>;
|
||||
|
||||
export const Default: Story = { args: { placeholder: 'Enter text...' } };
|
||||
export const WithLabel: Story = { args: { label: 'Email', placeholder: 'you@example.com' } };
|
||||
export const WithError: Story = {
|
||||
args: { label: 'Email', value: 'bad', error: 'Invalid email address' },
|
||||
};
|
||||
export const WithHint: Story = {
|
||||
args: { label: 'Username', placeholder: 'johndoe', hint: '3-20 characters, no spaces' },
|
||||
};
|
||||
export const Disabled: Story = { args: { label: 'Read Only', value: 'locked', disabled: true } };
|
||||
Loading…
Reference in New Issue
Block a user