diff --git a/ui/components/shadcn/dropdown/dropdown.test.tsx b/ui/components/shadcn/dropdown/dropdown.test.tsx
new file mode 100644
index 0000000000..72f8f13410
--- /dev/null
+++ b/ui/components/shadcn/dropdown/dropdown.test.tsx
@@ -0,0 +1,114 @@
+import { render, screen } from "@testing-library/react";
+import { describe, expect, it } from "vitest";
+
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuTrigger,
+} from "./dropdown";
+
+function renderActionsDropdown() {
+ return render(
+
+ Open actions
+
+ Edit
+ Delete
+
+ ,
+ );
+}
+
+describe("DropdownMenu", () => {
+ it("renders open menu content through the Radix DropdownMenu API", () => {
+ // Given
+ renderActionsDropdown();
+
+ // When
+ const menu = screen.getByRole("menu");
+
+ // Then
+ expect(menu).toBeVisible();
+ expect(menu).toHaveAttribute("data-slot", "dropdown-menu-content");
+ expect(screen.getByRole("menuitem", { name: "Edit" })).toBeVisible();
+ expect(screen.getByRole("menuitem", { name: "Delete" })).toBeVisible();
+ });
+
+ it("uses an intentional open and close motion contract", () => {
+ // Given
+ renderActionsDropdown();
+
+ // When
+ const menu = screen.getByRole("menu");
+
+ // Then
+ expect(menu).toHaveClass(
+ "origin-(--radix-dropdown-menu-content-transform-origin)",
+ "duration-200",
+ "ease-out",
+ "data-[state=open]:animate-in",
+ "data-[state=open]:fade-in-0",
+ "data-[state=open]:zoom-in-95",
+ "data-[state=closed]:animate-out",
+ "data-[state=closed]:fade-out-0",
+ "data-[state=closed]:zoom-out-95",
+ "data-[state=closed]:duration-100",
+ "data-[state=closed]:ease-in",
+ );
+ });
+
+ it("removes transform-heavy menu motion for reduced-motion users", () => {
+ // Given
+ renderActionsDropdown();
+
+ // When
+ const menu = screen.getByRole("menu");
+
+ // Then
+ expect(menu).toHaveClass(
+ "motion-reduce:animate-none",
+ "motion-reduce:transform-none",
+ "motion-reduce:transition-none",
+ );
+ });
+
+ it("applies the same motion contract to submenu content", () => {
+ // Given
+ render(
+
+ Open actions
+
+
+ More actions
+
+ Archive
+
+
+
+ ,
+ );
+
+ // When
+ const submenuContent = screen
+ .getByRole("menuitem", { name: "Archive" })
+ .closest("[data-slot='dropdown-menu-sub-content']");
+
+ // Then
+ expect(submenuContent).toHaveClass(
+ "origin-(--radix-dropdown-menu-content-transform-origin)",
+ "duration-200",
+ "ease-out",
+ "data-[state=open]:animate-in",
+ "data-[state=closed]:animate-out",
+ "data-[state=closed]:duration-100",
+ "data-[state=closed]:ease-in",
+ "motion-reduce:animate-none",
+ "motion-reduce:transform-none",
+ "motion-reduce:transition-none",
+ );
+ });
+});
diff --git a/ui/components/shadcn/dropdown/dropdown.tsx b/ui/components/shadcn/dropdown/dropdown.tsx
index c6cf066250..13b43522c6 100644
--- a/ui/components/shadcn/dropdown/dropdown.tsx
+++ b/ui/components/shadcn/dropdown/dropdown.tsx
@@ -42,7 +42,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md duration-200 ease-out data-[state=closed]:duration-100 data-[state=closed]:ease-in motion-reduce:transform-none motion-reduce:animate-none motion-reduce:transition-none",
className,
)}
{...props}
@@ -227,7 +227,7 @@ function DropdownMenuSubContent({