Button Component

Componente de botão versátil com múltiplas variações, estados e tamanhos. Construído com acessibilidade e responsividade em mente.

Variações Básicas

Variantes do Button

Diferentes estilos visuais para diferentes contextos

Tamanhos

Diferentes tamanhos para diferentes contextos de uso

Com Ícones

Botões com Ícones

Combinando ícones com texto para melhor UX

Estados Interativos

Estados e Loading

Botões com estados de loading e interações

Implementação

components/ui/button.tsxtsx
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"

const buttonVariants = cva(
  "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-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 bg-background 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",
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button"
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    )
  }
)
Button.displayName = "Button"

export { Button, buttonVariants }

Props API

PropTipoDefaultDescrição
variantstring"default"Estilo visual do botão
sizestring"default"Tamanho do botão
asChildbooleanfalseRenderiza como elemento filho
disabledbooleanfalseDesabilita o botão
Dica
Use a prop asChild quando quiser aplicar os estilos do Button a outro componente, como um Link do Next.js: <Button asChild><Link href="/page">Link</Link></Button>

Boas Práticas

✅ Faça

  • • Use ícones para melhorar a compreensão da ação
  • • Implemente estados de loading para ações assíncronas
  • • Use variantes apropriadas para o contexto (destructive para deletar)
  • • Mantenha textos concisos e descritivos

❌ Evite

  • • Usar muitas variantes diferentes na mesma interface
  • • Botões muito pequenos em dispositivos touch
  • • Textos genéricos como "Clique aqui" ou "Botão"
  • • Esquecer de implementar estados de loading