Skip to content

Commit bd67af5

Browse files
wheregmisealmloff
andauthored
Focusout for Dropdown, Menubar and ContextMenu (#22)
* Maybe dropdown fix? * on focus out try * this way might work * item selection should work now * adding type * Focus out try for menubar * Using data state instead of hidden and basic animations * Adding inert to context_menu, dropdown menu and menubar * Revert "Adding inert to context_menu, dropdown menu and menubar" This reverts commit a8e41a2. * Just comment inert for now * handle menubar navigation * merge styles * simplify menubar logic * implement similar keyboard navigation logic for the dropdown menu component * Keyboard navigation for the context menu component --------- Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
1 parent 7a3a558 commit bd67af5

File tree

8 files changed

+411
-242
lines changed

8 files changed

+411
-242
lines changed

preview/src/components/context_menu/mod.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,37 @@ pub(super) fn Demo() -> Element {
2525
class: "context-menu-item",
2626
value: "edit".to_string(),
2727
index: 0usize,
28+
on_select: move |value| {
29+
tracing::info!("Selected item: {}", value);
30+
},
2831
"Edit"
2932
}
3033
ContextMenuItem {
3134
class: "context-menu-item",
3235
value: "undo".to_string(),
3336
index: 1usize,
3437
disabled: true,
38+
on_select: move |value| {
39+
tracing::info!("Selected item: {}", value);
40+
},
3541
"Undo"
3642
}
3743
ContextMenuItem {
3844
class: "context-menu-item",
3945
value: "duplicate".to_string(),
40-
index: 1usize,
46+
index: 2usize,
47+
on_select: move |value| {
48+
tracing::info!("Selected item: {}", value);
49+
},
4150
"Duplicate"
4251
}
4352
ContextMenuItem {
4453
class: "context-menu-item",
4554
value: "delete".to_string(),
46-
index: 2usize,
55+
index: 3usize,
56+
on_select: move |value| {
57+
tracing::info!("Selected item: {}", value);
58+
},
4759
"Delete"
4860
}
4961
}

preview/src/components/context_menu/style.css

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
border-radius: 0.5rem;
55
padding: 0.25rem;
66
box-shadow: 0 0 0 1px var(--dim-border-color);
7-
animation: slideIn 0.1s ease-out;
7+
z-index: 1000;
8+
transform-origin: var(--radix-context-menu-content-transform-origin);
9+
will-change: transform, opacity;
810
}
911

1012
@media (prefers-color-scheme: dark) {
@@ -14,8 +16,18 @@
1416
}
1517
}
1618

17-
.context-menu-content[hidden] {
18-
display: none;
19+
.context-menu-content[data-state="closed"] {
20+
pointer-events: none;
21+
opacity: 0;
22+
transform: scale(0.95) translateY(-2px);
23+
transition: opacity 150ms ease-in, transform 150ms ease-in;
24+
}
25+
26+
.context-menu-content[data-state="open"] {
27+
opacity: 1;
28+
transform: scale(1) translateY(0);
29+
transition: opacity 200ms ease-out,
30+
transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
1931
}
2032

2133
.context-menu-item {
@@ -28,6 +40,7 @@
2840
color: var(--text-color);
2941
display: flex;
3042
align-items: center;
43+
transition: background-color 100ms ease-out;
3144
}
3245

3346
.context-menu-item[data-disabled="true"] {
@@ -47,15 +60,3 @@
4760
background: var(--hover-border-color);
4861
}
4962
}
50-
51-
@keyframes slideIn {
52-
from {
53-
opacity: 0;
54-
transform: scale(0.95);
55-
}
56-
57-
to {
58-
opacity: 1;
59-
transform: scale(1);
60-
}
61-
}

preview/src/components/dropdown_menu/style.css

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@
4242
padding: 0.25rem;
4343
box-shadow: inset 0 0 0 1px var(--dim-border-color);
4444
animation: slideIn 0.1s ease-out;
45+
z-index: 1000;
46+
/* Animation properties */
47+
opacity: 0;
48+
transform: translateY(-8px) scale(0.95);
49+
transition: all 0.2s ease;
4550
}
4651

4752
@media (prefers-color-scheme: dark) {
@@ -51,8 +56,17 @@
5156
}
5257
}
5358

54-
.dropdown-menu-content[hidden] {
55-
display: none;
59+
/* Open state animations */
60+
.dropdown-menu-content[data-state="open"] {
61+
opacity: 1;
62+
transform: translateY(0) scale(1);
63+
}
64+
65+
/* Closed state animations */
66+
.dropdown-menu-content[data-state="closed"] {
67+
opacity: 0;
68+
transform: translateY(-8px) scale(0.95);
69+
pointer-events: none;
5670
}
5771

5872
.dropdown-menu-item {
@@ -84,15 +98,3 @@
8498
background: var(--hover-border-color);
8599
}
86100
}
87-
88-
@keyframes slideIn {
89-
from {
90-
opacity: 0;
91-
transform: scale(0.95);
92-
}
93-
94-
to {
95-
opacity: 1;
96-
transform: scale(1);
97-
}
98-
}

