1.0.5 • Published 5 months ago

@mgalexandre/storybook-project v1.0.5

Weekly downloads
-
License
-
Repository
-
Last release
5 months ago

Storybook React Starter

Este é um projeto starter para desenvolvimento de componentes React utilizando Storybook, Vite, TypeScript e Tailwind CSS.

🚀 Tecnologias

  • React 19
  • Vite com SWC
  • TypeScript
  • Tailwind CSS
  • Storybook 9
  • Vitest para testes unitários
  • ESLint + Prettier para linting
  • class-variance-authority (cva) para variantes de componentes
  • Lottie para animações
  • Integração com Figma usando @storybook/addon-designs

NPM Package

https://www.npmjs.com/package/@mgalexandre/storybook-project

📦 Instalação

  1. Clone o repositório:
git clone [URL_DO_REPOSITÓRIO]
cd storybook-project
  1. Instale as dependências:
npm install
  1. Inicie o Storybook:
npm run storybook

🛠️ Scripts Disponíveis

  • npm run dev - Inicia o servidor de desenvolvimento Vite
  • npm run storybook - Inicia o Storybook
  • npm run build-storybook - Constrói o Storybook para produção
  • npm run test - Executa os testes com Vitest
  • npm run test:coverage - Executa os testes com cobertura
  • npm run test:ui - Executa os testes com interface visual
  • npm run lint - Executa o ESLint
  • npm run format - Formata o código com Prettier

📁 Estrutura do Projeto

src/
├── components/         # Componentes React
│   ├── Button/        # Exemplo de componente
│   │   ├── Button.tsx
│   │   ├── Button.stories.tsx
│   │   ├── Button.test.tsx
│   │   └── index.ts
├── assets/            # Recursos estáticos
├── styles/            # Estilos globais
└── utils/             # Funções utilitárias
    ├── cn.ts         # Utilitário para classes condicionais
    └── SvgUtil.tsx   # Componente utilitário para SVGs

🎨 Desenvolvimento de Componentes

Criando um Novo Componente

  1. Crie uma nova pasta em src/components com o nome do componente
  2. Crie os ficheiros necessários:
    • ComponentName.tsx - Implementação do componente
    • ComponentName.stories.tsx - Histórias do Storybook
    • ComponentName.test.tsx - Testes do componente
    • index.ts - Exportação do componente

Exemplo de Componente com CVA

import type { ComponentProps } from "react";
import { cn } from "../../utils/cn";
import { cva, type VariantProps } from "class-variance-authority";

type ButtonProps = ComponentProps<"button"> & 
  ComponentProps<"a"> & 
  VariantProps<typeof buttonStyles> & {
    children: React.ReactNode;
    handleButtonClick?: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>;
    link?: string;
    icon?: React.FC<React.SVGProps<SVGSVGElement>>;
    isLoading?: boolean;
};

const buttonStyles = cva([
  "rounded-md",
  "px-6",
  "py-3",
  "text-white",
  "border-transparent",
  "transition-all duration-500"
], {
  variants: {
    variant: {
      primary: "bg-neutral-100 text-neutral-900",
      secondary: "bg-neutral-800 text-neutral-200",
      outline: "bg-transparent text-neutral-200 border-1 border-neutral-700",
      ghost: "bg-transparent text-neutral-200",
      iconbutton: "bg-neutral-100 text-neutral-200 flex items-center gap-3",
    },
    size: {
      sm: "px-4 py-2 text-sm",
      md: "px-6 py-3 text-base",
      lg: "px-7 py-4 text-lg",
    },
    // ... outras variantes
  },
  defaultVariants: {
    variant: "primary",
    size: "sm",
  },
});

export default function Button({ 
  className, 
  children, 
  variant, 
  size,
  handleButtonClick,
  link,
  icon,
  isLoading,
  ...props 
}: ButtonProps) {
  const classes = cn(buttonStyles({ className, variant, size }));

  if (isLoading) {
    return (
      <div className={cn(classes)}>
        <DotLottieReact
          src="loading-animation.lottie"
          loop={true}
          autoplay={true}
          width={15}
          height={15}
          role="button"
          data-testid="loading-spinner"
          className="cursor-not-allowed"
        />
      </div>
    );
  }

  if (link) {
    return (
      <a 
        href={link} 
        className={classes} 
        onClick={handleButtonClick} 
        role="button" 
        {...props}
        tabIndex={0}
      >
        {children}
        {icon && <SvgUtil size="sm" role="img" Icon={icon} />}
      </a>
    );
  }

  return (
    <button 
      onClick={handleButtonClick} 
      className={classes} 
      {...props}
    >
      {children}
      {icon && <SvgUtil size="sm" role="img" Icon={icon} />}
    </button>
  );
}

