diff --git a/frontend/packages/swarm-ui/src/shell/LinksMenu.css b/frontend/packages/swarm-ui/src/shell/LinksMenu.css
index 268d6096..ae2110a6 100644
--- a/frontend/packages/swarm-ui/src/shell/LinksMenu.css
+++ b/frontend/packages/swarm-ui/src/shell/LinksMenu.css
@@ -43,6 +43,33 @@
border-radius: 0.5em;
background: var(--bg-elev);
box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.3);
+ animation: links-menu-popover-enter 140ms ease;
+}
+/* Mount-triggered, not a state transition — the popover only exists in
+ the DOM while open (`{open ?
: null}`), so a keyframe animation
+ on entry is the right tool, same shape as `.shell-body`'s own
+ `shell-page-enter` (Shell.css) — that's the precedent every popover
+ in this issue's "menus should animate" ask follows. */
+@keyframes links-menu-popover-enter {
+ from {
+ opacity: 0;
+ transform: translateY(-0.25em) scale(0.98);
+ }
+ to {
+ opacity: 1;
+ transform: none;
+ }
+}
+@media (prefers-reduced-motion: reduce) {
+ .links-menu-popover {
+ animation: none;
+ }
+}
+:root[data-motion='reduce'] .links-menu-popover {
+ animation: none;
+}
+:root[data-motion='allow'] .links-menu-popover {
+ animation: links-menu-popover-enter 140ms ease;
}
.links-menu-item {
display: flex;
diff --git a/frontend/packages/swarm-ui/src/shell/SettingsMenu.css b/frontend/packages/swarm-ui/src/shell/SettingsMenu.css
index 06c711df..ebc87b33 100644
--- a/frontend/packages/swarm-ui/src/shell/SettingsMenu.css
+++ b/frontend/packages/swarm-ui/src/shell/SettingsMenu.css
@@ -40,6 +40,31 @@
border-radius: 0.5em;
background: var(--bg-elev);
box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.3);
+ animation: settings-menu-popover-enter 140ms ease;
+}
+/* Mount-triggered, same shape as `LinksMenu.css`'s own version — see
+ its comment for why a keyframe (not a transition) is the right tool
+ here. */
+@keyframes settings-menu-popover-enter {
+ from {
+ opacity: 0;
+ transform: translateY(-0.25em) scale(0.98);
+ }
+ to {
+ opacity: 1;
+ transform: none;
+ }
+}
+@media (prefers-reduced-motion: reduce) {
+ .settings-menu-popover {
+ animation: none;
+ }
+}
+:root[data-motion='reduce'] .settings-menu-popover {
+ animation: none;
+}
+:root[data-motion='allow'] .settings-menu-popover {
+ animation: settings-menu-popover-enter 140ms ease;
}
.settings-menu-row {
display: flex;
diff --git a/frontend/packages/swarm-ui/src/shell/UserMenu.css b/frontend/packages/swarm-ui/src/shell/UserMenu.css
index 85233cad..d2a6624b 100644
--- a/frontend/packages/swarm-ui/src/shell/UserMenu.css
+++ b/frontend/packages/swarm-ui/src/shell/UserMenu.css
@@ -41,6 +41,31 @@
border-radius: 0.5em;
background: var(--bg-elev);
box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.3);
+ animation: user-menu-popover-enter 140ms ease;
+}
+/* Mount-triggered, same shape as `LinksMenu.css`'s own version — see
+ its comment for why a keyframe (not a transition) is the right tool
+ here. */
+@keyframes user-menu-popover-enter {
+ from {
+ opacity: 0;
+ transform: translateY(-0.25em) scale(0.98);
+ }
+ to {
+ opacity: 1;
+ transform: none;
+ }
+}
+@media (prefers-reduced-motion: reduce) {
+ .user-menu-popover {
+ animation: none;
+ }
+}
+:root[data-motion='reduce'] .user-menu-popover {
+ animation: none;
+}
+:root[data-motion='allow'] .user-menu-popover {
+ animation: user-menu-popover-enter 140ms ease;
}
.user-menu-name {
padding: 0.4em 0.6em 0.5em;