Capítulo 59 de 108

Spinner

Core Idea

Indicador de loading indeterminado: um ícone SVG (LoaderIcon do lucide-react) com animação de rotação via classe Tailwind animate-spin. É o componente mais simples do catálogo e serve como bloco de composição dentro de outros componentes.

Key Concepts

  • data-icon="inline-start" | "inline-end": atributo usado quando o Spinner é colocado dentro de Button ou Badge, para posicioná-lo antes/depois do texto.
  • size-*: classes Tailwind (size-3, size-4, size-6, size-8) controlam o tamanho do spinner — não há prop size dedicada.
  • Customização por substituição: trocar o ícone do spinner é editar diretamente o arquivo components/ui/spinner.tsx, não passar props.

Code Examples

import { LoaderIcon } from "lucide-react"
import { cn } from "@/lib/utils"

function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
  return (
    <LoaderIcon
      role="status"
      aria-label="Loading"
      className={cn("size-4 animate-spin", className)}
      {...props}
    />
  )
}

export { Spinner }
  • O que demonstra: implementação completa do componente — trivial o suficiente para editar in-place ao trocar de ícone.
<Button disabled size="sm">
  <Spinner data-icon="inline-start" />
  Loading...
</Button>
  • O que demonstra: padrão de botão em estado de loading, desabilitado com spinner à esquerda do texto.
<InputGroup>
  <InputGroupInput placeholder="Send a message..." disabled />
  <InputGroupAddon align="inline-end">
    <Spinner />
  </InputGroupAddon>
</InputGroup>
  • O que demonstra: uso do Spinner dentro de um InputGroupAddon para indicar processamento de um campo de texto.

Anti-patterns

  • Esquecer disabled no botão durante loading: o spinner sinaliza visualmente, mas não bloqueia interação sozinho.
  • Usar Progress quando não há valor numérico conhecido: Spinner é para estado indeterminado; Progress exige value.

Key Takeaways

  1. Spinner é essencialmente um ícone com animate-spin — customizar é editar o arquivo, não configurar props.
  2. data-icon="inline-start|inline-end" é o padrão de posicionamento usado em Button, Badge e InputGroup.
  3. Combine com Empty para telas de carregamento de página inteira.

Connects To

  • Badge (ch061): usa o mesmo padrão data-icon para exibir spinner dentro de um badge.
  • Empty (ch062): EmptyMedia pode conter um Spinner como estado de carregamento de página.
  • Progress (ch058): alternativa para quando o progresso é mensurável.