design

Design System: Como criar componentes reutilizáveis

Ricardo Laurito

Ricardo Laurito

UI/UX Designer e Desenvolvedor Web especializado em React e Next

10 ene 2025 3 min de leitura
HomeBlogdesign

Design System: Como criar componentes reutilizáveis

Um design system é fundamental para manter consistência em aplicações web modernas. Neste artigo, vamos explorar como criar e implementar um design system eficiente.

O que é um Design System?

Um design system é uma coleção de componentes reutilizáveis, guiados por padrões claros, que podem ser unidos para construir qualquer quantidade de aplicações.

Componentes principais:

  1. Tokens de design: Cores, tipografia, espaçamentos
  2. Componentes base: Buttons, inputs, cards
  3. Padrões de layout: Grid systems, containers
  4. Documentação: Guias de uso e exemplos

Criando um Button Component

Vamos começar com um componente básico - um botão:

// components/ui/Button.tsx
import { ReactNode } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';

const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
        outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
        secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
        link: 'text-primary underline-offset-4 hover:underline',
      },
      size: {
        default: 'h-10 px-4 py-2',
        sm: 'h-9 rounded-md px-3',
        lg: 'h-11 rounded-md px-8',
        icon: 'h-10 w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
);

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
  children: ReactNode;
}

export function Button({ className, variant, size, children, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    >
      {children}
    </button>
  );
}

Tokens de Design

Defina seus tokens de design no Tailwind config:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          50: '#eff6ff',
          500: '#3b82f6',
          900: '#1e3a8a',
        },
        secondary: {
          50: '#f8fafc',
          500: '#64748b',
          900: '#0f172a',
        },
      },
      fontFamily: {
        sans: ['Inter', 'sans-serif'],
        mono: ['JetBrains Mono', 'monospace'],
      },
      spacing: {
        '18': '4.5rem',
        '88': '22rem',
      },
    },
  },
};

Documentação com Storybook

Use Storybook para documentar seus componentes:

// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  title: 'Components/Button',
  component: Button,
  parameters: {
    layout: 'centered',
  },
  tags: ['autodocs'],
  argTypes: {
    variant: {
      control: { type: 'select' },
      options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'],
    },
  },
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    children: 'Button',
  },
};

export const Secondary: Story = {
  args: {
    variant: 'secondary',
    children: 'Button',
  },
};

Versionamento e Distribuição

  1. NPM Package: Publique como pacote npm
  2. Monorepo: Use Lerna ou NX
  3. Git Submodules: Para projetos internos
  4. CDN: Para distribuição rápida

Testes

Garanta qualidade com testes:

// Button.test.tsx
import { render, screen } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('renders button with text', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
  });

  it('applies variant styles', () => {
    render(<Button variant="secondary">Secondary</Button>);
    const button = screen.getByRole('button');
    expect(button).toHaveClass('bg-secondary');
  });
});

Conclusão

Um design system bem estruturado economiza tempo de desenvolvimento, garante consistência visual e melhora a experiência do usuário. Comece pequeno e evolua gradualmente.

Lembre-se: um design system é um produto vivo que deve evoluir com suas necessidades.

Ricardo Laurito

Sobre o Autor

UI/UX Designer e Desenvolvedor Web especializado em React e Next.js

Comentários

0 Comentários

Seja o primeiro a comentar neste artigo.