如何避免Storybook控件中cva生成的null值选项或实现默认回退
使用CVA创建按钮变体时解决Storybook控件出现null选项的问题
我用class-variance-authority(简称cva)定义按钮变体,并通过VariantProps推断按钮Props类型:
const variants = cva( { variants: { intent: { primary: [ ... ], secondary: [ ... ], ghost: [ ... ], }, size: { ... }, }, defaultVariants: { intent: "primary", size: "md", }, } ); type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof variants>
应用运行正常,手动传入intent或使用默认值都没问题,但Storybook的intent控件里除了定义的变体选项,还多出个null选项;选择null后按钮不会应用任何变体样式(预期应回退到默认样式)。目前只能通过在ButtonProps中添加额外类型覆盖cva的推断类型来消除null:
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof variants> & { intent?: string; };
以下是不覆盖cva推断类型的两种解决方案:
方案一:直接移除Storybook控件的null选项
在Storybook的参数配置中,给intent控件指定可选值为cva定义的变体,并禁用null选项:
// Button.stories.tsx import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button'; const meta: Meta<typeof Button> = { component: Button, argTypes: { intent: { control: { type: 'select', options: ['primary', 'secondary', 'ghost'], allowNull: false, }, }, }, }; export default meta; type Story = StoryObj<typeof Button>; export const Primary: Story = { args: { intent: 'primary', }, };
这样控件只会显示你定义的三个intent选项,不再出现null。
方案二:让null触发默认样式
修改按钮组件逻辑,将null值替换为cva的默认变体值,不改动类型定义:
import { cva, VariantProps } from 'class-variance-authority'; const variants = cva(/* 保持原有的变体定义 */); type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof variants>; export const Button = ({ intent, size, ...props }: ButtonProps) => { // 用空值合并运算符处理null,回退到默认值 const resolvedIntent = intent ?? 'primary'; const resolvedSize = size ?? 'md'; return ( <button className={variants({ intent: resolvedIntent, size: resolvedSize })} {...props} /> ); };
这样即使Storybook传入null,组件也会自动使用默认的primary样式,同时保留cva原本的类型推断逻辑,无需覆盖ButtonProps。
内容的提问来源于stack exchange,提问作者preska
相关产品推荐
相关产品推荐

