Button
Alvo de clique primário com seis variants visuais, oito presets de tamanho (incluindo icon-only), e um escape hatch `asChild` para renderização polimórfica.
Visão geral
Button é o primitive interativo fundamental. Uma única factory CVA controla sua superfície visual (variant) e footprint (size), então qualquer combinação é uma mudança de uma prop. Use para qualquer ação direta do usuário: submit, confirmar, navegar, dispensar, disparar.
Quando a ação precisa renderizar como um link, item de lista, ou qualquer host que não seja um button, defina asChild e o Radix Slot vai encaminhar todos os estilos e props do button para o primeiro filho.
Preview
'use client';import { Button } from '@gremorie/rx-forms';export function ButtonPreview() { return ( <div className="flex flex-wrap items-center gap-3"> <Button>Default</Button> <Button variant="secondary">Secondary</Button> <Button variant="outline">Outline</Button> <Button variant="ghost">Ghost</Button> <Button variant="link">Link</Button> <Button variant="destructive">Destructive</Button> </div> );}Anatomia
Button único <button> (ou filho asChild) estilizado por buttonVariants; filhos SVG são auto-dimensionados para size-4Instalação
bash npx gremorie@latest add rx-button bash pnpm dlx gremorie@latest add rx-button bash yarn dlx gremorie@latest add rx-button bash bunx --bun gremorie@latest add rx-button Uso
import { Button } from "@gremorie/rx-forms";
export function Example() {
return <Button onClick={handleClick}>Save changes</Button>;
}npx gremorie@latest add ng-buttonimport { Component } from '@angular/core';
import { Button } from '@gremorie/ng-forms';
@Component({
selector: 'app-example',
standalone: true,
imports: [Button],
template: `<ai-button (pressedChange)="handleClick()"
>Save changes</ai-button
>`,
})
export class ExampleComponent {
handleClick() {
// ...
}
}API
<Button>
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "default" | Tratamento visual. |
size | "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "default" | Preset de footprint. Tamanhos de icon são quadrados (size-*) sem padding horizontal. |
asChild | boolean | false | Quando true, renderiza via Radix Slot.Root; o primeiro filho recebe todos os estilos, props e eventos do button. |
disabled | boolean | false | Atributo HTML padrão. Adiciona pointer-events-none e opacity-50. |
Estende todos os React.ComponentProps<"button">. Encaminha um data-slot="button", data-variant e data-size para composição downstream (ex. ButtonGroup, InputGroup).
buttonVariants
Factory CVA exportada para que outros primitives possam reutilizar a superfície do button sem renderizar um <button> de verdade. As setas de navegação do Calendar e o InputGroupButton a consomem diretamente.
import { buttonVariants } from '@gremorie/rx-forms';
<a className={buttonVariants({ variant: 'outline', size: 'sm' })} href="/docs">
Read more
</a>;Composição
<Button>é a folha. Ele é dono de sua superfície visual e acessibilidade (disabled, focus ring,aria-invalid).- Ícones internos são auto-dimensionados via CSS (
[&_svg:not([class*='size-'])]:size-4) e recebempointer-events-nonepara que o button permaneça o alvo de clique. asChilddeixa você manter o tratamento visual enquanto renderiza como<a>,<Link>,<NavLink>, ou qualquer outro elemento host.
Variações
Todas as variants
Mostra cada variant como referência visual. default para ações primárias, destructive para as irreversíveis, outline e secondary para irmãos com menos ênfase, ghost para hosts estilo toolbar, link para navegação inline que deve parecer prosa.
<div className="flex flex-wrap gap-3">
<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button variant="destructive">Destructive</Button>
</div>Tamanhos
Quatro presets de footprint - xs, sm, default, lg - mantêm toolbars densas e CTAs primários visualmente consistentes. Tamanhos quadrados icon-only (icon-xs até icon-lg) são mostrados abaixo.
'use client';import { Button } from '@gremorie/rx-forms';export function ButtonSizesPreview() { return ( <div className="flex flex-wrap items-center gap-3"> <Button size="xs">Extra small</Button> <Button size="sm">Small</Button> <Button size="default">Default</Button> <Button size="lg">Large</Button> </div> );}Button com ícone à esquerda
Coloque um ícone como filho. O CSS o auto-dimensiona e aperta o padding horizontal via has-[>svg]:px-3.
'use client';import { Button } from '@gremorie/rx-forms';import { Download } from 'lucide-react';export function ButtonIconPreview() { return ( <Button> <Download /> Download report </Button> );}Button icon-only
Use size="icon" (ou icon-xs, icon-sm, icon-lg) para buttons quadrados. Sempre combine com um aria-label para que leitores de tela anunciem a ação.
Quando um icon button fica ao lado de outro controle, iguale os passos de altura pelas size variants (icon-sm com um select ou button size="sm", icon com os defaults) em vez de forçar alturas com classes. Veja Action rows e pareamento de tamanho.
'use client';import { Button } from '@gremorie/rx-forms';import { Trash2 } from 'lucide-react';export function ButtonIconOnlyPreview() { return ( <div className="flex flex-wrap items-center gap-3"> <Button size="icon-xs" variant="ghost" aria-label="Delete row"> <Trash2 /> </Button> <Button size="icon-sm" variant="ghost" aria-label="Delete row"> <Trash2 /> </Button> <Button size="icon" variant="ghost" aria-label="Delete row"> <Trash2 /> </Button> <Button size="icon-lg" variant="ghost" aria-label="Delete row"> <Trash2 /> </Button> </div> );}Disabled
disabled remove o button da ordem de tabulação, reduz a opacidade para 50% e bloqueia eventos de ponteiro. Aplica-se a todas as variants.
'use client';import { Button } from '@gremorie/rx-forms';export function ButtonDisabledPreview() { return ( <div className="flex flex-wrap items-center gap-3"> <Button disabled>Default</Button> <Button variant="outline" disabled> Outline </Button> <Button variant="destructive" disabled> Destructive </Button> </div> );}asChild para navegação
Renderize os estilos do button em um <Link> ou <a> para que a semântica do elemento combine com o destino (router.push no clique, middle-click funcionando, href amigável para SEO).
import Link from 'next/link';
<Button asChild>
<Link href="/dashboard">Open dashboard</Link>
</Button>;Acessibilidade
- Teclado: o
<button>nativo aceitaEntereSpace.asChildpreserva qualquer semântica que o elemento host fornecer. - Focus: ring de 3px controlado por
focus-visible:ring-ring/50, então aparece apenas para navegação por teclado, nunca no clique. - Disabled:
disabledremove o elemento da ordem de tabulação, reduz a opacidade para 50% e aplicapointer-events-nonepara que o button também não possa ser ativado pelo mouse. - Invalid:
aria-invalid="true"troca o focus ring para o token destructive. - Icon-only: sempre forneça
aria-label. Sem ele, leitores de tela anunciam o button sem nome.
Relacionados
- Button Group - une vários buttons em um único cluster com borda compartilhada
- Input Group - embute
InputGroupButtondentro de um input - Toggle - button de dois estados (
aria-pressed) para ações com estado - Field - compõe Button com
FormControlpara affordances de submit