chore: improve storybook (#27111)

This commit is contained in:
非法操作 2025-10-20 10:17:17 +08:00 committed by GitHub
parent 7e9be4d3d9
commit dc1a380888
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 974 additions and 762 deletions

View File

@ -1,19 +1,29 @@
import type { StorybookConfig } from '@storybook/nextjs'
const config: StorybookConfig = {
// stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
stories: ['../app/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-onboarding',
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-docs',
'@chromatic-com/storybook',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/nextjs',
options: {},
options: {
builder: {
useSWC: true,
lazyCompilation: false,
},
nextConfigPath: undefined,
},
},
staticDirs: ['../public'],
core: {
disableWhatsNewNotifications: true,
},
docs: {
defaultName: 'Documentation',
},
}
export default config

View File

@ -1,12 +1,21 @@
import React from 'react'
import type { Preview } from '@storybook/react'
import { withThemeByDataAttribute } from '@storybook/addon-themes'
import I18nServer from '../app/components/i18n-server'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import I18N from '../app/components/i18n'
import { ToastProvider } from '../app/components/base/toast'
import '../app/styles/globals.css'
import '../app/styles/markdown.scss'
import './storybook.css'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
},
},
})
export const decorators = [
withThemeByDataAttribute({
themes: {
@ -17,9 +26,15 @@ export const decorators = [
attributeName: 'data-theme',
}),
(Story) => {
return <I18nServer>
<Story />
</I18nServer>
return (
<QueryClientProvider client={queryClient}>
<I18N locale="en-US">
<ToastProvider>
<Story />
</ToastProvider>
</I18N>
</QueryClientProvider>
)
},
]
@ -31,7 +46,11 @@ const preview: Preview = {
date: /Date$/i,
},
},
docs: {
toc: true,
},
},
tags: ['autodocs'],
}
export default preview

View File

@ -1,5 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react'
import { fn } from '@storybook/test'
import type { Meta, StoryObj } from '@storybook/nextjs'
import { RocketLaunchIcon } from '@heroicons/react/20/solid'
import { Button } from '.'
@ -20,8 +19,7 @@ const meta = {
},
args: {
variant: 'ghost',
onClick: fn(),
children: 'adsf',
children: 'Button',
},
} satisfies Meta<typeof Button>
@ -33,6 +31,9 @@ export const Default: Story = {
variant: 'primary',
loading: false,
children: 'Primary Button',
styleCss: {},
spinnerClassName: '',
destructive: false,
},
}

View File

@ -1,4 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react'
import type { Meta, StoryObj } from '@storybook/nextjs'
import type { ChatItem } from '../../types'
import { mockedWorkflowProcess } from './__mocks__/workflowProcess'

View File

@ -1,4 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react'
import type { Meta, StoryObj } from '@storybook/nextjs'
import type { ChatItem } from '../types'
import Question from './question'

View File

