У каждого компонента есть характер, и его можно менять: пружина, которая задаёт движение, реакция кнопки под пальцем, появление диалогов и меню, форма и размер углов, а также то, сколько места занимает компонент. Каждый из этих параметров задаётся одним атрибутом для всего, что находится внутри элемента, или одним входным свойством для отдельного компонента.
Один атрибут на всё поддерево
Задайте атрибуты data-nui-* на <body> для всего приложения или на любом элементе — для отдельной его части. Действует ближайший атрибут, поэтому их можно вкладывать друг в друга. Атрибуты лишь задают CSS-переменные, так что работают одинаково с любым фреймворком и без него.
<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>Отдельный компонент
В Angular nuiButton, nuiDialog и nuiMenu принимают те же значения через входные свойства. Незаданные входные свойства берут значения из атрибутов выше по дереву.
<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>Пружины, скомпилированные в CSS
Движение подчиняется физике пружины: вместо длительности и кривой — жёсткость, затухание и масса. Компилятор токенов рассчитывает каждую пружину и записывает её в CSS как время, за которое она успокаивается, и функцию плавности linear(), поэтому анимация выполняется в потоке композитора без JavaScript. В комплекте шесть пружин в виде токенов, от --nui-spring-snappy до --nui-spring-mechanical, а в --nui-motion хранится текущая.
Для любой другой пружины достаточно одного входного свойства. Angular компилирует её во время выполнения тем же решателем, а springTransition() даёт CSS для ваших собственных элементов.
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}`;Любые промежуточные значения
Пресеты — лишь удобные сокращения. Для всего остального задайте CSS-переменные сами: любую трансформацию для --nui-press и --nui-enter, любое число для --nui-radius-scale и --nui-density.
.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;
}Доступность
Когда система просит меньше анимации, пружины срабатывают мгновенно, а эффекты нажатия и появления перестают двигаться. Плотность никогда не делает элемент управления меньше минимального размера области нажатия по WCAG 2.2 (24px), а пресеты не меняют цвета, поэтому все проверки контраста остаются в силе. Браузеры без поддержки corner-shape рисуют все углы скруглёнными.