Storybook 7.6中Button组件动态控制argTypes选项的实现咨询
解决方案:Storybook 7.6 动态控制 argTypes 选项
步骤1:定义外观与显示类型的映射关系
先创建一个映射对象,明确每种appearance对应的displayType可选值:
// 根据实际需求调整映射关系 const appearanceDisplayTypeMap: Record<string, string[]> = { primary: ['fill'], secondary: ['fill', 'outline'], danger: ['outline', 'text'], success: ['fill', 'outline'], inverse: ['fill', 'text'], transparent: ['text'], };
步骤2:更新 Meta 配置,添加动态控制逻辑
利用 Storybook 的useArgs钩子和装饰器,实现appearance切换时自动更新displayType的可选选项,同时自动重置无效值:
import { Meta, FC } from '@storybook/react'; import { forwardRef } from 'react'; import { useArgs } from '@storybook/preview-api'; import Button from './Button'; // 替换为你的Button组件路径 import { IButtonProps, args, propCategory } from './your-types'; // 替换为你的类型定义路径 const meta: Meta<typeof forwardRef<HTMLButtonElement, IButtonProps>> = { title: 'Atoms/Button', component: Button, argTypes: { size: args({ control: 'select', ...propCategory.appearance }), appearance: args({ control: 'select', ...propCategory.appearance }), text: args({ control: 'text', ...propCategory.content }), displayType: args({ control: 'select', ...propCategory.appearance }), fullWidth: args({ control: 'boolean', ...propCategory.appearance }), iconAfter: args({ control: 'boolean', ...propCategory.appearance }), className: args({ control: 'false', ...propCategory.appearance }), disabled: args({ control: 'boolean', ...propCategory.states }), isLoading: args({ control: 'boolean', ...propCategory.states }), Icon: args({ control: 'false', ...propCategory.content }), name: args({ control: 'false', ...propCategory.functionality }), onClick: args({ control: 'false', ...propCategory.action }) }, args: { text: 'Button', appearance: 'primary', size: 'large', displayType: 'fill', isLoading: false }, decorators: [ (Story) => { const [currentArgs, updateArgs] = useArgs(); // 获取当前外观对应的允许显示类型 const allowedDisplayTypes = appearanceDisplayTypeMap[currentArgs.appearance] || []; // 若当前选中的displayType无效,自动重置为第一个有效选项 if (allowedDisplayTypes.length > 0 && !allowedDisplayTypes.includes(currentArgs.displayType)) { updateArgs({ displayType: allowedDisplayTypes[0] }); } // 动态更新displayType的可选选项 const updatedArgTypes = { ...meta.argTypes, displayType: { ...meta.argTypes.displayType, options: allowedDisplayTypes, }, }; return <Story argTypes={updatedArgTypes} />; }, ], }; export default meta; const Template: FC<IButtonProps> = (args) => <Button {...args} />; export const Default = Template.bind({});
关键逻辑说明
- 映射关系:
appearanceDisplayTypeMap统一管理外观与显示类型的对应规则,可按需修改。 - 动态选项更新:在装饰器中通过
useArgs获取当前参数值,根据appearance的变化从映射中取出对应选项,更新argTypes配置。 - 无效值自动重置:切换外观后,若当前
displayType不在新的可选列表中,会自动重置为该外观下的第一个有效选项,避免无效状态。
简化方案(无自动重置)
如果不需要自动重置无效值,可直接在argTypes中为displayType设置动态选项函数:
argTypes: { // ...其他配置 displayType: { control: 'select', ...propCategory.appearance, // 根据当前appearance返回对应选项 options: (context) => appearanceDisplayTypeMap[context.args.appearance] || [], }, },
内容的提问来源于stack exchange,提问作者Garo Gabrielyan
相关产品推荐
相关产品推荐