@ -0,0 +1,199 @@
import type { Meta, StoryObj } from '@storybook/nextjs'
import { useState } from 'react'
import Confirm from '.'
import Button from '../button'
const meta = {
title: 'Base/Confirm',
component: Confirm,
parameters: {
layout: 'centered',
docs: {
description: {
component: 'Confirmation dialog component that supports warning and info types, with customizable button text and behavior.',
},
},
},
tags: ['autodocs'],
argTypes: {
type: {
control: 'select',
options: ['info', 'warning'],
description: 'Dialog type',
},
isShow: {
control: 'boolean',
description: 'Whether to show the dialog',
},
title: {
control: 'text',
description: 'Dialog title',
},
content: {
control: 'text',
description: 'Dialog content',
},
confirmText: {
control: 'text',
description: 'Confirm button text',
},
cancelText: {
control: 'text',
description: 'Cancel button text',
},
isLoading: {
control: 'boolean',
description: 'Confirm button loading state',
},
isDisabled: {
control: 'boolean',
description: 'Confirm button disabled state',
},
showConfirm: {
control: 'boolean',
description: 'Whether to show confirm button',
},
showCancel: {
control: 'boolean',
description: 'Whether to show cancel button',
},
maskClosable: {
control: 'boolean',
description: 'Whether clicking mask closes dialog',
},
},
} satisfies Meta<typeof Confirm>
export default meta
type Story = StoryObj<typeof meta>
// Interactive demo wrapper
const ConfirmDemo = (args: any) => {
const [isShow, setIsShow] = useState(false)
return (
<div>
<Button variant="primary" onClick={() => setIsShow(true)}>
Open Dialog
</Button>
<Confirm
{...args}
isShow={isShow}
onConfirm={() => {
console.log('✅ User clicked confirm')
setIsShow(false)
}}
onCancel={() => {
console.log('❌ User clicked cancel')
setIsShow(false)
}}
/>
</div>
)
}
// Basic warning dialog - Delete action
export const WarningDialog: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'warning',
title: 'Delete Confirmation',
content: 'Are you sure you want to delete this project? This action cannot be undone.',
},
}
// Info dialog
export const InfoDialog: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'info',
title: 'Notice',
content: 'Your changes have been saved. Do you want to proceed to the next step?',
},
}
// Custom button text
export const CustomButtonText: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'warning',
title: 'Exit Editor',
content: 'You have unsaved changes. Are you sure you want to exit?',
confirmText: 'Discard Changes',
cancelText: 'Continue Editing',
},
}
// Loading state
export const LoadingState: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'warning',
title: 'Deleting...',
content: 'Please wait while we delete the file...',
isLoading: true,
},
}
// Disabled state
export const DisabledState: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'info',
title: 'Verification Required',
content: 'Please complete email verification before proceeding.',
isDisabled: true,
},
}
// Alert style - Confirm button only
export const AlertStyle: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'info',
title: 'Success',
content: 'Your settings have been updated!',
showCancel: false,
confirmText: 'Got it',
},
}
// Dangerous action - Long content
export const DangerousAction: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'warning',
title: 'Permanently Delete Account',
content: 'This action will permanently delete your account and all associated data, including: all projects and files, collaboration history, and personal settings. This action cannot be reversed!',
confirmText: 'Delete My Account',
cancelText: 'Keep My Account',
},
}
// Non-closable mask
export const NotMaskClosable: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'warning',
title: 'Important Action',
content: 'This action requires your explicit choice. Clicking outside will not close this dialog.',
maskClosable: false,
},
}
// Full feature demo - Playground
export const Playground: Story = {
render: args => <ConfirmDemo {...args} />,
args: {
type: 'warning',
title: 'This is a title',
content: 'This is the dialog content text...',
confirmText: undefined,
cancelText: undefined,
isLoading: false,
isDisabled: false,
showConfirm: true,
showCancel: true,
maskClosable: true,
},
}

View File

@ -142,7 +142,7 @@
"devDependencies": {
"@antfu/eslint-config": "^5.0.0",
"@babel/core": "^7.28.3",
"@chromatic-com/storybook": "^3.1.0",
"@chromatic-com/storybook": "^4.1.1",
"@eslint-react/eslint-plugin": "^1.15.0",
"@happy-dom/jest-environment": "^20.0.2",
"@mdx-js/loader": "^3.1.0",
@ -151,14 +151,12 @@
"@next/eslint-plugin-next": "15.5.4",
"@next/mdx": "15.5.4",
"@rgrove/parse-xml": "^4.1.0",
"@storybook/addon-essentials": "8.5.0",
"@storybook/addon-interactions": "8.5.0",
"@storybook/addon-links": "8.5.0",
"@storybook/addon-onboarding": "8.5.0",
"@storybook/addon-themes": "8.5.0",
"@storybook/nextjs": "8.5.0",
"@storybook/react": "8.5.0",
"@storybook/test": "8.5.0",
"@storybook/addon-docs": "9.1.13",
"@storybook/addon-links": "9.1.13",
"@storybook/addon-onboarding": "9.1.13",
"@storybook/addon-themes": "9.1.13",
"@storybook/nextjs": "9.1.13",
"@storybook/react": "9.1.13",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.0.1",
@ -186,7 +184,7 @@
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.19",
"eslint-plugin-sonarjs": "^3.0.2",
"eslint-plugin-storybook": "^9.0.7",
"eslint-plugin-storybook": "^9.1.13",
"eslint-plugin-tailwindcss": "^3.18.0",
"globals": "^15.11.0",
"husky": "^9.1.6",
@ -197,7 +195,7 @@
"magicast": "^0.3.4",
"postcss": "^8.4.47",
"sass": "^1.92.1",
"storybook": "8.5.0",
"storybook": "9.1.13",
"tailwindcss": "^3.4.14",
"typescript": "^5.8.3",
"uglify-js": "^3.19.3"
@ -243,7 +241,8 @@
"object.fromentries": "npm:@nolyfill/object.fromentries@^1",
"object.groupby": "npm:@nolyfill/object.groupby@^1",
"object.values": "npm:@nolyfill/object.values@^1",
"safe-buffer": "npm:@nolyfill/safe-buffer@^1",
"safe-buffer": "^5.2.1",
"@nolyfill/safe-buffer": "npm:safe-buffer@^5.2.1",
"safe-regex-test": "npm:@nolyfill/safe-regex-test@^1",
"safer-buffer": "npm:@nolyfill/safer-buffer@^1",
"side-channel": "npm:@nolyfill/side-channel@^1",

File diff suppressed because it is too large Load Diff