← NASH N.A.S.H. DS Primary Button 327:845

Button

A pílula com rótulo, meta text e ícone opcional para qualquer ação com texto: 32, 44 e 56 de alto, raio 24, o anel de 1,5 por dentro. Três estados desenhados (Default, Hover e Pressed, no tamanho de 56) e o que um botão precisa além deles: três tamanhos, três ênfases (o primário com o arco âmbar girando, o secundário com o anel branco, o fantasma sem placa), ligado (aria-pressed), ocupado (aria-busy), foco pelo teclado, desabilitado. O accent é o do modo, a mesma tabela do Tab Bar, do Text Input e do Icon Button. Os nomes são os do mapa de vocabulário.

modo no ar: Chatúltimo gesto: nenhumpasse o cursor · aperte · o primário ocupa e conclui · Editar liga

As três variantes, e os dois eixos

O quadro do Figma, congelado: não respondem ao ponteiro, e o arco está parado no quadro desenhado. State=Default, Hover e Pressed, no único tamanho que a referência desenhou, 56 — o large da peça. Abaixo, o que o Figma não desenha e a peça define: os três tamanhos (data-size) e as três ênfases (data-emphasis). Pendentes no Figma.

Default Hover Pressed
small · 32 medium · 44 large · 56 primary secondary ghost
data-sizealturade onderaiorespiro lateralrótulometa textgapícone
small32--nash-target-dense, o alvo em barra densa24 → pílula16 (--nash-space-3)13 (--nash-type-size-3)11 (--nash-type-size-1) a 58%8 (--nash-space-1)16
medium44--nash-target-loose, a "pílula de 44px" do mapa; padrão24 → pílula24 (--nash-space-4)15 (--nash-type-size-4)12 (--nash-type-size-2) a 58%12 (--nash-space-2)16
large56o Figma, 327:8452426 (o Figma)15 (o Figma)12 (o Figma) a 58%12 (o Figma)16

Anatomia

O primário do Figma apertado e um secundário ligado, ampliados 1,35×. Numerado é o que o CSS desenha; cotado é o que o Figma mede.

