Carregando…
Carregando…
Carregando…Primitive button with 6 variants, 5 sizes, 7 intents, async loading, icon slots and magnetic/confetti/confirm modes.
$ npx kikitocn add button@/lib/utils| Prop | Tipo | Padrão | Descrição |
|---|---|---|---|
effect | 'none' | 'magnetic' | 'confetti' | 'none' | Efeito físico/visual absorvido: 'magnetic' atrai o botão em direção ao cursor; 'confetti' dispara uma explosão de confete no clique |
confirm | 'doubleclick' | 'hold' | undefined | Exige um gesto de confirmação antes de disparar onClick: duplo-clique ou pressionar-e-segurar |
magneticStrength | number | 0.4 | Intensidade da atração magnética (effect="magnetic") |
magneticRadius | number | 80 | Raio de ativação em px da atração magnética (effect="magnetic") |
particleCount | number | 60 | Número de partículas de confete (effect="confetti") |
spread | number | 120 | Dispersão do confete (effect="confetti") |
confirmLabel | ReactNode | 'Click again to confirm' | Texto exibido enquanto aguarda o segundo clique (confirm="doubleclick") |
holdDuration | number | 800 | Duração do hold em ms até confirmar (confirm="hold") |
resetDelay | number | 2000 | Atraso em ms antes de resetar o estado de confirmação (confirm="doubleclick") |
variant | 'solid' | 'outline' | 'ghost' | 'soft' | 'dashed' | 'link' | 'solid' | Estilo visual do botão |
intent | 'primary' | 'secondary' | 'danger' | 'success' | 'warning' | 'info' | 'neutral' | 'primary' | Intenção semântica da ação |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Tamanho do botão |
rounded | 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full' | undefined | Override do border-radius (independente do size) |
loading | boolean | false | Loading manual (não gerenciado automaticamente) |
status | 'idle' | 'loading' | 'success' | 'error' | undefined | Estado controlado externamente para feedback assíncrono |
successText | string | undefined | Texto exibido no estado success |
errorText | string | undefined | Texto exibido no estado error |
loadingText | string | undefined | Texto exibido no loading (quando loadingPosition="left") |
loadingPosition | 'replace' | 'left' | 'left' | Posição do spinner: left mostra inline ao lado do texto, replace troca o conteúdo preservando a largura |
iconLeft | ReactNode | undefined | Ícone exibido à esquerda do texto |
iconRight | ReactNode | undefined | Ícone exibido à direita do texto |
iconOnly | boolean | false | Botão quadrado sem texto (igual width/height) |
fullWidth | boolean | false | Expande para 100% da largura do container |
disabled | boolean | false | Desabilita o botão |
as | ElementType | 'button' | Elemento raiz polimórfico (ex: "a" para link button) |
onClick | (e: MouseEvent) => void | Promise<void> | undefined | Handler de clique. Se retornar Promise, gerencia loading/success/error automaticamente |
Solid (default)
Outline
Ghost
Soft
Dashed
Link
XS → XL (solid)
Icon-only sizes
All intents — solid
All intents — outline
All intents — soft
Icon left
Icon right
Radius progression — none → full
Loading — spinner beside text (default, keeps label)
Loading — replace mode (spinner only, preserves width)
Success / Error — animated check & X (auto from async onClick)
Disabled
Full width
Magnetic Button — button follows cursor within radius
Confetti Button — canvas confetti burst on click
Confirm Button — double-click or hold to confirm
import { Button } from "@/components/ui/cn/button/Button";
export function ButtonExample() {
return (
<div className="flex flex-wrap gap-2">
<Button variant="solid" intent="primary">
Confirmar
</Button>
<Button variant="outline" intent="neutral">
Cancelar
</Button>
<Button variant="ghost" intent="danger" size="sm">
Excluir
</Button>
<Button variant="solid" intent="primary" loading>
Salvando...
</Button>
</div>
);
}