Nash Icon Button
← Design system · Componentes N.A.S.H. DS Icon Button 327:754

Icon Button

A casca circular para qualquer ação com ícone: Small 56 com ícone de 24, Large 112 com o poço de 64 e ícone de 32. Quatro variantes desenhadas (Small Default, Hover, Pressed; Large Default) e os estados que um botão precisa além delas: ligado (aria-pressed), ocupado (aria-busy), aberto (aria-expanded), foco pelo teclado, desabilitado. O accent é o do modo, a mesma tabela do Tab Bar e do Text Input. Os nomes são os do mapa de vocabulário.

modo no ar: Chatúltimo gesto: nenhumpasse o cursor · aperte · o + abre · o microfone liga · o airplay ocupa

As quatro variantes

O quadro do Figma, congelado: não respondem ao ponteiro. Size=Small com State=Default, Hover e Pressed; Size=Large só com Default, como a referência desenhou. Em código, data-size e data-state.

Small · Default Small · Hover Small · Pressed Large · Default

Anatomia

Small ligado e Large em repouso, ampliados 1,35×. Numerado é o que o CSS desenha; cotado é o que o Figma mede.

Small 56 · raio 28 · ícone 24 Large 112 · raio 56 · poço 64 · ícone 32 · 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-placa, -hover, -pressed). Raio 50%.
  2. Os anéis, 1,5px por dentro.Branco 15 › 6 › 2 › 0 nos três estados do Figma; accent 45 › 18 › 6 › 0 quando ligado, ocupado ou em foco pelo teclado. A mesma máscara das duas peças anteriores.
  3. O poço.No Large, 64 de branco 8%: o icon-inner-container do Figma. No Small existe com o tamanho do ícone e sem fill, pra anatomia ser uma só.
  4. O ícone.24 no Small, 32 no Large, branco, traço 1,5 do .nash-icon do kit. Ligado toma o accent com drop-shadow de 8px e a parte .nash-icon-fill enche (a cápsula do mic); aberto gira 135° com mola; com data-icon-motion inclina 15° ou cresce 5% no hover.
  5. A luz do cursor.Névoa de 90% da casca no accent a 12% e o anel aceso no ponto mais perto do ponteiro. Só existe com o ponteiro em cima; mais forte apertada ou ligada.
  6. A aura.Um elemento próprio (i.nash-icon-button-halo) meia casca maior que a casca, com um degradê radial do accent (48% na borda, 20% a 70%, 0 no fim) sob uma máscara em anel. Existe porque box-shadow não tem borda de dentro: ligar abre a borda de fora; desligar move a borda 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:754O kit / as duas peçasA peça
Fill Default rgba(13,15,18,.32) · Hover rgba(31,33,40,.4) · Pressed rgba(8,10,13,.32)--nash-placa · --nash-placa-hover · --nash-placa-pressediguais, byte a byte — os três tokens já existiam
Stroke 1,5 branco 15 › 6 › 2 › 0 por dentro, nos três estadosanel branco por máscara (.nash-surface, .nash-tab, .nash-text-input)o mesmo anel, a 1 nos três estados. O Text Input o tem a 0,5 no repouso porque o Figma dele não desenha stroke no Default
Size=Small 56 (raio 28) · Size=Large 112 (raio 56).nash-icon-button era 44 (--nash-alvo-solto); .nash-icon-button--small, 3656 e 112 por data-size="small|large"; raio 50%. --nash-icon-button-size pra densidade de tela (36 no Project Builder). O modificador BEM saiu: variante é data-<eixo>
Icon/*/24 no Small, Icon/*/32 no Large, brancoo kit tinha 18; o Text Input usa 20 a 60%24 e 32, branco. O ícone que a página escreve (.nash-icon) ou data-icon="close|airplay|plus|mic|play|pause|previous|next"
icon-inner-container: 64, branco 8%, raio 32, só no Largenada.nash-icon-button-well nos dois tamanhos; no Small com o tamanho do ícone e sem fill
State=Pressedo kit tem pressão de 100ms; o Text Input mapeou o Pressed ao focoPressed = :active, scale 0,96 em 100ms, solta em 160. Num botão a pressão não fica; o que fica é ARIA
Large só Default—o Large recebe o Hover e o Pressed do Small (mesmas placas). Pendente no Figma
Sem ligado, ocupado, aberto, foco, desabilitadoo kit lia aria-pressed por um efeito de seleção, e fazia ocupado por classe (.nash-arco)aria-pressed (accent + halo + onda + aura, o ícone enche, o poço pula, 540ms; depois respira; desligar em 600, a aura comida de dentro pra fora), aria-busy (arco de 1,8s; o clique é segurado), aria-expanded (135° com mola, onda no poço), :focus-visible (anel + outline), :disabled (50%). Estado é ARIA; nenhum data-estado
—.nash-giro (× inclina 15°) e .nash-realce (ícone cresce 5%)data-icon-motion="tilt|scale", o eixo do vocabulário; vive dentro da peça
Nomes: Size, State, Icon/XCircle/24, icon-inner-container—data-size, data-state, ICONS.close, .nash-icon-button-well. O identificador é do mapa (docs/vocabulario-mapa.json): inglês, parte nash-<bloco>-<parte>, token --nash-icon-button-*, runtime --nash-runtime-*, evento nash:toggle
Escala de tempo--nash-tab-escala, --nash-text-input-escala, --nash-escala--nash-icon-button-time-scale, com --nash-escala da família como fallback
Movimento reduzido.nash-reduzido[data-motion="reduced"] num ancestral, o nome do vocabulário; as duas peças anteriores ainda leem .nash-reduzido

