Skip to main content
Gremorie

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-4

Instalaçã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-button
import { 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>

PropTypeDefaultDescription
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.
asChildbooleanfalseQuando true, renderiza via Radix Slot.Root; o primeiro filho recebe todos os estilos, props e eventos do button.
disabledbooleanfalseAtributo 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

  1. <Button> é a folha. Ele é dono de sua superfície visual e acessibilidade (disabled, focus ring, aria-invalid).
  2. Ícones internos são auto-dimensionados via CSS ([&_svg:not([class*='size-'])]:size-4) e recebem pointer-events-none para que o button permaneça o alvo de clique.
  3. asChild deixa 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 aceita Enter e Space. asChild preserva 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: disabled remove o elemento da ordem de tabulação, reduz a opacidade para 50% e aplica pointer-events-none para 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 InputGroupButton dentro de um input
  • Toggle - button de dois estados (aria-pressed) para ações com estado
  • Field - compõe Button com FormControl para affordances de submit

On this page