لكل مكوّن شخصية يمكنك تغييرها: النابض الذي يتحرك به، وما يفعله الزر تحت إصبعك، وطريقة ظهور مربعات الحوار والقوائم، وشكل زواياها وحجمها، والمساحة التي تشغلها. وكلٌّ منها سمة واحدة تسري على كل ما بداخل عنصر، أو مُدخَل واحد لمكوّن بعينه.
سمة واحدة لشجرة فرعية كاملة
ضع سمات 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()، فتعمل الحركة على المُركِّب (compositor) دون 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}`;أي شيء بين هذا وذاك
الإعدادات المسبقة مجرد اختصارات. ولأي شيء آخر، اضبط الخصائص المخصصة بنفسك: أي تحويل (transform) لـ --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;
}إمكانية الوصول
عندما يطلب النظام تقليل الحركة، تتحول النوابض إلى انتقال فوري، وتتوقف حركة الضغط والظهور. ولا تُصغِّر الكثافة أي عنصر تحكم أبدًا إلى ما دون حجم الهدف البالغ 24 بكسل في WCAG 2.2، ولا يمسّ أي إعداد مسبق الألوان، لذا تبقى كل فحوص التباين صالحة. أما المتصفحات التي لا تدعم corner-shape فترسم كل الزوايا مستديرة.