Large 56 · raio 24 · respiro 26 · rótulo 15 · meta 12 · gap 12 Medium 44 · respiro 24 · stroke 1,5 por dentro
  1. A placa.#0D0F12 a 32% com o vidro desfocado atrás; #1F2128 a 40% sob o ponteiro; #080A0D a 32% apertada, ligada ou ocupada. Os três fills são tokens do kit (--nash-surface-fill, -hover, -pressed). Raio 24 (pílula a 32 e a 44). O fantasma não tem placa em repouso.
  2. Os anéis, 1,5px por dentro.No secundário, branco 15 › 6 › 2 › 0; accent 45 › 18 › 6 › 0 quando ligado, ocupado ou em foco pelo teclado. No primário, o arco âmbar do Figma (#FFB454 › #FF6B2C, 14% de alfa fora do arco) dando uma volta a cada 5,5s. A mesma máscara das três peças anteriores.
  3. O rótulo.Archivo 15 a 500 (13 no small), branco; o texto que a página escreveu, embrulhado pelo JS em .nash-button-label. Ligado toma o accent com text-shadow de 8px; ocupado baixa a 60%.
  4. O meta text.12 a 400, branco 58% (11 no small): "1 crédito". Opcional; a página escreve span.nash-button-meta ou passa meta ao montar.
  5. O ícone.Opcional, 16, traço 1,5 do .nash-icon do kit, antes ou depois do rótulo. A parte .nash-icon-fill enche ao ligar.
  6. A luz do cursor.Névoa de 2,4 alturas no accent a 12% e o anel aceso no ponto mais perto do ponteiro (1,4 altura, accent 70%). Só existe com o ponteiro em cima; mais forte apertada ou ligada.
  7. A varredura.Um traço de luz a 6% que atravessa a placa uma vez quando o ponteiro entra, pelo lado por onde ele entrou. Era o lampejo do kit; dentro da peça.
  8. O anel de pressão.O Button.Ring do mapa: um anel âmbar apagado, 4% maior que a casca. Apertar fecha e sobe a 40% em 50ms; soltar abre e apaga em 300. O concluído (complete()) o acende, segura e apaga em 700.
  9. A aura.Um elemento próprio (i.nash-button-halo) que segue o contorno da pílula: uma sombra do accent a 48% num elemento sem fundo, cuja borda de dentro é o tamanho do elemento e a de fora é o desfoque. Ligar abre a de fora; desligar move a de dentro, e a luz é comida de dentro pra fora. O halo da borda (box-shadow de 24px) continua na casca.

O que o Figma diz e o que a peça faz

Coluna a coluna: a medida do Figma, o que o kit já tinha, e o que a peça adotou. O identificador sai do mapa de vocabulário; o Figma dá a base.

Figma 327:845O kit / as três peçasA peça
Fill Default rgba(13,15,18,.32) · Hover rgba(31,33,40,.4) · Pressed rgba(8,10,13,.32)--nash-surface-fill · --nash-surface-fill-hover · --nash-surface-fill-pressediguais, byte a byte — os três tokens já existiam
Stroke 1,5 por dentro, o par âmbar #FFB454 › #FF6B2C, "animado no código, congelado aqui", uma volta a cada 4,5s; 14% de alfa fora do arco.nash-arco: o mesmo conic-gradient, degrau por degrau, a 5,5s (o dono alongou de 4,5 em 2026-09-04)data-emphasis="primary": o arco no anel, --nash-button-arc-a/-b, 5,5s (--nash-motion-loop-arc). Uma por tela
"Ações secundárias usam a mesma placa com o stroke branco original"anel branco 15 › 6 › 2 › 0 por máscara (.nash-surface, as três peças)o padrão, sem atributo (secondary); ghost sem placa em repouso
200 × 56, raio 24, respiro 26, gap 12 — um tamanho só.nash-button 44 (--nash-target-loose), --small 32 (--nash-target-dense), --large 56, raio píluladata-size="small|medium|large" = 32, 44, 56; o Figma é o large; raio 24 em todos (pílula a 32 e 44). --nash-button-height pra densidade de tela. O modificador BEM saiu
label: Archivo 15, branco · meta: 12, branco 58%rótulo t4 a 500, sem metarótulo 15 a 500 (13 no small); meta 12 a 400 e 58% (11 no small), parte .nash-button-meta
State=Pressed.nash-fx-press (0,98 em 100) + .nash-fx-ring-press (o anel sobe em 50, apaga em 300)Pressed = :active: placa, 0,98 em 100, solta em 160; o anel de pressão é parte da peça (fecha e sobe em 50; abre e apaga em 300). Num botão a pressão não fica; o que fica é ARIA
Sem ligado, ocupado, foco, desabilitadoaria-pressed pelo .nash-fx-selected; ocupado por nashMotion.ocupado; :disabled a 35%aria-pressed (accent no rótulo + halo + onda + aura, 540ms; depois respira; desligar em 600, a aura comida de dentro pra fora), aria-busy (arco de 1,8s; no primário sem salto; o clique é segurado), :focus-visible (anel + outline), :disabled (50%, o arco para). Estado é ARIA; nenhum data-estado. Pendentes no Figma
—.nash-button--filled: placa cheia no accent, texto no contrastesaiu. A ênfase mais alta é primary, com o arco; o eixo do mapa é primary|secondary|ghost, sem material
—.nash-fx-sweep + <i class="nash-surface-sweep">: o lampejo.nash-button-sweep, parte da peça: o mesmo traço, 640ms, pelo lado de entrada (--nash-runtime-sweep-direction). O lampejo do kit continua nos cartões
—.nash-fx-ring-complete + nashMotion.concluido(el): 700mscomplete(): os mesmos quadros no CSS, o disparo no JS. Efeito de um componente só não é camada (mapa, regra 9)
—sete classes por botão: nash-fx-interactive nash-surface nash-arco nash-fx-press nash-fx-highlight nash-fx-sweep nash-fx-ring-pressuma: class="nash-button" + data-size + data-emphasis + ARIA. A peça é autossuficiente, como o Icon Button
Nome: Primary Button, label, meta, State—.nash-button, .nash-button-label, .nash-button-meta, data-state. O identificador é do mapa (docs/vocabulario-mapa.json): inglês, parte nash-<bloco>-<parte>, token --nash-button-*, runtime --nash-runtime-*, evento nash:toggle
Escala de tempo--nash-tab-escala, --nash-text-input-escala, --nash-icon-button-time-scale, --nash-motion-scale--nash-button-time-scale, com --nash-motion-scale da família como fallback
Movimento reduzido.nash-reduzido; o Icon Button lê [data-motion="reduced"][data-motion="reduced"] num ancestral, o nome do vocabulário

O que se move

Toda curva é a de saída do kit. Os laços ficam presos a estados: o arco do primário (5,5s; pausado desabilitado, congelado ou reduzido), a volta de ocupado (1,8s) e a respiração de aria-pressed (um número, --nash-button-breath, que o halo da borda e a aura leem; ao desligar ele pausa onde está em vez de sumir).

Ponteiro entra hover

A placa sobe de 32% a 40% e a luz do cursor acende. O anel branco já está a 1; no fantasma ele aparece junto com a placa. O stroke âmbar do primário não muda: só o fill, como o Figma diz.

passe o cursor pelos três
propriedadede → paratempo
placa#0D0F12 32% → #1F2128 40%180ms
anel branco (fantasma)0 → 1180ms
luz do cursor0 → 1260ms

A luz do cursor vidro

Uma névoa de 2,4 alturas no accent e o anel aceso no ponto mais próximo do ponteiro. Segue em 70ms; apaga em 260 quando o ponteiro sai. Apertada ou ligada, a névoa é mais forte.

arraste o cursor devagar pela pílula
camadacortempo
névoaaccent 12% (ligado 18%, apertada 24%), 2,4 alturas260ms · segue em 70
anelaccent 70%, 1,4 altura260ms

A varredura é vidro

Um traço de luz a 6% atravessa a placa uma vez quando o ponteiro entra, pelo lado por onde ele entrou (o JS grava --nash-runtime-sweep-direction antes de o :hover disparar). Não repete enquanto o ponteiro fica. Era o lampejo do kit; nos cartões ele continua sendo.

entre pela esquerda, depois pela direita
propriedadede → paratempo
traço (42% da casca, branco 6%, −8°)translateX −130% → 190%, pelo lado de entrada640ms
opacidade0 → 1 a 20% → 0640ms

Pressão o Pressed do Figma

A placa desce pro #080A0D e a casca assenta a 0,98 em 100ms; junto, o anel de pressão fecha na borda e sobe a 40% em 50. Soltar: a casca volta em 160 e o anel abre 4% e apaga em 300. Não fica: o que fica é aria-pressed.

segure o botão apertado e solte

Apertar · 180ms

Soltar · 300ms

Ligar e desligar aria-pressed

Ligar: a placa desce pro #080A0D, o anel branco apaga (no primário o arco fica), o rótulo toma o accent em 140 com text-shadow, a parte .nash-icon-fill do ícone enche em 260 e o anel de accent acende. O halo da borda espera 120 e vai a 32px antes de assentar em 24 — a curva do ponto da aba — com uma onda que se abre da borda e apaga, e a aura se abre da borda até meia casca além em 420. Total: 540ms. Depois, ligado, respira: halo e aura, laço de 1,8s. Desligar: placa, anéis, cor e fill voltam nos mesmos tempos; o halo da borda apaga em 320; a aura é comida de dentro pra fora em 600 e a respiração pausa onde está, então nada salta. O clique alterna quando a peça é montada com toggle; o evento é nash:toggle.

Ligar · 540ms

Desligar · 600ms

Ocupado aria-busy

No secundário, o anel de accent vira um arco que dá a volta em 1,8s, sem halo. No primário, a volta lenta do arco âmbar pausa e a de ocupado roda, também em 1,8s: são dois ângulos registrados somados, então o arco não salta ao entrar nem ao sair. O rótulo baixa a 60%; o clique é segurado. Termina com o estado.

propriedadede → paratempo
anel de accent (secundário)gradiente → arco cônico, --nash-runtime-spin 0 → 360°laço 1800ms
arco âmbar (primário)a volta lenta pausa; --nash-button-busy-spin 0 → 360°laço 1800ms
rótulo1 → 0,6140ms

O arco data-emphasis="primary"

A ação principal, viva: o stroke é o par âmbar do Figma dando uma volta a cada 5,5s, com 14% de alfa fora do arco pra borda nunca sumir. Uma por tela — é a única cor em movimento na interface. Desabilitado, congelado (data-state) ou com movimento reduzido, para no quadro em que estava: o que o Figma desenha.

à direita, desabilitado: o arco parado
propriedadede → paratempo
--nash-runtime-spin0 → 360°, linearlaço 5500ms
arco#FFB454 a 58° → #FF6B2C a 118°; 14% de 196° a 360°—

Concluído complete()

O anel de pressão acende, segura e apaga em 700ms, uma vez por evento — só opacidade, sem escala. Era o nashMotion.concluido(el) do kit; os quadros continuam no CSS (nash-button-ring-complete), o disparo é o método da peça. O evento é nash:complete.

clique
propriedadede → paratempo
anel de pressão0 → 1 a 15% → 1 a 70% → 0700ms

A entrada uma vez

Opacidade 0 → 1 e scale 0,96 → 1 em 420ms, com `backwards`: o botão chega, não pisca.

propriedadede → paratempo
opacidade · scale0 → 1 · 0,96 → 1420ms

Uso

Dois arquivos do kit. Carregar o JS basta: todo .nash-button da página é completado e montado sozinho; o que a página cria depois, mount() ou mountAll(escopo).

<link rel="stylesheet" href="css/nash-button.css" />   ← depois de nash-componentes.css
<button class="nash-button" data-emphasis="primary">Criar imagem<span class="nash-button-meta">1 crédito</span></button>
<button class="nash-button">Cancelar</button>
<script src="js/nash-button.js"></script>

const botao = NashButton.mount('#criar', {
  label: 'Criar imagem',                  // o rótulo (.nash-button-label); sem ele, o texto que a página escreveu
  meta: '1 crédito',                      // o meta text (.nash-button-meta), opcional
  size: 'large',                          // data-size: small · medium (padrão) · large
  emphasis: 'primary',                    // data-emphasis: primary · secondary (padrão) · ghost
  toggle: true,                           // o clique alterna aria-pressed e emite nash:toggle
  onToggle(pressed, b) {}
})
botao.setPressed(true)                     // aria-pressed: accent + halo + aura
botao.setBusy(true)                        // aria-busy: o arco de 1,8s; o clique é segurado
botao.complete()                           // o anel acende, segura e apaga em 700ms; emite nash:complete
botao.setLabel('Desconectar')              // escreve o rótulo sem levar a anatomia
botao.setMeta('')                          // tira o meta text
botao.el.addEventListener('nash:toggle', (e) => e.detail)   // { pressed }

// com ícone, antes ou depois do texto; a parte .nash-icon-fill enche ao ligar:
<button class="nash-button" aria-pressed="false"><svg class="nash-icon" viewBox="0 0 24 24">…</svg>Ditar</button>

// variante congelada, pra documentação — não responde ao ponteiro, o arco parado:
<button class="nash-button" data-state="hover" data-emphasis="primary">Criar imagem</button>

// no botão:  data-size="small|medium|large"  · data-emphasis="primary|secondary|ghost"  · data-mode="chat|voz|design|imagem|social"  · aria-pressed · aria-busy · disabled
// tokens:    --nash-button-accent  · --nash-button-arc-a / -b (o par do arco e do anel de pressão)  · --nash-button-height (densidade de tela)  · --nash-button-padding  · --nash-button-radius  · --nash-button-icon-size  · --nash-button-time-scale
// na família:  --nash-motion-scale: 4  (câmera lenta)  · [data-motion="reduced"]

Decisões