diff --git a/ui/components/shadcn/combobox/combobox.test.tsx b/ui/components/shadcn/combobox/combobox.test.tsx
new file mode 100644
index 0000000000..f5ea9e492d
--- /dev/null
+++ b/ui/components/shadcn/combobox/combobox.test.tsx
@@ -0,0 +1,94 @@
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { beforeAll, describe, expect, it, vi } from "vitest";
+
+import { Combobox } from "./combobox";
+
+const options = [
+ { value: "aws", label: "AWS" },
+ { value: "azure", label: "Azure" },
+ { value: "gcp", label: "GCP" },
+];
+
+beforeAll(() => {
+ global.ResizeObserver = class ResizeObserver {
+ observe = vi.fn();
+ unobserve = vi.fn();
+ disconnect = vi.fn();
+ } as unknown as typeof ResizeObserver;
+
+ Object.defineProperty(HTMLElement.prototype, "scrollIntoView", {
+ configurable: true,
+ value: vi.fn(),
+ });
+
+ Object.defineProperty(HTMLElement.prototype, "hasPointerCapture", {
+ configurable: true,
+ value: vi.fn(() => false),
+ });
+ Object.defineProperty(HTMLElement.prototype, "releasePointerCapture", {
+ configurable: true,
+ value: vi.fn(),
+ });
+});
+
+describe("Combobox", () => {
+ it("renders a selectable combobox trigger", () => {
+ // Given
+ render();
+
+ // When
+ const trigger = screen.getByRole("combobox", { name: /select provider/i });
+
+ // Then
+ expect(trigger).toBeVisible();
+ expect(trigger).toHaveAttribute("aria-expanded", "false");
+ });
+
+ it("uses visible trigger and chevron open-state motion", () => {
+ // Given
+ render();
+
+ // When
+ const trigger = screen.getByRole("combobox", { name: /select provider/i });
+ const icon = trigger.querySelector("svg");
+
+ // Then
+ expect(trigger).toHaveClass(
+ "group",
+ "transition-[background-color,border-color,color,box-shadow]",
+ );
+ expect(icon).toHaveClass(
+ "transition-transform",
+ "duration-200",
+ "ease-out",
+ "group-aria-expanded:rotate-180",
+ "motion-reduce:rotate-0",
+ "motion-reduce:transition-none",
+ );
+ });
+
+ it("opens with the shared Popover content motion contract", async () => {
+ // Given
+ const user = userEvent.setup();
+ render();
+
+ // When
+ await user.click(
+ screen.getByRole("combobox", { name: /select provider/i }),
+ );
+ const content = document.querySelector("[data-slot='popover-content']");
+
+ // Then
+ expect(content).toHaveClass(
+ "duration-200",
+ "ease-out",
+ "data-[state=open]:animate-in",
+ "data-[state=open]:fade-in-0",
+ "data-[state=open]:zoom-in-95",
+ "motion-reduce:animate-none",
+ "motion-reduce:transform-none",
+ "motion-reduce:transition-none",
+ );
+ });
+});
diff --git a/ui/components/shadcn/combobox/combobox.tsx b/ui/components/shadcn/combobox/combobox.tsx
index b10bcf8973..8279a4147b 100644
--- a/ui/components/shadcn/combobox/combobox.tsx
+++ b/ui/components/shadcn/combobox/combobox.tsx
@@ -113,8 +113,10 @@ export function Combobox({
variant="outline"
role="combobox"
aria-expanded={open}
+ aria-label={selectedOption ? selectedOption.label : placeholder}
disabled={disabled}
className={cn(
+ "group transition-[background-color,border-color,color,box-shadow]",
comboboxTriggerVariants({ variant }),
triggerClassName,
className,
@@ -123,7 +125,7 @@ export function Combobox({
{selectedOption ? selectedOption.label : placeholder}
-
+