🎨 Estilização

Utilitários

  • cn.ts - Função utilitária para combinar classes condicionais
  • SvgUtil.tsx - Componente para renderização consistente de ícones SVG

Temas e Variantes

  • Use class-variance-authority para gerir variantes de componentes
  • Mantenha consistência com o design system
  • Utilize classes utilitárias do Tailwind
  • Suporte a temas claro/escuro
  • Animações com Lottie

📝 Documentação

Para mais detalhes sobre:

  • Convenções de código
  • Processo de contribuição
  • Guia de estilos
  • Configuração de temas

Consulte o ficheiro CONTRIBUTING.md

🤝 Contribuindo

Por favor, leia o CONTRIBUTING.md para detalhes sobre o nosso código de conduta e o processo para enviar pull requests.

📄 Licença

Este projeto está sob a licença MIT. Veja o ficheiro LICENSE para mais detalhes.

🧪 Testes

Configuração de Testes

O projeto utiliza Vitest e React Testing Library para testes de componentes. A configuração dos testes está em vitest.config.ts e src/setupTests.ts.

Testes de Componentes

Os seguintes componentes possuem suites de testes abrangentes:

  • Button.test.tsx: Testes para variantes, tamanhos, temas e interações
  • Input.test.tsx: Testes para variantes, tamanhos, temas e manipulação de formulários
  • Card.test.tsx: Testes para variantes, tamanhos, temas e renderização de conteúdo
  • Avatar.test.tsx: Testes para variantes, tamanhos, indicadores de estado e manipulação de imagens
  • Modal.test.tsx: Testes para variantes, tamanhos, temas e manipulação de interações
  • Navbar.test.tsx: Testes para variantes, tamanhos, temas e layout
  • Section.test.tsx: Testes para variantes, tamanhos, orientações e layout
  • Badge.test.tsx: Testes para variantes, tamanhos, esquemas de cores e posicionamento

Cada suite de testes cobre: 1. Renderização básica 2. Manipulação de props 3. Interações do utilizador 4. Variantes e estilos 5. Recursos de acessibilidade 6. Casos de borda

Executando Testes

# Executa testes em modo watch
npm test

# Executa testes com cobertura
npm run test:coverage

# Executa testes com UI
npm run test:ui

Exemplo de Teste com Vitest

import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import Button from './Button';

describe('Button', () => {
  it('renderiza corretamente', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button')).toBeInTheDocument();
  });

  it('manipula eventos de clique', () => {
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>Click me</Button>);
    screen.getByRole('button').click();
    expect(handleClick).toHaveBeenCalled();
  });
});

Cobertura de Testes

O projeto visa uma alta cobertura de testes. Execute npm run test:coverage para gerar um relatório de cobertura. Foque em testar:

  • Renderização de componentes
  • Interações do utilizador
  • Props e variantes
  • Acessibilidade
  • Casos de borda

Boas Práticas de Testes

  1. Use queries semânticas (getByRole, getByLabelText, etc.)
  2. Teste interações do utilizador, não detalhes de implementação
  3. Mock dependências externas
  4. Teste recursos de acessibilidade
  5. Use atributos data-testid quando necessário
  6. Mantenha os testes focados e isolados

🎨 Desenvolvimento de Componentes

Integração com Figma

O projeto utiliza o @storybook/addon-designs para integração com o Figma. Para configurar:

  1. Instale o addon:
npm i -D @storybook/addon-designs
  1. Configure no .storybook/main.ts:
import type { StorybookConfig } from "@storybook/react-vite";

const config: StorybookConfig = {
  stories: ["../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-essentials",
    "@storybook/addon-designs"
  ],
  framework: {
    name: "@storybook/react-vite",
    options: {},
  },
  docs: {
    autodocs: true,
  },
};

export default config;
  1. Use nas suas stories:
export default {
  title: 'Components/Button',
  component: Button,
};

export const Default = {
  parameters: {
    design: {
      type: 'figma',
      url: 'https://www.figma.com/file/YOUR_FILE_ID/YOUR_FILE_NAME',
    },
  },
};

```# storybook-template-rn