@mgalexandre/storybook-project v1.0.5
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
- Clone o repositório:
git clone [URL_DO_REPOSITÓRIO]
cd storybook-project- Instale as dependências:
npm install- Inicie o Storybook:
npm run storybook🛠️ Scripts Disponíveis
npm run dev- Inicia o servidor de desenvolvimento Vitenpm run storybook- Inicia o Storybooknpm run build-storybook- Constrói o Storybook para produçãonpm run test- Executa os testes com Vitestnpm run test:coverage- Executa os testes com coberturanpm run test:ui- Executa os testes com interface visualnpm run lint- Executa o ESLintnpm 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
- Crie uma nova pasta em
src/componentscom o nome do componente - Crie os ficheiros necessários:
ComponentName.tsx- Implementação do componenteComponentName.stories.tsx- Histórias do StorybookComponentName.test.tsx- Testes do componenteindex.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 condicionaisSvgUtil.tsx- Componente para renderização consistente de ícones SVG
Temas e Variantes
- Use
class-variance-authoritypara 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çõesInput.test.tsx: Testes para variantes, tamanhos, temas e manipulação de formuláriosCard.test.tsx: Testes para variantes, tamanhos, temas e renderização de conteúdoAvatar.test.tsx: Testes para variantes, tamanhos, indicadores de estado e manipulação de imagensModal.test.tsx: Testes para variantes, tamanhos, temas e manipulação de interaçõesNavbar.test.tsx: Testes para variantes, tamanhos, temas e layoutSection.test.tsx: Testes para variantes, tamanhos, orientações e layoutBadge.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:uiExemplo 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
- Use queries semânticas (getByRole, getByLabelText, etc.)
- Teste interações do utilizador, não detalhes de implementação
- Mock dependências externas
- Teste recursos de acessibilidade
- Use atributos data-testid quando necessário
- 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:
- Instale o addon:
npm i -D @storybook/addon-designs- 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;- 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