O que se move

Toda curva é a de saída do kit, menos uma: a mola do abrir. Dois laços, cada um preso a um estado: a respiração de aria-pressed (um número, --nash-icon-button-breath, que o halo da borda, a aura e o poço leem; ao desligar ele pausa onde está em vez de sumir) e o giro de aria-busy.

Ponteiro entra hover

A placa sobe de 32% a 40% e a luz do cursor acende. O anel branco já está a 1: o Figma o desenha nos três estados.

passe o cursor pelos dois
propriedadede → paratempo
placa#0D0F12 32% → #1F2128 40%180ms
luz do cursor0 → 1260ms

A luz do cursor vidro

Uma névoa de 90% da casca 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 casca
camadacortempo
névoaaccent 12% (ligado 18%, apertada 24%), 90% da casca260ms · segue em 70
anelaccent 70%, 55% da casca260ms

Pressão o Pressed do Figma

A placa desce pro #080A0D e a casca assenta a 0,96 em 100ms; solta em 160. Não fica: o que fica é aria-pressed.

segure o botão apertado
propriedadede → paratempo
placa→ #080A0D 32%180ms
cascascale 1 → 0,96100ms · solta em 160
luz do cursor12% → 24%260ms

Ligar e desligar aria-pressed

Ligar: a placa desce pro #080A0D, o anel branco apaga, o ícone toma o accent em 140 e enche em 260 (a parte .nash-icon-fill: a cápsula do mic), o poço pula 18% 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, aura e poço, 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 — a borda de dentro da máscara caminha até a de fora enquanto a luz cai — 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

O anel de accent vira um arco que dá a volta em 1,8s; o ícone baixa a 60%; o clique é segurado. Único laço da peça; termina com o estado.

propriedadede → paratempo
anel de accentgradiente → arco cônico, --nash-runtime-spin 0 → 360°laço 1800ms
ícone1 → 0,6140ms

Abrir aria-expanded

O ícone gira 135° em 420ms pela mola (passa do alvo e volta): o + vira ×. A placa desce à apertada e do poço sai uma onda no accent. Fechar desfaz o giro pela mesma mola. A página escreve o atributo; a peça o lê.

clique pra abrir e fechar
propriedadede → paratempo
íconerotate 0 → 135°, cubic-bezier(0.34, 1.56, 0.64, 1)420ms
placa→ #080A0D 32%180ms
poçoonda: anel de accent 45%, spread 0 → 16px, apagando420ms

O ícone no hover data-icon-motion

tilt inclina 15° (o × de fechar: "vai fechar"); scale cresce 5% ("esse ícone é a ação"). Um ou outro, nunca os dois. Eram .nash-giro e .nash-realce.

tilt à esquerda, scale à direita
eixode → paratempo
tiltrotate 0 → 15°140ms
scalescale 1 → 1,05140ms

A entrada uma vez

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

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

Uso

Dois arquivos do kit. Carregar o JS basta: todo .nash-icon-button da página é completado e montado sozinho.

<link rel="stylesheet" href="css/nash-icon-button.css" />   ← depois de nash-componentes.css
<button class="nash-icon-button" data-icon="close" aria-label="Fechar"></button>
<script src="js/nash-icon-button.js"></script>

const botao = NashIconButton.mount('#fechar', {
  icon: 'close',                          // close · airplay · plus · mic · play · pause · previous · next; ou o <svg class="nash-icon"> da página
  label: 'Fechar',                        // aria-label
  size: 'large',                          // data-size: small (padrão) · large
  iconMotion: 'tilt',                     // data-icon-motion: tilt · scale
  toggle: true,                           // o clique alterna aria-pressed e emite nash:toggle
  onToggle(pressed, b) {}
})
botao.setPressed(true)                     // aria-pressed: accent + halo
botao.setBusy(true)                        // aria-busy: o arco; o clique é segurado
botao.setIcon('pause')
botao.el.addEventListener('nash:toggle', (e) => e.detail)   // { pressed }

// a página escreve o ícone; o JS completa a luz e o poço:
<button class="nash-icon-button" aria-label="Tocar"><svg class="nash-icon" viewBox="0 0 24 24">…</svg></button>

// variante congelada, pra documentação — não responde ao ponteiro:
<button class="nash-icon-button" data-state="hover" data-icon="close"></button>

// no ícone da página:  <rect class="nash-icon-fill" …>  ← a parte que enche ao ligar
// no botão:  data-size="small|large"  · data-icon-motion="tilt|scale"  · data-mode="chat|voz|design|imagem|social"  · aria-pressed · aria-busy · aria-expanded
// tokens:    --nash-icon-button-accent  · --nash-icon-button-size (36 pra densidade de tela)  · --nash-icon-button-icon-size  · --nash-icon-button-time-scale
// na família:  --nash-escala: 4  (câmera lenta)  · [data-motion="reduced"]

Decisões