每个组件都有你可以改变的个性:驱动它运动的弹簧、按钮在你指尖下的反应、对话框和菜单的入场方式、边角的形状和大小,以及它们占用的空间。每一项都可以用一个属性作用于某个元素内的所有内容,也可以用一个输入属性只作用于单个组件。

一个属性,作用于整棵子树

data-nui-* 属性加在 <body> 上会作用于整个应用,加在任意元素上则只作用于其中一部分。离得最近的属性优先生效,因此可以嵌套使用。它们只设置 CSS 自定义属性,所以无论使用哪种框架,甚至不用框架,效果都完全一样。

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>

单个组件

在 Angular 中,nuiButtonnuiDialognuiMenu 以输入属性的形式接受相同的值。未设置的输入属性会沿用外层元素上的属性。

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>

编译为 CSS 的弹簧

动效基于弹簧物理:用刚度、阻尼和质量取代时长和曲线。token 编译器会求解每个弹簧,并将其写入 CSS,表示为稳定所需的时长和一个 linear() 缓动函数,因此动画在合成器线程上运行,无需 JavaScript。内置六种弹簧 token,从 --nui-spring-snappy--nui-spring-mechanical--nui-motion 则保存当前使用的那一种。

想用其他弹簧,只需设置一个输入属性。Angular 会在运行时用同一个求解器编译它,而 springTransition() 能为你自己的元素生成对应的 CSS。

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

预设之外的任意值

预设只是快捷方式。其他任何效果,都可以自己设置 CSS 自定义属性来实现:--nui-press--nui-enter 可以使用任意 transform,--nui-radius-scale--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;
}

无障碍

当系统要求减少动态效果时,弹簧会瞬间完成,按压和入场效果也不再运动。无论密度如何设置,控件都不会小于 WCAG 2.2 规定的 24px 目标尺寸;而且没有任何预设会改动颜色,因此所有对比度检查依然成立。不支持 corner-shape 的浏览器会把所有边角都绘制成圆角。