@ai-matrx/design-system 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +244 -2
- package/README.md +15 -1
- package/dist/index.cjs +183 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +161 -8
- package/dist/index.d.ts +161 -8
- package/dist/index.js +183 -82
- package/dist/index.js.map +1 -1
- package/dist/styles.css +483 -0
- package/dist/tokens.css +30 -0
- package/package.json +1 -1
package/dist/styles.css
CHANGED
|
@@ -230,6 +230,489 @@
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
234
|
+
THE MOTION LAYER (0.10.0) — every overlay animation this package emits.
|
|
235
|
+
|
|
236
|
+
THE DOCTRINE (FEATURE.md): a primitive that leaves motion to the host has
|
|
237
|
+
not shipped motion, it has shipped a coin flip. 0.8.0 and 0.9.0 closed that
|
|
238
|
+
for Accordion and Collapsible one primitive at a time. The sweep that
|
|
239
|
+
followed found the SAME shape on ten more, and far worse than a missing
|
|
240
|
+
keyframe: every floating surface in this package — Dialog, AlertDialog,
|
|
241
|
+
Sheet, CommandDialog, Popover, DropdownMenu, ContextMenu, HoverCard,
|
|
242
|
+
Select, Tooltip — animated with `animate-in` / `animate-out` /
|
|
243
|
+
`fade-in-0` / `zoom-in-95` / `slide-in-from-*-2`. Those are not Tailwind
|
|
244
|
+
utilities. They come from the `tailwindcss-animate` plugin (or its v4
|
|
245
|
+
successor `tw-animate-css`), which is a HOST dependency this package never
|
|
246
|
+
declared and cannot declare — a Tailwind plugin is loaded by the host's CSS
|
|
247
|
+
entry, not by a node_modules package.
|
|
248
|
+
|
|
249
|
+
Measured on built output, 2026-09-07, before this file owned any of it:
|
|
250
|
+
|
|
251
|
+
matrx-frontend `@import "tw-animate-css"` in globals.css → animated
|
|
252
|
+
aidream/dashboard no plugin → 0 rules
|
|
253
|
+
aidream/workflow-studio no plugin → 0 rules
|
|
254
|
+
matrx-extend `tailwindcss-animate` in package.json but
|
|
255
|
+
NEVER LOADED (it is a Tailwind v3 plugin and
|
|
256
|
+
extend is on v4 with no `@plugin` directive)
|
|
257
|
+
→ 0 rules
|
|
258
|
+
|
|
259
|
+
Three consumers out of four. `grep -c 'animate-in\|slide-in-from'` on each
|
|
260
|
+
app's built stylesheet returned 0. Every dialog, dropdown, popover, tooltip
|
|
261
|
+
and sheet in the two aidream apps and the Chrome extension appeared
|
|
262
|
+
instantly, with no animation and no error, for as long as they existed.
|
|
263
|
+
The one host that worked, worked by accident of its own CSS entry.
|
|
264
|
+
|
|
265
|
+
So the package owns it. Below: package-defined keyframes, applied through
|
|
266
|
+
`matrx-`-prefixed classes the components put on the DOM themselves, timed
|
|
267
|
+
from `--matrx-motion-*` tokens, silenced by `prefers-reduced-motion`, and
|
|
268
|
+
asserted by `styles.test.ts` + the packed-tarball canary.
|
|
269
|
+
|
|
270
|
+
WHERE THE LINE IS. This layer owns KEYFRAME ANIMATION — motion that either
|
|
271
|
+
happens or silently does not. It deliberately does NOT own Tailwind's
|
|
272
|
+
`transition-*` / `duration-*` / `ease-*` utilities that the primitives also
|
|
273
|
+
carry (a hover colour easing, the progress bar's width, the close button's
|
|
274
|
+
opacity). Those are CORE Tailwind, present in every Tailwind host, and
|
|
275
|
+
their absence degrades to an instant-but-correct change rather than to a
|
|
276
|
+
surface that lies about its state. Re-implementing them here would mean
|
|
277
|
+
shipping a copy of Tailwind.
|
|
278
|
+
|
|
279
|
+
UNLAYERED on purpose, exactly like the accordion and collapsible rules
|
|
280
|
+
above: a host that still loads `tw-animate-css` would otherwise emit a
|
|
281
|
+
competing `animation` from `@layer utilities` and win, giving that one host
|
|
282
|
+
different motion from everyone else — the coin flip again, wearing a
|
|
283
|
+
working coat. Unlayered means every consumer gets identical motion. The
|
|
284
|
+
sanctioned escape is the `animated={false}` prop on the component, not a
|
|
285
|
+
className.
|
|
286
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
287
|
+
|
|
288
|
+
/* --- scrim ------------------------------------------------------------- */
|
|
289
|
+
@keyframes matrx-fade-in {
|
|
290
|
+
from {
|
|
291
|
+
opacity: 0;
|
|
292
|
+
}
|
|
293
|
+
to {
|
|
294
|
+
opacity: 1;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
@keyframes matrx-fade-out {
|
|
298
|
+
from {
|
|
299
|
+
opacity: 1;
|
|
300
|
+
}
|
|
301
|
+
to {
|
|
302
|
+
opacity: 0;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
.matrx-motion-overlay[data-state="open"] {
|
|
306
|
+
animation: matrx-fade-in var(--matrx-motion-duration-base)
|
|
307
|
+
var(--matrx-motion-ease-out);
|
|
308
|
+
}
|
|
309
|
+
.matrx-motion-overlay[data-state="closed"] {
|
|
310
|
+
animation: matrx-fade-out var(--matrx-motion-duration-base)
|
|
311
|
+
var(--matrx-motion-ease-in);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* --- centred dialog card ----------------------------------------------
|
|
315
|
+
CENTRING AND MOTION ARE TWO DIFFERENT CSS PROPERTIES HERE, ON PURPOSE.
|
|
316
|
+
0.10.0 centred the card with `translate-x-[-50%] translate-y-[-50%]`
|
|
317
|
+
utilities and RE-STATED that centring inside the keyframes, on the
|
|
318
|
+
assumption an animation of `transform` replaces whatever positioned the
|
|
319
|
+
element. That assumption is a Tailwind v3 assumption, and it shipped a
|
|
320
|
+
live regression:
|
|
321
|
+
|
|
322
|
+
Tailwind v3 `translate-x-[-50%]` -> `transform: translate(…)` (replaced)
|
|
323
|
+
Tailwind v4 `translate-x-[-50%]` -> `translate: -50% -50%` (COMPOSES)
|
|
324
|
+
|
|
325
|
+
`translate` is an independent transform property: per spec it is applied
|
|
326
|
+
IN ADDITION to `transform`, not replaced by it. So on every v4 host the
|
|
327
|
+
card was centred twice for the animation's whole duration and snapped back
|
|
328
|
+
at the end. Measured live, 2560x1289, resting rect x=128 y=32:
|
|
329
|
+
currentTime=0 -> x=-966 y=-525 (off the top-left of the viewport);
|
|
330
|
+
`el.style.translate='none'` mid-animation -> x=137 y=41, i.e. resting.
|
|
331
|
+
Three of four consumers regressed (aidream/dashboard, workflow-studio,
|
|
332
|
+
matrx-extend went from instant-and-centred to flying in from off-screen).
|
|
333
|
+
|
|
334
|
+
The fix does not pick a Tailwind version. The package owns the centring
|
|
335
|
+
itself, in the `translate` property, on `.matrx-dialog-centered` below —
|
|
336
|
+
so it reads identically under v3 and v4 hosts — and the keyframes express
|
|
337
|
+
ONLY the delta: opacity, and a 2% rise scaled up from 95% carried by
|
|
338
|
+
`transform`, which now has no other job. Resting state is
|
|
339
|
+
`translate: -50% -50%; transform: none`, byte-identical to 0.10.0's
|
|
340
|
+
rendered rect. The two never restate each other again, and
|
|
341
|
+
`motion.test.tsx` fails the build if a centred surface goes back to
|
|
342
|
+
wearing a non-zero translate utility. */
|
|
343
|
+
.matrx-dialog-centered {
|
|
344
|
+
translate: -50% -50%;
|
|
345
|
+
}
|
|
346
|
+
@keyframes matrx-dialog-in {
|
|
347
|
+
from {
|
|
348
|
+
opacity: 0;
|
|
349
|
+
transform: translateY(2%) scale(0.95);
|
|
350
|
+
}
|
|
351
|
+
to {
|
|
352
|
+
opacity: 1;
|
|
353
|
+
transform: none;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
@keyframes matrx-dialog-out {
|
|
357
|
+
from {
|
|
358
|
+
opacity: 1;
|
|
359
|
+
transform: none;
|
|
360
|
+
}
|
|
361
|
+
to {
|
|
362
|
+
opacity: 0;
|
|
363
|
+
transform: translateY(2%) scale(0.95);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
.matrx-motion-dialog[data-state="open"] {
|
|
367
|
+
animation: matrx-dialog-in var(--matrx-motion-duration-base)
|
|
368
|
+
var(--matrx-motion-ease-out);
|
|
369
|
+
}
|
|
370
|
+
.matrx-motion-dialog[data-state="closed"] {
|
|
371
|
+
animation: matrx-dialog-out var(--matrx-motion-duration-base)
|
|
372
|
+
var(--matrx-motion-ease-in);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/* --- edge sheets -------------------------------------------------------
|
|
376
|
+
Five named classes rather than one `data-side` rule, because a Sheet's side
|
|
377
|
+
is a `sheetVariants` variant on the element's own class list — Radix
|
|
378
|
+
publishes no `data-side` on a Dialog-based sheet. The mobile Dialog /
|
|
379
|
+
CommandDialog bottom sheet reuses `-bottom`. */
|
|
380
|
+
@keyframes matrx-slide-in-top {
|
|
381
|
+
from {
|
|
382
|
+
transform: translateY(-100%);
|
|
383
|
+
}
|
|
384
|
+
to {
|
|
385
|
+
transform: translateY(0);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
@keyframes matrx-slide-out-top {
|
|
389
|
+
from {
|
|
390
|
+
transform: translateY(0);
|
|
391
|
+
}
|
|
392
|
+
to {
|
|
393
|
+
transform: translateY(-100%);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
@keyframes matrx-slide-in-bottom {
|
|
397
|
+
from {
|
|
398
|
+
transform: translateY(100%);
|
|
399
|
+
}
|
|
400
|
+
to {
|
|
401
|
+
transform: translateY(0);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
@keyframes matrx-slide-out-bottom {
|
|
405
|
+
from {
|
|
406
|
+
transform: translateY(0);
|
|
407
|
+
}
|
|
408
|
+
to {
|
|
409
|
+
transform: translateY(100%);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
@keyframes matrx-slide-in-left {
|
|
413
|
+
from {
|
|
414
|
+
transform: translateX(-100%);
|
|
415
|
+
}
|
|
416
|
+
to {
|
|
417
|
+
transform: translateX(0);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
@keyframes matrx-slide-out-left {
|
|
421
|
+
from {
|
|
422
|
+
transform: translateX(0);
|
|
423
|
+
}
|
|
424
|
+
to {
|
|
425
|
+
transform: translateX(-100%);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
@keyframes matrx-slide-in-right {
|
|
429
|
+
from {
|
|
430
|
+
transform: translateX(100%);
|
|
431
|
+
}
|
|
432
|
+
to {
|
|
433
|
+
transform: translateX(0);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
@keyframes matrx-slide-out-right {
|
|
437
|
+
from {
|
|
438
|
+
transform: translateX(0);
|
|
439
|
+
}
|
|
440
|
+
to {
|
|
441
|
+
transform: translateX(100%);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
.matrx-motion-sheet-top[data-state="open"] {
|
|
445
|
+
animation: matrx-slide-in-top var(--matrx-motion-duration-sheet)
|
|
446
|
+
var(--matrx-motion-ease-out);
|
|
447
|
+
}
|
|
448
|
+
.matrx-motion-sheet-top[data-state="closed"] {
|
|
449
|
+
animation: matrx-slide-out-top var(--matrx-motion-duration-slow)
|
|
450
|
+
var(--matrx-motion-ease-in);
|
|
451
|
+
}
|
|
452
|
+
.matrx-motion-sheet-bottom[data-state="open"] {
|
|
453
|
+
animation: matrx-slide-in-bottom var(--matrx-motion-duration-sheet)
|
|
454
|
+
var(--matrx-motion-ease-out);
|
|
455
|
+
}
|
|
456
|
+
.matrx-motion-sheet-bottom[data-state="closed"] {
|
|
457
|
+
animation: matrx-slide-out-bottom var(--matrx-motion-duration-slow)
|
|
458
|
+
var(--matrx-motion-ease-in);
|
|
459
|
+
}
|
|
460
|
+
.matrx-motion-sheet-left[data-state="open"] {
|
|
461
|
+
animation: matrx-slide-in-left var(--matrx-motion-duration-sheet)
|
|
462
|
+
var(--matrx-motion-ease-out);
|
|
463
|
+
}
|
|
464
|
+
.matrx-motion-sheet-left[data-state="closed"] {
|
|
465
|
+
animation: matrx-slide-out-left var(--matrx-motion-duration-slow)
|
|
466
|
+
var(--matrx-motion-ease-in);
|
|
467
|
+
}
|
|
468
|
+
.matrx-motion-sheet-right[data-state="open"] {
|
|
469
|
+
animation: matrx-slide-in-right var(--matrx-motion-duration-sheet)
|
|
470
|
+
var(--matrx-motion-ease-out);
|
|
471
|
+
}
|
|
472
|
+
.matrx-motion-sheet-right[data-state="closed"] {
|
|
473
|
+
animation: matrx-slide-out-right var(--matrx-motion-duration-slow)
|
|
474
|
+
var(--matrx-motion-ease-in);
|
|
475
|
+
}
|
|
476
|
+
/* A `side="center"` Sheet has no edge to come from, so it fades like a
|
|
477
|
+
dialog scrim rather than sliding from nowhere. */
|
|
478
|
+
.matrx-motion-sheet-center[data-state="open"] {
|
|
479
|
+
animation: matrx-fade-in var(--matrx-motion-duration-sheet)
|
|
480
|
+
var(--matrx-motion-ease-out);
|
|
481
|
+
}
|
|
482
|
+
.matrx-motion-sheet-center[data-state="closed"] {
|
|
483
|
+
animation: matrx-fade-out var(--matrx-motion-duration-slow)
|
|
484
|
+
var(--matrx-motion-ease-in);
|
|
485
|
+
}
|
|
486
|
+
/* The mobile Dialog / CommandDialog bottom sheet: slides AND fades, at the
|
|
487
|
+
dialog's 200ms rather than the Sheet's 500ms, because it is a dialog
|
|
488
|
+
wearing sheet geometry and it opens from a tap, not from a nav gesture. */
|
|
489
|
+
@keyframes matrx-bottom-sheet-in {
|
|
490
|
+
from {
|
|
491
|
+
opacity: 0;
|
|
492
|
+
transform: translateY(100%);
|
|
493
|
+
}
|
|
494
|
+
to {
|
|
495
|
+
opacity: 1;
|
|
496
|
+
transform: translateY(0);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
@keyframes matrx-bottom-sheet-out {
|
|
500
|
+
from {
|
|
501
|
+
opacity: 1;
|
|
502
|
+
transform: translateY(0);
|
|
503
|
+
}
|
|
504
|
+
to {
|
|
505
|
+
opacity: 0;
|
|
506
|
+
transform: translateY(100%);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
.matrx-motion-bottom-sheet[data-state="open"] {
|
|
510
|
+
animation: matrx-bottom-sheet-in var(--matrx-motion-duration-base)
|
|
511
|
+
var(--matrx-motion-ease-out);
|
|
512
|
+
}
|
|
513
|
+
.matrx-motion-bottom-sheet[data-state="closed"] {
|
|
514
|
+
animation: matrx-bottom-sheet-out var(--matrx-motion-duration-base)
|
|
515
|
+
var(--matrx-motion-ease-in);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/* --- poppers -----------------------------------------------------------
|
|
519
|
+
Popover, DropdownMenu, ContextMenu, HoverCard, Select and Tooltip all
|
|
520
|
+
position through Radix's popper, which publishes `data-side` on the content
|
|
521
|
+
and `--radix-popper-transform-origin` — the point on the surface that faces
|
|
522
|
+
the trigger. Reading that origin is a correctness fix the `zoom-in-95`
|
|
523
|
+
original never had: the surface now grows OUT OF its anchor instead of out
|
|
524
|
+
of its own centre, so a menu below a button no longer appears to expand
|
|
525
|
+
upward into the button.
|
|
526
|
+
|
|
527
|
+
`data-side` says where the surface sits, so it travels FROM the trigger:
|
|
528
|
+
a surface on the `bottom` starts slightly above where it lands. Exit fades
|
|
529
|
+
and shrinks without sliding — matching the originals, and the right
|
|
530
|
+
behaviour, since a surface leaving should not appear to move somewhere. */
|
|
531
|
+
@keyframes matrx-popper-in-from-top {
|
|
532
|
+
from {
|
|
533
|
+
opacity: 0;
|
|
534
|
+
transform: scale(0.95) translateY(calc(-1 * var(--matrx-motion-popper-travel)));
|
|
535
|
+
}
|
|
536
|
+
to {
|
|
537
|
+
opacity: 1;
|
|
538
|
+
transform: scale(1) translateY(0);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
@keyframes matrx-popper-in-from-bottom {
|
|
542
|
+
from {
|
|
543
|
+
opacity: 0;
|
|
544
|
+
transform: scale(0.95) translateY(var(--matrx-motion-popper-travel));
|
|
545
|
+
}
|
|
546
|
+
to {
|
|
547
|
+
opacity: 1;
|
|
548
|
+
transform: scale(1) translateY(0);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
@keyframes matrx-popper-in-from-left {
|
|
552
|
+
from {
|
|
553
|
+
opacity: 0;
|
|
554
|
+
transform: scale(0.95) translateX(calc(-1 * var(--matrx-motion-popper-travel)));
|
|
555
|
+
}
|
|
556
|
+
to {
|
|
557
|
+
opacity: 1;
|
|
558
|
+
transform: scale(1) translateX(0);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
@keyframes matrx-popper-in-from-right {
|
|
562
|
+
from {
|
|
563
|
+
opacity: 0;
|
|
564
|
+
transform: scale(0.95) translateX(var(--matrx-motion-popper-travel));
|
|
565
|
+
}
|
|
566
|
+
to {
|
|
567
|
+
opacity: 1;
|
|
568
|
+
transform: scale(1) translateX(0);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
@keyframes matrx-popper-out {
|
|
572
|
+
from {
|
|
573
|
+
opacity: 1;
|
|
574
|
+
transform: scale(1);
|
|
575
|
+
}
|
|
576
|
+
to {
|
|
577
|
+
opacity: 0;
|
|
578
|
+
transform: scale(0.95);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
/* THE RIGHT VARIABLE, PER PRIMITIVE. Radix publishes the anchor-facing origin
|
|
582
|
+
under the shared popper name AND under a per-primitive alias, and which one
|
|
583
|
+
is present depends on the primitive — `Select` sets
|
|
584
|
+
`--radix-select-content-transform-origin`, `Tooltip` sets
|
|
585
|
+
`--radix-tooltip-content-transform-origin`, and so on. Reusing one
|
|
586
|
+
primitive's variable on another is the exact silent death census row 19f
|
|
587
|
+
recorded (accordion keyframes on a collapsible panel), so this states the
|
|
588
|
+
whole chain rather than betting on one name. If none resolves, the origin
|
|
589
|
+
falls back to the element's centre — degraded, never broken. */
|
|
590
|
+
.matrx-motion-popper {
|
|
591
|
+
transform-origin: var(
|
|
592
|
+
--radix-popper-transform-origin,
|
|
593
|
+
var(
|
|
594
|
+
--radix-select-content-transform-origin,
|
|
595
|
+
var(
|
|
596
|
+
--radix-tooltip-content-transform-origin,
|
|
597
|
+
var(
|
|
598
|
+
--radix-dropdown-menu-content-transform-origin,
|
|
599
|
+
var(
|
|
600
|
+
--radix-context-menu-content-transform-origin,
|
|
601
|
+
var(
|
|
602
|
+
--radix-hover-card-content-transform-origin,
|
|
603
|
+
var(--radix-popover-content-transform-origin, center)
|
|
604
|
+
)
|
|
605
|
+
)
|
|
606
|
+
)
|
|
607
|
+
)
|
|
608
|
+
)
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
/* A surface rendered BELOW the trigger enters from above it, and so on. The
|
|
612
|
+
bare `[data-state=open]` rule is the fallback for the frame before the
|
|
613
|
+
popper has measured a side (and for `Select` in `item-aligned` position,
|
|
614
|
+
which publishes no side at all). */
|
|
615
|
+
.matrx-motion-popper[data-state="open"] {
|
|
616
|
+
animation: matrx-popper-in-from-top var(--matrx-motion-duration-fast)
|
|
617
|
+
var(--matrx-motion-ease-out);
|
|
618
|
+
}
|
|
619
|
+
.matrx-motion-popper[data-state="open"][data-side="bottom"] {
|
|
620
|
+
animation-name: matrx-popper-in-from-top;
|
|
621
|
+
}
|
|
622
|
+
.matrx-motion-popper[data-state="open"][data-side="top"] {
|
|
623
|
+
animation-name: matrx-popper-in-from-bottom;
|
|
624
|
+
}
|
|
625
|
+
.matrx-motion-popper[data-state="open"][data-side="right"] {
|
|
626
|
+
animation-name: matrx-popper-in-from-left;
|
|
627
|
+
}
|
|
628
|
+
.matrx-motion-popper[data-state="open"][data-side="left"] {
|
|
629
|
+
animation-name: matrx-popper-in-from-right;
|
|
630
|
+
}
|
|
631
|
+
.matrx-motion-popper[data-state="closed"] {
|
|
632
|
+
animation: matrx-popper-out var(--matrx-motion-duration-fast)
|
|
633
|
+
var(--matrx-motion-ease-in);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/* THE POPPER'S RESTING GAP — same law as `.matrx-dialog-centered` above, same
|
|
637
|
+
reason. `Select` in `popper` position used to nudge itself off its trigger
|
|
638
|
+
with `data-[side=bottom]:translate-y-1` and three siblings. Those are
|
|
639
|
+
Tailwind translate utilities on a surface whose keyframes animate
|
|
640
|
+
`transform` — the identical composite hazard the centred card shipped in
|
|
641
|
+
0.10.0, at 4px instead of half a viewport: on a v4 host the gap composed
|
|
642
|
+
correctly by luck, on a v3 host the animation replaced it and the surface
|
|
643
|
+
snapped 4px at the end. Stated as the `translate` property, it is the
|
|
644
|
+
resting offset in every host and the keyframes keep `transform` to
|
|
645
|
+
themselves. Sides are Radix's `data-side` (where the surface SITS), so a
|
|
646
|
+
surface below its trigger moves further down. */
|
|
647
|
+
.matrx-popper-offset[data-side="bottom"] {
|
|
648
|
+
translate: 0 var(--matrx-popper-offset);
|
|
649
|
+
}
|
|
650
|
+
.matrx-popper-offset[data-side="top"] {
|
|
651
|
+
translate: 0 calc(-1 * var(--matrx-popper-offset));
|
|
652
|
+
}
|
|
653
|
+
.matrx-popper-offset[data-side="right"] {
|
|
654
|
+
translate: var(--matrx-popper-offset) 0;
|
|
655
|
+
}
|
|
656
|
+
.matrx-popper-offset[data-side="left"] {
|
|
657
|
+
translate: calc(-1 * var(--matrx-popper-offset)) 0;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/* --- the two indefinite loops -----------------------------------------
|
|
661
|
+
`animate-pulse` and `animate-spin` ARE core Tailwind, so they survive in a
|
|
662
|
+
Tailwind host — but a Skeleton that does not pulse is indistinguishable
|
|
663
|
+
from an empty grey box, and a spinner that does not spin claims the work
|
|
664
|
+
has stopped. Both are load-bearing lies in a non-Tailwind consumer, and
|
|
665
|
+
both are four lines. The package owns them. */
|
|
666
|
+
@keyframes matrx-pulse {
|
|
667
|
+
0%,
|
|
668
|
+
100% {
|
|
669
|
+
opacity: 1;
|
|
670
|
+
}
|
|
671
|
+
50% {
|
|
672
|
+
opacity: 0.5;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
@keyframes matrx-spin {
|
|
676
|
+
to {
|
|
677
|
+
transform: rotate(360deg);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
.matrx-pulse {
|
|
681
|
+
animation: matrx-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
682
|
+
}
|
|
683
|
+
.matrx-spin {
|
|
684
|
+
animation: matrx-spin 1s linear infinite;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/* --- the accessibility switch -----------------------------------------
|
|
688
|
+
ONE block for the whole motion layer. A surface still appears and
|
|
689
|
+
disappears — it just does so without travelling. The two indefinite loops
|
|
690
|
+
are the exception that proves the rule: a Skeleton and a spinner say
|
|
691
|
+
"still working" with motion and nothing else, so silencing them entirely
|
|
692
|
+
would remove the information. They slow down instead of stopping.
|
|
693
|
+
|
|
694
|
+
Deliberately NOT a `--matrx-motion-*` token: a user's OS-level reduced
|
|
695
|
+
motion preference is not an org setting a host may override. */
|
|
696
|
+
@media (prefers-reduced-motion: reduce) {
|
|
697
|
+
.matrx-motion-overlay[data-state],
|
|
698
|
+
.matrx-motion-dialog[data-state],
|
|
699
|
+
.matrx-motion-sheet-top[data-state],
|
|
700
|
+
.matrx-motion-sheet-bottom[data-state],
|
|
701
|
+
.matrx-motion-sheet-left[data-state],
|
|
702
|
+
.matrx-motion-sheet-right[data-state],
|
|
703
|
+
.matrx-motion-sheet-center[data-state],
|
|
704
|
+
.matrx-motion-bottom-sheet[data-state],
|
|
705
|
+
.matrx-motion-popper[data-state] {
|
|
706
|
+
animation: none;
|
|
707
|
+
}
|
|
708
|
+
.matrx-pulse {
|
|
709
|
+
animation-duration: 4s;
|
|
710
|
+
}
|
|
711
|
+
.matrx-spin {
|
|
712
|
+
animation-duration: 3s;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
233
716
|
/* ────────────────────────────────────────────────────────────────────────
|
|
234
717
|
Scroll fade — the "there is more below" cue. UNLAYERED on purpose.
|
|
235
718
|
Driven by `useScrollFade`, which sets the data attributes ONLY on edges
|
package/dist/tokens.css
CHANGED
|
@@ -117,6 +117,36 @@
|
|
|
117
117
|
0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
118
118
|
--matrx-glass-shadow-lg:
|
|
119
119
|
0 4px 16px rgba(0, 0, 0, 0.08), 0 2px 6px rgba(0, 0, 0, 0.04);
|
|
120
|
+
|
|
121
|
+
/* MOTION (0.10.0). Every package-owned animation in styles.css reads its
|
|
122
|
+
duration and easing from here, so a host retimes the whole system by
|
|
123
|
+
redeclaring four values — and an org that wants calmer motion sets them
|
|
124
|
+
once instead of overriding twenty rules. They are NOT the accessibility
|
|
125
|
+
switch: `prefers-reduced-motion: reduce` silences the animations
|
|
126
|
+
outright in styles.css, regardless of these values.
|
|
127
|
+
|
|
128
|
+
The numbers are the ones the primitives already carried as Tailwind
|
|
129
|
+
`duration-*` utilities before the package owned the keyframes:
|
|
130
|
+
poppers/tooltips 150ms, dialogs and overlays 200ms, a sheet closing
|
|
131
|
+
300ms and opening 500ms. */
|
|
132
|
+
--matrx-motion-duration-fast: 150ms;
|
|
133
|
+
--matrx-motion-duration-base: 200ms;
|
|
134
|
+
--matrx-motion-duration-slow: 300ms;
|
|
135
|
+
--matrx-motion-duration-sheet: 500ms;
|
|
136
|
+
/* Enters decelerate (the surface arrives and settles); exits accelerate
|
|
137
|
+
(it leaves and is gone). Linear on both — which is what
|
|
138
|
+
`tailwindcss-animate` defaulted to — reads mechanical at these
|
|
139
|
+
durations. */
|
|
140
|
+
--matrx-motion-ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
141
|
+
--matrx-motion-ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
142
|
+
/* The distance a popper travels toward its anchor as it opens. 0.5rem is
|
|
143
|
+
the `slide-in-from-*-2` the primitives carried. */
|
|
144
|
+
--matrx-motion-popper-travel: 0.5rem;
|
|
145
|
+
/* The RESTING gap between a `popper`-positioned surface and its trigger —
|
|
146
|
+
not motion, geometry. 0.25rem is the `translate-y-1` the primitives
|
|
147
|
+
carried before 0.10.1 moved it off Tailwind's translate utilities and
|
|
148
|
+
into the `translate` property (see `.matrx-popper-offset`). */
|
|
149
|
+
--matrx-popper-offset: 0.25rem;
|
|
120
150
|
}
|
|
121
151
|
|
|
122
152
|
/* Dark theme. Matches the `.dark`-class convention (Tailwind v4 hosts wire
|
package/package.json
CHANGED