preview/src/components/menubar/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,29 @@ pub(super) fn Demo() -> Element {
1515
MenubarTrigger { class: "menubar-trigger", "File" }
1616
MenubarContent { class: "menubar-content",
1717
MenubarItem {
18+
index: 0usize,
1819
class: "menubar-item",
1920
value: "new".to_string(),
2021
on_select: move |value| {
21-
tracing::info!("Selected: {value}");
22+
tracing::info!("Selected value: {}", value);
2223
},
2324
"New"
2425
}
2526
MenubarItem {
27+
index: 1usize,
2628
class: "menubar-item",
2729
value: "open".to_string(),
2830
on_select: move |value| {
29-
tracing::info!("Selected: {value}");
31+
tracing::info!("Selected value: {}", value);
3032
},
3133
"Open"
3234
}
3335
MenubarItem {
36+
index: 2usize,
3437
class: "menubar-item",
3538
value: "save".to_string(),
3639
on_select: move |value| {
37-
tracing::info!("Selected: {value}");
40+
tracing::info!("Selected value: {}", value);
3841
},
3942
"Save"
4043
}
@@ -44,26 +47,29 @@ pub(super) fn Demo() -> Element {
4447
MenubarTrigger { class: "menubar-trigger", "Edit" }
4548
MenubarContent { class: "menubar-content",
4649
MenubarItem {
50+
index: 0usize,
4751
class: "menubar-item",
4852
value: "cut".to_string(),
4953
on_select: move |value| {
50-
tracing::info!("Selected: {value}");
54+
tracing::info!("Selected value: {}", value);
5155
},
5256
"Cut"
5357
}
5458
MenubarItem {
59+
index: 1usize,
5560
class: "menubar-item",
5661
value: "copy".to_string(),
5762
on_select: move |value| {
58-
tracing::info!("Selected: {value}");
63+
tracing::info!("Selected value: {}", value);
5964
},
6065
"Copy"
6166
}
6267
MenubarItem {
68+
index: 2usize,
6369
class: "menubar-item",
6470
value: "paste".to_string(),
6571
on_select: move |value| {
66-
tracing::info!("Selected: {value}");
72+
tracing::info!("Selected value: {}", value);
6773
},
6874
"Paste"
6975
}

preview/src/components/menubar/style.css

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
cursor: pointer;
2121
color: var(--text-color);
2222
border-radius: calc(.5rem - .25rem);
23+
transition: background-color 100ms ease-out;
2324
}
2425

2526
.menubar-menu[data-state="open"] .menubar-trigger {
@@ -41,6 +42,7 @@
4142
.menubar-trigger:focus-visible {
4243
color: var(--bright-text-color);
4344
background: var(--hover-background-color);
45+
outline: none;
4446
}
4547
@media (prefers-color-scheme: dark) {
4648
.menubar-trigger:hover:not([data-disabled="true"]),
@@ -50,7 +52,6 @@
5052
}
5153

5254
.menubar-content {
53-
display: none;
5455
position: absolute;
5556
top: 100%;
5657
left: 0;
@@ -61,7 +62,9 @@
6162
border-radius: .5rem;
6263
padding: .25rem;
6364
box-shadow: inset 0 0 0 1px var(--dim-border-color);
64-
animation: menubarSlideIn 0.1s ease-out;
65+
z-index: 1000;
66+
transform-origin: top;
67+
will-change: transform, opacity;
6568
}
6669

6770
@media (prefers-color-scheme: dark) {
@@ -71,8 +74,17 @@
7174
}
7275
}
7376

74-
.menubar-menu[data-state="open"] .menubar-content {
75-
display: block;
77+
.menubar-content[data-state="closed"] {
78+
pointer-events: none;
79+
opacity: 0;
80+
transform: translateY(-4px) scale(0.98);
81+
transition: opacity 150ms ease-in, transform 150ms ease-in;
82+
}
83+
84+
.menubar-content[data-state="open"] {
85+
opacity: 1;
86+
transform: translateY(0) scale(1);
87+
transition: opacity 200ms ease-out, transform 200ms cubic-bezier(0.16, 1, 0.3, 1);
7688
}
7789

7890
.menubar-item {
@@ -92,6 +104,7 @@
92104
.menubar-item:focus-visible {
93105
color: var(--bright-text-color);
94106
background: var(--hover-background-color);
107+
outline: none;
95108
}
96109
@media (prefers-color-scheme: dark) {
97110
.menubar-item:hover:not([data-disabled="true"]),
@@ -104,15 +117,3 @@
104117
opacity: 0.5;
105118
cursor: not-allowed;
106119
}
107-
108-
@keyframes menubarSlideIn {
109-
from {
110-
opacity: 0;
111-
transform: scale(0.95);
112-
}
113-
114-
to {
115-
opacity: 1;
116-
transform: scale(1);
117-
}
118-
}

0 commit comments

Comments
 (0)