You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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({});

关键逻辑说明

  1. 映射关系:appearanceDisplayTypeMap统一管理外观与显示类型的对应规则,可按需修改。
  2. 动态选项更新:在装饰器中通过useArgs获取当前参数值,根据appearance的变化从映射中取出对应选项,更新argTypes配置。
  3. 无效值自动重置:切换外观后,若当前displayType不在新的可选列表中,会自动重置为该外观下的第一个有效选项,避免无效状态。

简化方案(无自动重置)

如果不需要自动重置无效值,可直接在argTypes中为displayType设置动态选项函数:

argTypes: {
  // ...其他配置
  displayType: {
    control: 'select',
    ...propCategory.appearance,
    // 根据当前appearance返回对应选项
    options: (context) => appearanceDisplayTypeMap[context.args.appearance] || [],
  },
},

内容的提问来源于stack exchange,提问作者Garo Gabrielyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:52:13