|
| 1 | +import type { Meta, StoryObj } from '@storybook/react' |
| 2 | +import { useState } from 'react' |
| 3 | +import { DocumentEdit } from './document-edit' |
| 4 | +import type { KnowledgeDocument } from './types' |
| 5 | + |
| 6 | +const meta: Meta<typeof DocumentEdit> = { |
| 7 | + title: 'Digital Colleagues/DocumentEdit', |
| 8 | + component: DocumentEdit, |
| 9 | + parameters: { |
| 10 | + layout: 'fullscreen', |
| 11 | + docs: { |
| 12 | + description: { |
| 13 | + component: 'A document editing interface that allows users to modify knowledge document properties and content.' |
| 14 | + } |
| 15 | + } |
| 16 | + }, |
| 17 | + tags: ['autodocs'], |
| 18 | + argTypes: { |
| 19 | + document: { |
| 20 | + control: false, |
| 21 | + description: 'The knowledge document to edit' |
| 22 | + }, |
| 23 | + onSave: { |
| 24 | + action: 'document-saved', |
| 25 | + description: 'Callback fired when the document is saved' |
| 26 | + }, |
| 27 | + onCancel: { |
| 28 | + action: 'edit-cancelled', |
| 29 | + description: 'Callback fired when editing is cancelled' |
| 30 | + } |
| 31 | + }, |
| 32 | +} |
| 33 | + |
| 34 | +export default meta |
| 35 | +type Story = StoryObj<typeof meta> |
| 36 | + |
| 37 | +// Sample documents for stories |
| 38 | +const sampleMarkdownDocument: KnowledgeDocument = { |
| 39 | + id: '1', |
| 40 | + title: 'React Development Best Practices', |
| 41 | + description: 'Comprehensive guide to React development patterns and practices', |
| 42 | + format: 'markdown', |
| 43 | + metadata: { |
| 44 | + category: 'Development', |
| 45 | + difficulty: 'Intermediate', |
| 46 | + author: 'Dev Team', |
| 47 | + lastReviewed: '2024-06-01' |
| 48 | + }, |
| 49 | + tags: ['react', 'javascript', 'frontend'], |
| 50 | + createdAt: new Date('2024-01-15'), |
| 51 | + updatedAt: new Date('2024-06-20'), |
| 52 | + content: `# React Development Best Practices |
| 53 | +
|
| 54 | +This comprehensive guide covers the essential patterns and practices for React development. |
| 55 | +
|
| 56 | +## Introduction |
| 57 | +
|
| 58 | +React is a powerful library for building user interfaces. Following best practices ensures your applications are maintainable, performant, and scalable. |
| 59 | +
|
| 60 | +### Key Principles |
| 61 | +
|
| 62 | +1. **Component Composition** - Build small, reusable components |
| 63 | +2. **State Management** - Keep state as local as possible |
| 64 | +3. **Performance** - Use React.memo and useMemo when appropriate |
| 65 | +4. **Testing** - Write comprehensive tests for your components |
| 66 | +
|
| 67 | +## Code Examples |
| 68 | +
|
| 69 | +Here's an example of a well-structured React component: |
| 70 | +
|
| 71 | +\`\`\`jsx |
| 72 | +import React, { useState, useCallback } from 'react'; |
| 73 | +
|
| 74 | +function UserProfile({ userId }) { |
| 75 | + const [user, setUser] = useState(null); |
| 76 | + const [loading, setLoading] = useState(false); |
| 77 | +
|
| 78 | + const fetchUser = useCallback(async () => { |
| 79 | + setLoading(true); |
| 80 | + try { |
| 81 | + const response = await fetch(\`/api/users/\${userId}\`); |
| 82 | + const userData = await response.json(); |
| 83 | + setUser(userData); |
| 84 | + } catch (error) { |
| 85 | + console.error('Failed to fetch user:', error); |
| 86 | + } finally { |
| 87 | + setLoading(false); |
| 88 | + } |
| 89 | + }, [userId]); |
| 90 | +
|
| 91 | + return ( |
| 92 | + <div> |
| 93 | + {loading && <p>Loading...</p>} |
| 94 | + {user && ( |
| 95 | + <div> |
| 96 | + <h2>{user.name}</h2> |
| 97 | + <p>{user.email}</p> |
| 98 | + </div> |
| 99 | + )} |
| 100 | + </div> |
| 101 | + ); |
| 102 | +} |
| 103 | +
|
| 104 | +export default UserProfile; |
| 105 | +\`\`\` |
| 106 | +
|
| 107 | +## Best Practices Checklist |
| 108 | +
|
| 109 | +- [ ] Use functional components with hooks |
| 110 | +- [ ] Implement proper error boundaries |
| 111 | +- [ ] Optimize renders with React.memo |
| 112 | +- [ ] Use TypeScript for better type safety |
| 113 | +- [ ] Follow consistent naming conventions |
| 114 | +- [ ] Write unit and integration tests |
| 115 | +
|
| 116 | +## Conclusion |
| 117 | +
|
| 118 | +Following these best practices will help you build robust React applications that are easy to maintain and scale.` |
| 119 | +} |
| 120 | + |
| 121 | +const sampleRichTextDocument: KnowledgeDocument = { |
| 122 | + id: '2', |
| 123 | + title: 'Team Communication Guidelines', |
| 124 | + description: 'Essential guidelines for effective team communication', |
| 125 | + format: 'richtext', |
| 126 | + metadata: { |
| 127 | + category: 'Management', |
| 128 | + difficulty: 'Beginner', |
| 129 | + department: 'HR', |
| 130 | + priority: 'High' |
| 131 | + }, |
| 132 | + tags: ['communication', 'team', 'guidelines'], |
| 133 | + createdAt: new Date('2024-02-10'), |
| 134 | + updatedAt: new Date('2024-05-15'), |
| 135 | + content: `Team Communication Guidelines |
| 136 | +
|
| 137 | +Effective communication is crucial for team success. These guidelines help ensure clear, respectful, and productive interactions. |
| 138 | +
|
| 139 | +Core Principles: |
| 140 | +• Be clear and concise in your messaging |
| 141 | +• Listen actively and ask clarifying questions |
| 142 | +• Respect different communication styles and preferences |
| 143 | +• Use appropriate channels for different types of communication |
| 144 | +
|
| 145 | +Meeting Guidelines: |
| 146 | +• Start and end on time |
| 147 | +• Come prepared with agenda items |
| 148 | +• Encourage participation from all team members |
| 149 | +• Follow up with action items and next steps |
| 150 | +
|
| 151 | +Digital Communication: |
| 152 | +• Use @mentions when you need someone's attention |
| 153 | +• Keep messages focused and actionable |
| 154 | +• Use threads to keep conversations organized |
| 155 | +• Respond within 24 hours during business days |
| 156 | +
|
| 157 | +Remember: Good communication builds trust and improves team productivity.` |
| 158 | +} |
| 159 | + |
| 160 | +const emptyDocument: KnowledgeDocument = { |
| 161 | + id: '3', |
| 162 | + title: '', |
| 163 | + description: '', |
| 164 | + format: 'markdown', |
| 165 | + tags: [], |
| 166 | + createdAt: new Date(), |
| 167 | + content: '' |
| 168 | +} |
| 169 | + |
| 170 | +const documentWithoutTags: KnowledgeDocument = { |
| 171 | + id: '4', |
| 172 | + title: 'Simple Document', |
| 173 | + description: 'A document without tags for testing', |
| 174 | + format: 'mdx', |
| 175 | + metadata: { category: 'Testing' }, |
| 176 | + createdAt: new Date('2024-01-01'), |
| 177 | + content: 'Simple content for testing purposes.' |
| 178 | +} |
| 179 | + |
| 180 | +// Wrapper component to handle state management |
| 181 | +const DocumentEditWrapper = (args: any) => { |
| 182 | + const [currentDocument, setCurrentDocument] = useState<KnowledgeDocument>(args.document) |
| 183 | + |
| 184 | + const handleSave = (savedDocument: KnowledgeDocument) => { |
| 185 | + setCurrentDocument(savedDocument) |
| 186 | + args.onSave?.(savedDocument) |
| 187 | + } |
| 188 | + |
| 189 | + const handleCancel = () => { |
| 190 | + // Reset to original document |
| 191 | + setCurrentDocument(args.document) |
| 192 | + args.onCancel?.() |
| 193 | + } |
| 194 | + |
| 195 | + return ( |
| 196 | + <div className="h-screen bg-background"> |
| 197 | + <DocumentEdit |
| 198 | + document={currentDocument} |
| 199 | + onSave={handleSave} |
| 200 | + onCancel={handleCancel} |
| 201 | + /> |
| 202 | + </div> |
| 203 | + ) |
| 204 | +} |
| 205 | + |
| 206 | +export const EditMarkdownDocument: Story = { |
| 207 | + render: DocumentEditWrapper, |
| 208 | + args: { |
| 209 | + document: sampleMarkdownDocument |
| 210 | + }, |
| 211 | + parameters: { |
| 212 | + docs: { |
| 213 | + description: { |
| 214 | + story: 'Document editor for a markdown document with comprehensive content and metadata.' |
| 215 | + } |
| 216 | + } |
| 217 | + } |
| 218 | +} |
| 219 | + |
| 220 | +export const EditRichTextDocument: Story = { |
| 221 | + render: DocumentEditWrapper, |
| 222 | + args: { |
| 223 | + document: sampleRichTextDocument |
| 224 | + }, |
| 225 | + parameters: { |
| 226 | + docs: { |
| 227 | + description: { |
| 228 | + story: 'Document editor for a rich text document with formatted content.' |
| 229 | + } |
| 230 | + } |
| 231 | + } |
| 232 | +} |
| 233 | + |
| 234 | +export const EditEmptyDocument: Story = { |
| 235 | + render: DocumentEditWrapper, |
| 236 | + args: { |
| 237 | + document: emptyDocument |
| 238 | + }, |
| 239 | + parameters: { |
| 240 | + docs: { |
| 241 | + description: { |
| 242 | + story: 'Document editor starting with an empty document to test creation workflow.' |
| 243 | + } |
| 244 | + } |
| 245 | + } |
| 246 | +} |
| 247 | + |
| 248 | +export const EditDocumentWithoutTags: Story = { |
| 249 | + render: DocumentEditWrapper, |
| 250 | + args: { |
| 251 | + document: documentWithoutTags |
| 252 | + }, |
| 253 | + parameters: { |
| 254 | + docs: { |
| 255 | + description: { |
| 256 | + story: 'Document editor for a document without tags to test the tags input field.' |
| 257 | + } |
| 258 | + } |
| 259 | + } |
| 260 | +} |
| 261 | + |
| 262 | +export const EditLongContent: Story = { |
| 263 | + render: DocumentEditWrapper, |
| 264 | + args: { |
| 265 | + document: { |
| 266 | + ...sampleMarkdownDocument, |
| 267 | + content: sampleMarkdownDocument.content + '\n\n' + |
| 268 | + 'Additional content section with more details. '.repeat(20) + '\n\n' + |
| 269 | + sampleMarkdownDocument.content + '\n\n' + |
| 270 | + 'Even more content to test the textarea scrolling behavior. '.repeat(30) + '\n\n' + |
| 271 | + '## Additional Section\n\nMore content here to make it really long and test the editing experience with substantial content.' |
| 272 | + } |
| 273 | + }, |
| 274 | + parameters: { |
| 275 | + docs: { |
| 276 | + description: { |
| 277 | + story: 'Document editor with very long content to test textarea behavior and scrolling.' |
| 278 | + } |
| 279 | + } |
| 280 | + } |
| 281 | +} |
| 282 | + |
| 283 | +export const EditMinimalDocument: Story = { |
| 284 | + render: DocumentEditWrapper, |
| 285 | + args: { |
| 286 | + document: { |
| 287 | + id: '5', |
| 288 | + title: 'Minimal Doc', |
| 289 | + format: 'markdown' as const, |
| 290 | + createdAt: new Date(), |
| 291 | + content: 'Just basic content.' |
| 292 | + } |
| 293 | + }, |
| 294 | + parameters: { |
| 295 | + docs: { |
| 296 | + description: { |
| 297 | + story: 'Document editor with minimal fields to test the layout with fewer properties.' |
| 298 | + } |
| 299 | + } |
| 300 | + } |
| 301 | +} |
| 302 | + |
| 303 | +export const EditMdxDocument: Story = { |
| 304 | + render: DocumentEditWrapper, |
| 305 | + args: { |
| 306 | + document: { |
| 307 | + id: '6', |
| 308 | + title: 'MDX Component Guide', |
| 309 | + description: 'Interactive guide for MDX components', |
| 310 | + format: 'mdx' as const, |
| 311 | + metadata: { |
| 312 | + category: 'Documentation', |
| 313 | + interactive: true, |
| 314 | + complexity: 'Advanced' |
| 315 | + }, |
| 316 | + tags: ['mdx', 'components', 'react', 'documentation'], |
| 317 | + createdAt: new Date('2024-03-01'), |
| 318 | + updatedAt: new Date('2024-06-15'), |
| 319 | + content: `# MDX Component Guide |
| 320 | +
|
| 321 | +This is an interactive MDX document that combines markdown with React components. |
| 322 | +
|
| 323 | +## Basic Usage |
| 324 | +
|
| 325 | +\`\`\`mdx |
| 326 | +import { Button } from './components/Button' |
| 327 | +
|
| 328 | +# My Document |
| 329 | +
|
| 330 | +Here's a custom component: |
| 331 | +
|
| 332 | +<Button variant="primary">Click me!</Button> |
| 333 | +\`\`\` |
| 334 | +
|
| 335 | +## Advanced Features |
| 336 | +
|
| 337 | +MDX allows you to: |
| 338 | +- Use React components directly in markdown |
| 339 | +- Pass props to components |
| 340 | +- Create interactive documentation |
| 341 | +- Combine content with functionality |
| 342 | +
|
| 343 | +<CustomComponent prop="value" /> |
| 344 | +
|
| 345 | +## Best Practices |
| 346 | +
|
| 347 | +1. Keep components simple and focused |
| 348 | +2. Document component props clearly |
| 349 | +3. Test interactive elements thoroughly |
| 350 | +4. Maintain good performance` |
| 351 | + } |
| 352 | + }, |
| 353 | + parameters: { |
| 354 | + docs: { |
| 355 | + description: { |
| 356 | + story: 'Document editor for an MDX document with React components and interactive content.' |
| 357 | + } |
| 358 | + } |
| 359 | + } |
| 360 | +} |
0 commit comments