Skip to content

Commit ffc8ce3

Browse files
committed
Feat: Display AvatarUpload and RAGFlowAvatar in Storybook #9914
1 parent aa1251a commit ffc8ce3

File tree

7 files changed

+682
-1
lines changed

7 files changed

+682
-1
lines changed

web/.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = {
1313
'check-file/filename-naming-convention': [
1414
'error',
1515
{
16-
'**/*.{jsx,tsx}': 'KEBAB_CASE',
16+
'**/*.{jsx,tsx}': '[a-z0-9.-]*',
1717
'**/*.{js,ts}': '[a-z0-9.-]*',
1818
},
1919
],

web/.storybook/preview.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type { Preview } from '@storybook/react-webpack5';
2+
import { createElement } from 'react';
3+
import { TooltipProvider } from '../src/components/ui/tooltip';
4+
25
import '../tailwind.css';
36

47
const preview: Preview = {
@@ -10,6 +13,9 @@ const preview: Preview = {
1013
},
1114
},
1215
},
16+
decorators: [
17+
(Story) => createElement(TooltipProvider, null, createElement(Story)),
18+
],
1319
};
1420

1521
export default preview;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import type { Meta, StoryObj } from '@storybook/react-webpack5';
2+
3+
import { fn } from 'storybook/test';
4+
5+
import { AvatarUpload } from '@/components/avatar-upload';
6+
7+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
8+
const meta = {
9+
title: 'Example/AvatarUpload',
10+
component: AvatarUpload,
11+
parameters: {
12+
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
13+
layout: 'centered',
14+
docs: {
15+
description: {
16+
component: `
17+
## AvatarUpload Component
18+
19+
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.
20+
21+
### Import Path
22+
\`\`\`typescript
23+
import { AvatarUpload } from '@/components/avatar-upload';
24+
\`\`\`
25+
26+
### Basic Usage
27+
\`\`\`tsx
28+
import { useState } from 'react';
29+
import { AvatarUpload } from '@/components/avatar-upload';
30+
31+
function MyComponent() {
32+
const [avatarValue, setAvatarValue] = useState('');
33+
34+
return (
35+
<AvatarUpload
36+
value={avatarValue}
37+
onChange={(base64String) => setAvatarValue(base64String)}
38+
/>
39+
);
40+
}
41+
\`\`\`
42+
43+
### Features
44+
- Supports image upload with drag & drop
45+
- Image preview with hover effects
46+
- Remove button to clear selected image
47+
- Base64 encoding for easy handling
48+
- Accepts common image formats (jpg, jpeg, png, webp, bmp)
49+
`,
50+
},
51+
},
52+
},
53+
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
54+
tags: ['autodocs'],
55+
// More on argTypes: https://storybook.js.org/docs/api/argtypes
56+
argTypes: {
57+
value: {
58+
description: 'The current avatar value as base64 string',
59+
control: { type: 'text' },
60+
type: { name: 'string', required: false },
61+
},
62+
onChange: {
63+
description: 'Callback function called when avatar changes',
64+
control: false,
65+
type: { name: 'function', required: false },
66+
},
67+
},
68+
// 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
69+
args: { onChange: fn() },
70+
} satisfies Meta<typeof AvatarUpload>;
71+
72+
export default meta;
73+
type Story = StoryObj<typeof meta>;
74+
75+
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
76+
export const EmptyState: Story = {
77+
args: {
78+
value: '',
79+
},
80+
parameters: {
81+
docs: {
82+
description: {
83+
story: `
84+
### Empty State
85+
86+
Shows the upload area when no avatar is selected.
87+
88+
\`\`\`tsx
89+
<AvatarUpload
90+
value=""
91+
onChange={(base64String) => console.log('Avatar uploaded:', base64String)}
92+
/>
93+
\`\`\`
94+
`,
95+
},
96+
},
97+
},
98+
tags: ['!dev'],
99+
};
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import type { Meta, StoryObj } from '@storybook/react-webpack5';
2+
3+
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
4+
5+
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
6+
const meta = {
7+
title: 'Example/RAGFlowAvatar',
8+
component: RAGFlowAvatar,
9+
parameters: {
10+
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
11+
layout: 'centered',
12+
docs: {
13+
description: {
14+
component: `
15+
## RAGFlowAvatar Component
16+
17+
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.
18+
19+
### Import Path
20+
\`\`\`typescript
21+
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
22+
\`\`\`
23+
24+
### Basic Usage
25+
\`\`\`tsx
26+
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
27+
28+
function MyComponent() {
29+
return (
30+
<RAGFlowAvatar
31+
name="John Doe"
32+
avatar="https://example.com/avatar.jpg"
33+
isPerson={true}
34+
/>
35+
);
36+
}
37+
\`\`\`
38+
39+
### Features
40+
- Displays user avatar images when available
41+
- Generates colorful gradient fallbacks with initials
42+
- Supports both person (circular) and non-person (rounded) styles
43+
- Automatic font size calculation based on container size
44+
- Color generation based on name for consistent appearance
45+
- Responsive design with resize observer
46+
`,
47+
},
48+
},
49+
},
50+
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
51+
tags: ['autodocs'],
52+
// More on argTypes: https://storybook.js.org/docs/api/argtypes
53+
argTypes: {
54+
name: {
55+
description:
56+
'The name to display initials for when no avatar is available',
57+
control: { type: 'text' },
58+
type: { name: 'string', required: false },
59+
},
60+
avatar: {
61+
description: 'The URL of the avatar image',
62+
control: { type: 'text' },
63+
type: { name: 'string', required: false },
64+
},
65+
isPerson: {
66+
description: 'Whether this avatar represents a person (affects styling)',
67+
control: { type: 'boolean' },
68+
type: { name: 'boolean', required: false },
69+
defaultValue: false,
70+
},
71+
className: {
72+
description: 'Additional CSS classes to apply',
73+
control: { type: 'text' },
74+
type: { name: 'string', required: false },
75+
},
76+
},
77+
args: {
78+
name: 'John Doe',
79+
isPerson: false,
80+
},
81+
} satisfies Meta<typeof RAGFlowAvatar>;
82+
83+
export default meta;
84+
type Story = StoryObj<typeof meta>;
85+
86+
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
87+
export const WithInitials: Story = {
88+
args: {
89+
name: 'John Doe',
90+
isPerson: false,
91+
},
92+
parameters: {
93+
docs: {
94+
description: {
95+
story: `
96+
### With Initials Only
97+
98+
Shows the avatar component with only a name, displaying generated initials with a gradient background.
99+
100+
\`\`\`tsx
101+
<RAGFlowAvatar
102+
name="John Doe"
103+
isPerson={false}
104+
/>
105+
\`\`\`
106+
`,
107+
},
108+
},
109+
},
110+
tags: ['!dev'],
111+
};
112+
113+
export const WithAvatar: Story = {
114+
args: {
115+
name: 'Jane Smith',
116+
avatar:
117+
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMzIiIGZpbGw9IiM0RjZERUUiLz4KPGNpcmNsZSBjeD0iMzIiIGN5PSIyNCIgcj0iOCIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTQ4IDQ4QzQ4IDQxLjM3MyA0MS45NDA2IDM2IDM0LjUgMzZIMjkuNUMyMi4wNTk0IDM2IDE2IDQxLjM3MyAxNiA0OCIgZmlsbD0id2hpdGUiLz4KPC9zdmc+',
118+
isPerson: true,
119+
},
120+
parameters: {
121+
docs: {
122+
description: {
123+
story: `
124+
### With Avatar Image
125+
126+
Shows the avatar component with an actual image. When isPerson is true, the avatar will be circular.
127+
128+
\`\`\`tsx
129+
<RAGFlowAvatar
130+
name="Jane Smith"
131+
avatar="https://example.com/avatar.jpg"
132+
isPerson={true}
133+
/>
134+
\`\`\`
135+
`,
136+
},
137+
},
138+
},
139+
tags: ['!dev'],
140+
};
141+
142+
export const PersonStyle: Story = {
143+
args: {
144+
name: 'Alice Johnson',
145+
isPerson: true,
146+
},
147+
parameters: {
148+
docs: {
149+
description: {
150+
story: `
151+
### Person Style (Circular)
152+
153+
Shows the avatar component with isPerson set to true, which makes it circular.
154+
155+
\`\`\`tsx
156+
<RAGFlowAvatar
157+
name="Alice Johnson"
158+
isPerson={true}
159+
/>
160+
\`\`\`
161+
`,
162+
},
163+
},
164+
},
165+
tags: ['!dev'],
166+
};
167+
168+
export const NonPersonStyle: Story = {
169+
args: {
170+
name: 'Bot Assistant',
171+
isPerson: false,
172+
},
173+
parameters: {
174+
docs: {
175+
description: {
176+
story: `
177+
### Non-Person Style (Rounded Rectangle)
178+
179+
Shows the avatar component with isPerson set to false, which makes it a rounded rectangle.
180+
181+
\`\`\`tsx
182+
<RAGFlowAvatar
183+
name="Bot Assistant"
184+
isPerson={false}
185+
/>
186+
\`\`\`
187+
`,
188+
},
189+
},
190+
},
191+
tags: ['!dev'],
192+
};

0 commit comments

Comments
 (0)