Cada componente tem uma personalidade que você pode mudar: a mola com que ele se move, o que um botão faz sob o seu dedo, como diálogos e menus entram em cena, o formato e o tamanho dos cantos e quanto espaço ele ocupa. Cada traço é um atributo para tudo o que está dentro de um elemento, ou um input para um único componente.

Um atributo, uma subárvore inteira

Coloque os atributos data-nui-* no <body> para a aplicação inteira, ou em qualquer elemento para uma parte dela. O mais próximo vence, por isso eles podem ser aninhados. Eles só definem propriedades personalizadas CSS, então funcionam do mesmo jeito com qualquer framework, ou sem nenhum.

customize.html
<body data-nui-motion="bouncy" data-nui-corners="squircle">
<!-- Everything here bounces and has squircle corners… -->
<main data-nui-press="squish" data-nui-density="compact">
<!-- …buttons in here squish, and controls are compact… -->
</main>
<aside data-nui-motion="none" data-nui-radius="none">
<!-- …and nothing in here moves or has rounded corners. -->
</aside>
</body>

Um único componente

No Angular, nuiButton, nuiDialog e nuiMenu aceitam os mesmos valores como inputs. Os inputs que você não definir seguem os atributos ao redor do componente.

customize-inputs.html
<button nuiButton press="rubber" motion="elastic">Boing</button>

<dialog nuiDialog [(open)]="editing" enter="flip" corners="squircle">…</dialog>

<button nuiButton [nuiMenuTrigger]="actions">Actions</button>
<div nuiMenu #actions="ngMenu" enter="unfold" motion="mechanical">…</div>

Molas compiladas para CSS

O movimento é física de molas: rigidez, amortecimento e massa em vez de uma duração e uma curva. O compilador de tokens resolve cada mola e a escreve no CSS como o tempo que ela leva para se estabilizar e uma função de easing linear(), então ela roda no compositor sem JavaScript. Seis molas vêm como tokens, de --nui-spring-snappy a --nui-spring-mechanical, e --nui-motion guarda a que está em uso.

Qualquer outra mola está a um input de distância. O Angular a compila em tempo de execução com o mesmo solver, e springTransition() entrega o CSS para os seus próprios elementos.

customize-spring.ts
import { springTransition } from '@needless-ui/angular';

// In a template, any spring is an input:
// <button nuiButton [spring]="{ stiffness: 900, damping: 12 }">Save</button>

// Anywhere else, compile it yourself:
const wobbly = springTransition({ stiffness: 120, damping: 4, mass: 1.2 });
// '4152ms linear(0, 0.014 0.41%, …, 1)'

const card = document.querySelector<HTMLElement>('.card')!;
card.style.transition = `transform ${wobbly}`;

Qualquer meio-termo

Os presets são atalhos. Para qualquer outra coisa, defina você mesmo as propriedades personalizadas: qualquer transformação para --nui-press e --nui-enter, qualquer número para --nui-radius-scale e --nui-density.

customize.css
.checkout {
--nui-motion: var(--nui-spring-jelly);
--nui-press: scale(0.92) rotate(-2deg);
--nui-enter: translateY(100%);
--nui-radius-scale: 1.5;
--nui-density: 1.1;
}

Acessibilidade

Quando o sistema pede menos movimento, as molas se tornam instantâneas, e os efeitos ao pressionar e as animações de entrada param de se mover. A densidade nunca deixa um controle abaixo do tamanho mínimo de alvo de 24 px das WCAG 2.2, e nenhum preset mexe nas cores, então todas as verificações de contraste continuam valendo. Navegadores sem corner-shape desenham todos os cantos arredondados.