Ogni componente ha una personalità che puoi cambiare: la molla con cui si muove, cosa fa un pulsante sotto il tuo dito, come entrano in scena dialog e menu, la forma e la dimensione degli angoli e quanto spazio occupa. Ognuno di questi tratti è un attributo per tutto ciò che sta dentro un elemento, o un input per un singolo componente.

Un attributo, un intero sottoalbero

Metti gli attributi data-nui-* su <body> per tutta l’app, o su un elemento qualsiasi per una sola parte. Vince il più vicino, perciò si possono annidare. Impostano solo custom property CSS, quindi funzionano allo stesso modo con qualsiasi framework, o anche senza.

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>

Un solo componente

In Angular, nuiButton, nuiDialog e nuiMenu accettano gli stessi valori come input. Gli input che non imposti seguono gli attributi intorno al 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>

Molle compilate in CSS

Il movimento è fisica delle molle: rigidezza, smorzamento e massa al posto di una durata e di una curva. Il compilatore dei token risolve ogni molla e la scrive nel CSS come tempo di assestamento più un easing linear(), così gira sul compositor senza JavaScript. Sei molle sono incluse come token, da --nui-spring-snappy a --nui-spring-mechanical, e --nui-motion contiene quella in uso.

Qualsiasi altra molla è a un input di distanza. Angular la compila a runtime con lo stesso risolutore, e springTransition() ti dà il CSS per i tuoi elementi.

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}`;

Tutte le vie di mezzo

I preset sono scorciatoie. Per tutto il resto imposta tu le custom property: qualsiasi trasformazione per --nui-press e --nui-enter, qualsiasi numero per --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;
}

Accessibilità

Quando il sistema chiede meno animazioni, le molle diventano istantanee, mentre effetti alla pressione e animazioni di entrata restano fermi. La densità non porta mai un controllo sotto l’area di tocco minima di 24px delle WCAG 2.2, e nessun preset tocca i colori, quindi ogni verifica di contrasto resta valida. I browser senza corner-shape disegnano tutti gli angoli arrotondati.