tangled
alpha
login
or
join now
mary.my.id
/
danaus
4
fork
atom
work-in-progress atproto PDS
typescript
atproto
pds
atcute
4
fork
atom
overview
issues
pulls
pipelines
feat: menu and dialog transitions
mary.my.id
2 months ago
841e161f
241ca27f
verified
This commit was signed with the committer's
known signature
.
mary.my.id
SSH Key Fingerprint:
SHA256:ZlTP/auFSGpGnaoDg4mCTG1g9OZvXp62jWR4c6H4O3c=
+201
4 changed files
expand all
collapse all
unified
split
packages
danaus
src
web
primitives
dialog-surface.tsx
menu-popover.tsx
styles
main.css
main.out.css
+2
packages/danaus/src/web/primitives/dialog-surface.tsx
···
16
16
'sm:items-center',
17
17
// backdrop
18
18
'backdrop:bg-background-overlay',
19
19
+
// entry/exit animations
20
20
+
'dialog-animate dialog-backdrop-animate',
19
21
],
20
22
});
21
23
+2
packages/danaus/src/web/primitives/menu-popover.tsx
···
8
8
base: [
9
9
'm-0 box-border w-max max-w-75 min-w-35 overflow-x-hidden rounded-md border border-transparent bg-neutral-background-1 p-1 text-neutral-foreground-1 shadow-16',
10
10
'anchored anchored-bottom-span-left try-flip-y',
11
11
+
// entry/exit animations (slides down from anchor)
12
12
+
'popover-animate popover-slide-down',
11
13
],
12
14
});
13
15
+128
packages/danaus/src/web/styles/main.css
···
89
89
90
90
--ease-*: initial;
91
91
--ease-fluent: cubic-bezier(0.33, 0, 0.67, 1);
92
92
+
--ease-accelerate-min: cubic-bezier(0.8, 0, 0.78, 1);
93
93
+
--ease-decelerate-mid: cubic-bezier(0, 0, 0, 1);
94
94
+
95
95
+
--duration-*: initial;
96
96
+
--duration-faster: 100ms;
97
97
+
--duration-fast: 150ms;
98
98
+
--duration-normal: 200ms;
99
99
+
--duration-gentle: 250ms;
100
100
+
--duration-slow: 300ms;
101
101
+
--duration-slower: 400ms;
92
102
93
103
--animate-*: initial;
94
104
--animate-spin-linear: spin-linear 1.5s linear infinite;
···
422
432
}
423
433
424
434
/* #endregion */
435
435
+
436
436
+
/* #region dialog animations */
437
437
+
438
438
+
/*
439
439
+
* dialog entry/exit animations using @starting-style
440
440
+
* inspired by FluentUI's Dialog motion: scale + fade with decelerate/accelerate easing
441
441
+
*/
442
442
+
443
443
+
@utility dialog-animate {
444
444
+
/* transition properties for both dialog surface and backdrop */
445
445
+
transition-property: opacity, scale, overlay, display;
446
446
+
transition-duration: var(--duration-faster);
447
447
+
transition-timing-function: var(--ease-decelerate-mid);
448
448
+
transition-behavior: allow-discrete;
449
449
+
450
450
+
/* final open state */
451
451
+
&[open] {
452
452
+
opacity: 1;
453
453
+
scale: 1;
454
454
+
}
455
455
+
456
456
+
/* exit state (dialog closing) */
457
457
+
&:not([open]) {
458
458
+
opacity: 0;
459
459
+
scale: 0.95;
460
460
+
transition-timing-function: var(--ease-accelerate-min);
461
461
+
}
462
462
+
463
463
+
/* entry starting state */
464
464
+
@starting-style {
465
465
+
&[open] {
466
466
+
opacity: 0;
467
467
+
scale: 0.95;
468
468
+
}
469
469
+
}
470
470
+
}
471
471
+
472
472
+
/* backdrop animation (fade only, no scale) */
473
473
+
@utility dialog-backdrop-animate {
474
474
+
&::backdrop {
475
475
+
transition-property: opacity, overlay, display;
476
476
+
transition-duration: var(--duration-faster);
477
477
+
transition-timing-function: var(--ease-decelerate-mid);
478
478
+
transition-behavior: allow-discrete;
479
479
+
opacity: 1;
480
480
+
}
481
481
+
482
482
+
&:not([open])::backdrop {
483
483
+
opacity: 0;
484
484
+
transition-timing-function: var(--ease-accelerate-min);
485
485
+
}
486
486
+
487
487
+
@starting-style {
488
488
+
&[open]::backdrop {
489
489
+
opacity: 0;
490
490
+
}
491
491
+
}
492
492
+
}
493
493
+
494
494
+
/* #endregion */
495
495
+
496
496
+
/* #region popover animations */
497
497
+
498
498
+
/*
499
499
+
* popover entry/exit animations using @starting-style
500
500
+
* inspired by FluentUI's Menu motion: slide + fade based on placement
501
501
+
*/
502
502
+
503
503
+
@utility popover-animate {
504
504
+
--_slide-x: 0;
505
505
+
--_slide-y: 8px;
506
506
+
507
507
+
transition-property: opacity, translate, overlay, display;
508
508
+
transition-duration: var(--duration-faster);
509
509
+
transition-timing-function: var(--ease-decelerate-mid);
510
510
+
transition-behavior: allow-discrete;
511
511
+
512
512
+
/* final open state */
513
513
+
&:popover-open {
514
514
+
opacity: 1;
515
515
+
translate: 0 0;
516
516
+
}
517
517
+
518
518
+
/* exit state */
519
519
+
&:not(:popover-open) {
520
520
+
opacity: 0;
521
521
+
translate: var(--_slide-x) var(--_slide-y);
522
522
+
transition-timing-function: var(--ease-accelerate-min);
523
523
+
}
524
524
+
525
525
+
/* entry starting state */
526
526
+
@starting-style {
527
527
+
&:popover-open {
528
528
+
opacity: 0;
529
529
+
translate: var(--_slide-x) var(--_slide-y);
530
530
+
}
531
531
+
}
532
532
+
}
533
533
+
534
534
+
/* slide direction variants based on anchor position */
535
535
+
@utility popover-slide-down {
536
536
+
--_slide-x: 0;
537
537
+
--_slide-y: -8px;
538
538
+
}
539
539
+
@utility popover-slide-up {
540
540
+
--_slide-x: 0;
541
541
+
--_slide-y: 8px;
542
542
+
}
543
543
+
@utility popover-slide-left {
544
544
+
--_slide-x: 8px;
545
545
+
--_slide-y: 0;
546
546
+
}
547
547
+
@utility popover-slide-right {
548
548
+
--_slide-x: -8px;
549
549
+
--_slide-y: 0;
550
550
+
}
551
551
+
552
552
+
/* #endregion */
+69
packages/danaus/src/web/styles/main.out.css
···
81
81
--color-subtle-background-hover: var(--color-subtle-background-hover);
82
82
--color-subtle-background: var(--color-subtle-background);
83
83
--ease-fluent: cubic-bezier(0.33, 0, 0.67, 1);
84
84
+
--ease-accelerate-min: cubic-bezier(0.8, 0, 0.78, 1);
85
85
+
--ease-decelerate-mid: cubic-bezier(0, 0, 0, 1);
86
86
+
--duration-faster: 100ms;
84
87
--shadow-2: var(--shadow-2);
85
88
--shadow-4: var(--shadow-4);
86
89
--shadow-8: var(--shadow-8);
···
494
497
.basis-0 {
495
498
flex-basis: calc(var(--spacing) * 0);
496
499
}
500
500
+
.popover-animate {
501
501
+
--_slide-x: 0;
502
502
+
--_slide-y: 8px;
503
503
+
transition-property: opacity, translate, overlay, display;
504
504
+
transition-duration: var(--duration-faster);
505
505
+
transition-timing-function: var(--ease-decelerate-mid);
506
506
+
transition-behavior: allow-discrete;
507
507
+
&:popover-open {
508
508
+
opacity: 1;
509
509
+
translate: 0 0;
510
510
+
}
511
511
+
&:not(:popover-open) {
512
512
+
opacity: 0;
513
513
+
translate: var(--_slide-x) var(--_slide-y);
514
514
+
transition-timing-function: var(--ease-accelerate-min);
515
515
+
}
516
516
+
@starting-style {
517
517
+
&:popover-open {
518
518
+
opacity: 0;
519
519
+
translate: var(--_slide-x) var(--_slide-y);
520
520
+
}
521
521
+
}
522
522
+
}
523
523
+
.dialog-animate {
524
524
+
transition-property: opacity, scale, overlay, display;
525
525
+
transition-duration: var(--duration-faster);
526
526
+
transition-timing-function: var(--ease-decelerate-mid);
527
527
+
transition-behavior: allow-discrete;
528
528
+
&[open] {
529
529
+
opacity: 1;
530
530
+
scale: 1;
531
531
+
}
532
532
+
&:not([open]) {
533
533
+
opacity: 0;
534
534
+
scale: 0.95;
535
535
+
transition-timing-function: var(--ease-accelerate-min);
536
536
+
}
537
537
+
@starting-style {
538
538
+
&[open] {
539
539
+
opacity: 0;
540
540
+
scale: 0.95;
541
541
+
}
542
542
+
}
543
543
+
}
497
544
.cursor-pointer {
498
545
cursor: pointer;
499
546
}
···
866
913
.no-underline {
867
914
text-decoration-line: none;
868
915
}
916
916
+
.dialog-backdrop-animate {
917
917
+
&::backdrop {
918
918
+
transition-property: opacity, overlay, display;
919
919
+
transition-duration: var(--duration-faster);
920
920
+
transition-timing-function: var(--ease-decelerate-mid);
921
921
+
transition-behavior: allow-discrete;
922
922
+
opacity: 1;
923
923
+
}
924
924
+
&:not([open])::backdrop {
925
925
+
opacity: 0;
926
926
+
transition-timing-function: var(--ease-accelerate-min);
927
927
+
}
928
928
+
@starting-style {
929
929
+
&[open]::backdrop {
930
930
+
opacity: 0;
931
931
+
}
932
932
+
}
933
933
+
}
869
934
.opacity-0 {
870
935
opacity: 0%;
871
936
}
···
907
972
.outline-none {
908
973
--tw-outline-style: none;
909
974
outline-style: none;
975
975
+
}
976
976
+
.popover-slide-down {
977
977
+
--_slide-x: 0;
978
978
+
--_slide-y: -8px;
910
979
}
911
980
.select-none {
912
981
-webkit-user-select: none;