Pesquisa de site

reactjs - Evitando valor nulo nos controles do Storybook


Estou usando class-variance-authority para criar variantes de botão e, em seguida, inferindo tipos a partir disso para as propriedades do botão:

const variants = cva(
  {
    variants: {
      intent: {
        primary: [
          ...
        ],
        secondary: [
          ...
        ],
        ghost: [
          ...
        ],
      },
      size: {
        ...
      },
    },
    defaultVariants: {
      intent: "primary",
      size: "md",
    },
  }
);

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
  VariantProps<typeof variants>

isso funciona bem no app. Consigo adicionar a propriedade intent ao botão ou usar a padrão como fallback.

Mas no Storybook, sob controles para intenção, eu recebo variantes do cva e valor nulo.

captura de tela do storybook

Se eu escolher nulo, meu botão não terá nenhum dos estilos das variantes (eu estava sob a impressão de que ele voltaria para o padrão).
Para evitar nulo, eu tenho que adicionar um tipo adicional nas propriedades do botão, e com isso basicamente sobrescrevo o que foi inferido a partir do cva.

Então, como posso obter um valor alternativo ao clicar em null, ou como não ver o valor null de forma alguma sem sobrescrever o tipo inferido de cva

quando eu adiciono às propriedades do meu botão

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
  VariantProps<typeof variants> & {
     intent?: string;
  };

o valor nulo desapareceu

Resposta #1

Deixei uma pergunta no GitHub do cva e recebi a resposta abaixo. https://github.com/joe-bell/cva/issues/253

Acho que haverá uma atualização em breve, amigos.

Ou, aqui está também uma alternativa. remover null ou undefined das propriedades de um tipo

Resposta #2

Uma solução que eu encontrei é criar um tipo utilitário personalizado VariantProp que exclui o tipo null. Aqui está como:

import { type VariantProp } from 'class-variant-authority';

type ExcludeNull<T> = { [P in keyof T]: Exclude<T[P], null> };

export type CustomVariantProp<Comp extends (...args: any) => any> = ExcludeNull<VariantProps<Comp>>;

Aqui está um exemplo:

const variants = cva(
  {
    variants: {
      color: {
        primary: 'bg-primary',
        secondary: 'bg-secondary',
      }
    }
  }
);

// ❌
type WierdWithStorybookControls = VariantProps<typeof variants>;
// -> { color: 'primary' | 'secondary' | null | undefined }

// ✅
type WorksWithStorybookControls = CustomVariantProps<typeof variants>;
// -> { color: 'primary' | 'secondary' | undefined }


type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> &
  CustomVariantProps<typeof variants> & {
     intent?: string;
  };

Você também pode ir além para excluir undefined se quiser, passar uma variante padrão para cva OU usar react-docgen-typescript em vez disso. Veja a configuração do storybook - https://storybook.js.org/docs/configure/typescript

Como mencionado, o problema será corrigido no futuro, então fique atento (https://github.com/joe-bell/cva/issues/253#issuecomment-1882982172)