mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-11-30 17:06:33 +00:00
### What problem does this PR solve? Feat: Display AvatarUpload and RAGFlowAvatar in Storybook #9914 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
abd19b0f48
commit
d04ae3f943
@ -13,7 +13,7 @@ module.exports = {
|
||||
'check-file/filename-naming-convention': [
|
||||
'error',
|
||||
{
|
||||
'**/*.{jsx,tsx}': 'KEBAB_CASE',
|
||||
'**/*.{jsx,tsx}': '[a-z0-9.-]*',
|
||||
'**/*.{js,ts}': '[a-z0-9.-]*',
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
import type { Preview } from '@storybook/react-webpack5';
|
||||
import { createElement } from 'react';
|
||||
import { TooltipProvider } from '../src/components/ui/tooltip';
|
||||
|
||||
import '../tailwind.css';
|
||||
|
||||
const preview: Preview = {
|
||||
@ -10,6 +13,9 @@ const preview: Preview = {
|
||||
},
|
||||
},
|
||||
},
|
||||
decorators: [
|
||||
(Story) => createElement(TooltipProvider, null, createElement(Story)),
|
||||
],
|
||||
};
|
||||
|
||||
export default preview;
|
||||
|
||||
99
web/src/stories/avatar-upload.stories.ts
Normal file
99
web/src/stories/avatar-upload.stories.ts
Normal file
@ -0,0 +1,99 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||
|
||||
import { fn } from 'storybook/test';
|
||||
|
||||
import { AvatarUpload } from '@/components/avatar-upload';
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||
const meta = {
|
||||
title: 'Example/AvatarUpload',
|
||||
component: AvatarUpload,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
## AvatarUpload Component
|
||||
|
||||
AvatarUpload is a file upload component specifically designed for uploading and displaying avatar images. It supports image preview, removal, and provides a user-friendly interface for avatar management.
|
||||
|
||||
### Import Path
|
||||
\`\`\`typescript
|
||||
import { AvatarUpload } from '@/components/avatar-upload';
|
||||
\`\`\`
|
||||
|
||||
### Basic Usage
|
||||
\`\`\`tsx
|
||||
import { useState } from 'react';
|
||||
import { AvatarUpload } from '@/components/avatar-upload';
|
||||
|
||||
function MyComponent() {
|
||||
const [avatarValue, setAvatarValue] = useState('');
|
||||
|
||||
return (
|
||||
<AvatarUpload
|
||||
value={avatarValue}
|
||||
onChange={(base64String) => setAvatarValue(base64String)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Features
|
||||
- Supports image upload with drag & drop
|
||||
- Image preview with hover effects
|
||||
- Remove button to clear selected image
|
||||
- Base64 encoding for easy handling
|
||||
- Accepts common image formats (jpg, jpeg, png, webp, bmp)
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||
argTypes: {
|
||||
value: {
|
||||
description: 'The current avatar value as base64 string',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
onChange: {
|
||||
description: 'Callback function called when avatar changes',
|
||||
control: false,
|
||||
type: { name: 'function', required: false },
|
||||
},
|
||||
},
|
||||
// Use `fn` to spy on the onChange arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
|
||||
args: { onChange: fn() },
|
||||
} satisfies Meta<typeof AvatarUpload>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||
export const EmptyState: Story = {
|
||||
args: {
|
||||
value: '',
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Empty State
|
||||
|
||||
Shows the upload area when no avatar is selected.
|
||||
|
||||
\`\`\`tsx
|
||||
<AvatarUpload
|
||||
value=""
|
||||
onChange={(base64String) => console.log('Avatar uploaded:', base64String)}
|
||||
/>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
192
web/src/stories/ragflow-avatar.stories.ts
Normal file
192
web/src/stories/ragflow-avatar.stories.ts
Normal file
@ -0,0 +1,192 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||
|
||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||
const meta = {
|
||||
title: 'Example/RAGFlowAvatar',
|
||||
component: RAGFlowAvatar,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
## RAGFlowAvatar Component
|
||||
|
||||
RAGFlowAvatar is a customizable avatar component that displays user avatars with intelligent fallbacks. When an image is not available, it generates colorful gradient backgrounds with user initials.
|
||||
|
||||
### Import Path
|
||||
\`\`\`typescript
|
||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||
\`\`\`
|
||||
|
||||
### Basic Usage
|
||||
\`\`\`tsx
|
||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||
|
||||
function MyComponent() {
|
||||
return (
|
||||
<RAGFlowAvatar
|
||||
name="John Doe"
|
||||
avatar="https://example.com/avatar.jpg"
|
||||
isPerson={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Features
|
||||
- Displays user avatar images when available
|
||||
- Generates colorful gradient fallbacks with initials
|
||||
- Supports both person (circular) and non-person (rounded) styles
|
||||
- Automatic font size calculation based on container size
|
||||
- Color generation based on name for consistent appearance
|
||||
- Responsive design with resize observer
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||
argTypes: {
|
||||
name: {
|
||||
description:
|
||||
'The name to display initials for when no avatar is available',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
avatar: {
|
||||
description: 'The URL of the avatar image',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
isPerson: {
|
||||
description: 'Whether this avatar represents a person (affects styling)',
|
||||
control: { type: 'boolean' },
|
||||
type: { name: 'boolean', required: false },
|
||||
defaultValue: false,
|
||||
},
|
||||
className: {
|
||||
description: 'Additional CSS classes to apply',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
},
|
||||
args: {
|
||||
name: 'John Doe',
|
||||
isPerson: false,
|
||||
},
|
||||
} satisfies Meta<typeof RAGFlowAvatar>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||
export const WithInitials: Story = {
|
||||
args: {
|
||||
name: 'John Doe',
|
||||
isPerson: false,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### With Initials Only
|
||||
|
||||
Shows the avatar component with only a name, displaying generated initials with a gradient background.
|
||||
|
||||
\`\`\`tsx
|
||||
<RAGFlowAvatar
|
||||
name="John Doe"
|
||||
isPerson={false}
|
||||
/>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
|
||||
export const WithAvatar: Story = {
|
||||
args: {
|
||||
name: 'Jane Smith',
|
||||
avatar:
|
||||
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMzIiIGZpbGw9IiM0RjZERUUiLz4KPGNpcmNsZSBjeD0iMzIiIGN5PSIyNCIgcj0iOCIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTQ4IDQ4QzQ4IDQxLjM3MyA0MS45NDA2IDM2IDM0LjUgMzZIMjkuNUMyMi4wNTk0IDM2IDE2IDQxLjM3MyAxNiA0OCIgZmlsbD0id2hpdGUiLz4KPC9zdmc+',
|
||||
isPerson: true,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### With Avatar Image
|
||||
|
||||
Shows the avatar component with an actual image. When isPerson is true, the avatar will be circular.
|
||||
|
||||
\`\`\`tsx
|
||||
<RAGFlowAvatar
|
||||
name="Jane Smith"
|
||||
avatar="https://example.com/avatar.jpg"
|
||||
isPerson={true}
|
||||
/>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
|
||||
export const PersonStyle: Story = {
|
||||
args: {
|
||||
name: 'Alice Johnson',
|
||||
isPerson: true,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Person Style (Circular)
|
||||
|
||||
Shows the avatar component with isPerson set to true, which makes it circular.
|
||||
|
||||
\`\`\`tsx
|
||||
<RAGFlowAvatar
|
||||
name="Alice Johnson"
|
||||
isPerson={true}
|
||||
/>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
|
||||
export const NonPersonStyle: Story = {
|
||||
args: {
|
||||
name: 'Bot Assistant',
|
||||
isPerson: false,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Non-Person Style (Rounded Rectangle)
|
||||
|
||||
Shows the avatar component with isPerson set to false, which makes it a rounded rectangle.
|
||||
|
||||
\`\`\`tsx
|
||||
<RAGFlowAvatar
|
||||
name="Bot Assistant"
|
||||
isPerson={false}
|
||||
/>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
231
web/src/stories/ragflow-form.stories.tsx
Normal file
231
web/src/stories/ragflow-form.stories.tsx
Normal file
@ -0,0 +1,231 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||
import { Form } from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
||||
// Define form schema
|
||||
const FormSchema = z.object({
|
||||
username: z.string().min(2, {
|
||||
message: 'Username must be at least 2 characters.',
|
||||
}),
|
||||
email: z.string().email({
|
||||
message: 'Please enter a valid email address.',
|
||||
}),
|
||||
description: z.string().optional(),
|
||||
});
|
||||
|
||||
// Create a wrapper component to demonstrate RAGFlowFormItem
|
||||
function FormExample({
|
||||
horizontal = false,
|
||||
fieldName = 'username',
|
||||
label = 'Username',
|
||||
tooltip = 'Please enter your username',
|
||||
placeholder = 'Enter username',
|
||||
}: {
|
||||
horizontal?: boolean;
|
||||
fieldName?: string;
|
||||
label?: string;
|
||||
tooltip?: string;
|
||||
placeholder?: string;
|
||||
}) {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: {
|
||||
username: '',
|
||||
email: '',
|
||||
description: '',
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="w-full p-4 border rounded-lg">
|
||||
<Form {...form}>
|
||||
<form className="space-y-4">
|
||||
<RAGFlowFormItem
|
||||
name={fieldName}
|
||||
label={label}
|
||||
tooltip={tooltip}
|
||||
horizontal={horizontal}
|
||||
>
|
||||
<Input placeholder={placeholder} />
|
||||
</RAGFlowFormItem>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||
const meta = {
|
||||
title: 'Example/RAGFlowForm',
|
||||
component: FormExample,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
## RAGFlowFormItem Component
|
||||
|
||||
RAGFlowFormItem is a wrapper component built on top of shadcn/ui Form components, providing unified form item styling and layout.
|
||||
|
||||
### Import Path
|
||||
\`\`\`typescript
|
||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||
import { Form } from '@/components/ui/form';
|
||||
\`\`\`
|
||||
|
||||
### Basic Usage
|
||||
\`\`\`tsx
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { z } from 'zod';
|
||||
|
||||
const FormSchema = z.object({
|
||||
username: z.string(),
|
||||
});
|
||||
|
||||
function MyForm() {
|
||||
const form = useForm({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: { username: '' },
|
||||
});
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form>
|
||||
<RAGFlowFormItem
|
||||
name="username"
|
||||
label="Username"
|
||||
tooltip="Please enter your username"
|
||||
>
|
||||
<Input placeholder="Enter username" />
|
||||
</RAGFlowFormItem>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Features
|
||||
- Built-in FormField, FormItem, FormLabel, FormControl and FormMessage
|
||||
- Supports both horizontal and vertical layouts
|
||||
- Supports tooltip hints
|
||||
- Fully compatible with react-hook-form
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||
argTypes: {
|
||||
horizontal: {
|
||||
description: 'Whether to display the form item horizontally',
|
||||
control: { type: 'boolean' },
|
||||
type: { name: 'boolean', required: false },
|
||||
defaultValue: false,
|
||||
},
|
||||
fieldName: {
|
||||
description: 'The name of the form field',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: true },
|
||||
},
|
||||
label: {
|
||||
description: 'The label of the form field',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
tooltip: {
|
||||
description: 'The tooltip text for the form field',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
placeholder: {
|
||||
description: 'The placeholder text for the input',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
},
|
||||
args: {
|
||||
horizontal: false,
|
||||
fieldName: 'username',
|
||||
label: 'Username',
|
||||
tooltip: 'Please enter your username',
|
||||
placeholder: 'Enter username',
|
||||
},
|
||||
} satisfies Meta<typeof FormExample>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||
export const VerticalLayout: Story = {
|
||||
args: {
|
||||
horizontal: false,
|
||||
fieldName: 'username',
|
||||
label: 'Username',
|
||||
tooltip: 'Please enter your username',
|
||||
placeholder: 'Enter username',
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Vertical Layout Example
|
||||
|
||||
Default vertical layout with label above the input field.
|
||||
|
||||
\`\`\`tsx
|
||||
<RAGFlowFormItem
|
||||
name="username"
|
||||
label="Username"
|
||||
tooltip="Please enter your username"
|
||||
horizontal={false}
|
||||
>
|
||||
<Input placeholder="Enter username" />
|
||||
</RAGFlowFormItem>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// tags: ['!dev'],
|
||||
};
|
||||
|
||||
export const HorizontalLayout: Story = {
|
||||
args: {
|
||||
horizontal: true,
|
||||
fieldName: 'email',
|
||||
label: 'Email Address',
|
||||
tooltip: 'Please enter a valid email address',
|
||||
placeholder: 'Enter email',
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Horizontal Layout Example
|
||||
|
||||
Horizontal layout with label and input field on the same row.
|
||||
|
||||
\`\`\`tsx
|
||||
<RAGFlowFormItem
|
||||
name="email"
|
||||
label="Email Address"
|
||||
tooltip="Please enter a valid email address"
|
||||
horizontal={true}
|
||||
>
|
||||
<Input type="email" placeholder="Enter email" />
|
||||
</RAGFlowFormItem>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// tags: ['!dev'],
|
||||
};
|
||||
68
web/src/stories/ragflow-pagination.stories.ts
Normal file
68
web/src/stories/ragflow-pagination.stories.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||
|
||||
import { fn } from 'storybook/test';
|
||||
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||
const meta = {
|
||||
title: 'Example/RAGFlowPagination',
|
||||
component: RAGFlowPagination,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
## Component Description
|
||||
|
||||
RAGFlowPagination is a pagination component that helps navigate through large datasets by dividing them into pages. It provides intuitive controls for users to move between pages, adjust page size, and view their current position within the dataset.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||
argTypes: {
|
||||
current: { control: 'number' },
|
||||
pageSize: { control: 'number' },
|
||||
total: { control: 'number' },
|
||||
},
|
||||
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
|
||||
args: { onChange: fn() },
|
||||
} satisfies Meta<typeof RAGFlowPagination>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||
export const WithLoading: Story = {
|
||||
args: {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 100,
|
||||
showSizeChanger: true,
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Usage Examples
|
||||
|
||||
\`\`\`tsx
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total}
|
||||
onChange={(page, pageSize) => {
|
||||
setPagination({ page, pageSize });
|
||||
}}>
|
||||
</RAGFlowPagination>
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
85
web/src/stories/skeleton-card.stories.ts
Normal file
85
web/src/stories/skeleton-card.stories.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||
|
||||
import { SkeletonCard } from '@/components/skeleton-card';
|
||||
|
||||
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||
const meta = {
|
||||
title: 'Example/SkeletonCard',
|
||||
component: SkeletonCard,
|
||||
parameters: {
|
||||
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component: `
|
||||
## SkeletonCard Component
|
||||
|
||||
SkeletonCard is a loading placeholder component that displays skeleton lines while content is being loaded. It provides a consistent loading experience with animated placeholders.
|
||||
|
||||
### Import Path
|
||||
\`\`\`typescript
|
||||
import { SkeletonCard } from '@/components/skeleton-card';
|
||||
\`\`\`
|
||||
|
||||
### Basic Usage
|
||||
\`\`\`tsx
|
||||
import { SkeletonCard } from '@/components/skeleton-card';
|
||||
|
||||
function MyComponent() {
|
||||
return (
|
||||
<SkeletonCard className="w-64" />
|
||||
);
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
### Features
|
||||
- Displays animated skeleton loading placeholders
|
||||
- Three lines of skeleton content with varying widths
|
||||
- Customizable styling through className prop
|
||||
- Consistent spacing and appearance
|
||||
- Built on top of the Skeleton UI component
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
|
||||
tags: ['autodocs'],
|
||||
// More on argTypes: https://storybook.js.org/docs/api/argtypes
|
||||
argTypes: {
|
||||
className: {
|
||||
description: 'Additional CSS classes to apply to the skeleton card',
|
||||
control: { type: 'text' },
|
||||
type: { name: 'string', required: false },
|
||||
},
|
||||
},
|
||||
args: {
|
||||
className: '',
|
||||
},
|
||||
} satisfies Meta<typeof SkeletonCard>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||
|
||||
export const WithCustomWidth: Story = {
|
||||
args: {
|
||||
className: 'w-80',
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: `
|
||||
### Custom Width
|
||||
|
||||
Shows the skeleton card with a custom width applied.
|
||||
|
||||
\`\`\`tsx
|
||||
<SkeletonCard className="w-80" />
|
||||
\`\`\`
|
||||
`,
|
||||
},
|
||||
},
|
||||
},
|
||||
tags: ['!dev'],
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user