mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2025-11-29 19:08:33 +08:00
## Summary Reviewed and refactored all Storybook stories to use shared utilities, eliminating ~200 lines of duplicate code while ensuring stories use current theme, config, and styles consistently. ## Changes ### New Shared Utilities (.storybook/) - **argTypes.ts**: Shared argTypes definitions (hostname, subscription, etc.) - **decorators.tsx**: Reusable decorators (context providers, hostname mocking) - **mocks.ts**: Shared mock context values (AFConfig, AppContext) ### Refactored Story Files - HomePageSetting.stories.tsx: Now uses shared utilities - UpgradeBanner.stories.tsx: Reduced from ~195 to ~80 lines - UpgradePlan.stories.tsx: Reduced from ~180 to ~95 lines - TextColor.stories.tsx: Uses shared argTypes - RecordNotFound.stories.tsx: Reduced from ~235 to ~170 lines ### Configuration Updates - **main.ts**: Added MUI optimizeDeps for proper theme support, removed deprecated buildStoriesJson - **GUIDE.md**: Comprehensive documentation with examples and best practices - **tsconfig.web.json**: Explicitly exclude .storybook/ from production builds ### Lint Fixes & Improvements - **ApproveRequestPage.tsx**: Added missing blank line (lint fix) - **subscription.ts**: Fixed type casting to avoid @typescript-eslint/no-explicit-any - **AppTheme.tsx**: Changed to named imports (better practice) ## Benefits - ✅ Zero code duplication across stories - ✅ Consistent theme, config, and styles across all stories - ✅ Better maintainability (change once, apply everywhere) - ✅ Improved type safety with shared utilities - ✅ Comprehensive documentation for future story development - ✅ Storybook files guaranteed excluded from production builds ## Testing - All linting passes (pnpm run lint) - Storybook configuration verified to not be included in production builds - Multiple layers of protection ensure isolation from main application Co-Authored-By: Claude <noreply@anthropic.com>
118 lines
2.8 KiB
TypeScript
118 lines
2.8 KiB
TypeScript
/**
|
|
* Shared mock values for Storybook stories
|
|
*
|
|
* This file contains common mock context values to avoid duplication across story files.
|
|
* Import and use these mocks in your stories instead of creating new ones.
|
|
*/
|
|
|
|
import { SubscriptionInterval, SubscriptionPlan } from '@/application/types';
|
|
|
|
/**
|
|
* Mock AFConfig context value
|
|
* Used by components that need authentication and service configuration
|
|
*/
|
|
export const mockAFConfigValue = {
|
|
service: {
|
|
getSubscriptionLink: async () => 'https://example.com/subscribe',
|
|
},
|
|
isAuthenticated: true,
|
|
currentUser: {
|
|
email: 'storybook@example.com',
|
|
name: 'Storybook User',
|
|
uid: 'storybook-uid',
|
|
avatar: null,
|
|
uuid: 'storybook-uuid',
|
|
latestWorkspaceId: 'storybook-workspace-id',
|
|
},
|
|
updateCurrentUser: async () => {
|
|
// Mock implementation
|
|
},
|
|
openLoginModal: () => {
|
|
// Mock implementation
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Minimal mock AFConfig without service
|
|
* Use this for components that don't need service functionality
|
|
*/
|
|
export const mockAFConfigValueMinimal = {
|
|
service: undefined,
|
|
isAuthenticated: true,
|
|
currentUser: {
|
|
email: 'storybook@example.com',
|
|
name: 'Storybook User',
|
|
uid: 'storybook-uid',
|
|
avatar: null,
|
|
uuid: 'storybook-uuid',
|
|
latestWorkspaceId: 'storybook-workspace-id',
|
|
},
|
|
updateCurrentUser: async () => {
|
|
// Mock implementation
|
|
},
|
|
openLoginModal: () => {
|
|
// Mock implementation
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Mock App context value
|
|
* Used by components that need workspace and app state
|
|
*/
|
|
export const mockAppContextValue = {
|
|
userWorkspaceInfo: {
|
|
selectedWorkspace: {
|
|
id: 'storybook-workspace-id',
|
|
name: 'Storybook Workspace',
|
|
owner: {
|
|
uid: 'storybook-uid',
|
|
},
|
|
},
|
|
workspaces: [
|
|
{
|
|
id: 'storybook-workspace-id',
|
|
name: 'Storybook Workspace',
|
|
owner: {
|
|
uid: 'storybook-uid',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
currentWorkspaceId: 'storybook-workspace-id',
|
|
outline: [],
|
|
rendered: true,
|
|
toView: async () => {},
|
|
loadViewMeta: async () => {
|
|
throw new Error('Not implemented in story');
|
|
},
|
|
loadView: async () => {
|
|
throw new Error('Not implemented in story');
|
|
},
|
|
createRowDoc: async () => {
|
|
throw new Error('Not implemented in story');
|
|
},
|
|
appendBreadcrumb: () => {},
|
|
onRendered: () => {},
|
|
updatePage: async () => {},
|
|
addPage: async () => 'test-page-id',
|
|
deletePage: async () => {},
|
|
openPageModal: () => {},
|
|
loadViews: async () => [],
|
|
setWordCount: () => {},
|
|
uploadFile: async () => {
|
|
throw new Error('Not implemented in story');
|
|
},
|
|
eventEmitter: undefined,
|
|
awarenessMap: {},
|
|
getSubscriptions: async () => {
|
|
return [
|
|
{
|
|
plan: SubscriptionPlan.Free,
|
|
currency: 'USD',
|
|
recurring_interval: SubscriptionInterval.Month,
|
|
price_cents: 0,
|
|
},
|
|
];
|
|
},
|
|
};
|