mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-18 17:34:17 +00:00
feat(ui): add Popover open close microinteraction
- Add explicit timing for Popover state transitions - Add reduced-motion fallback utilities - Cover controlled Popover motion behavior
This commit is contained in:
2 files changed
+88
-1
No files matched your search
@@ -0,0 +1,87 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "./popover";
|
||||
|
||||
describe("Popover", () => {
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
|
||||
it("renders controlled content through the Radix Popover API", () => {
|
||||
// Given
|
||||
const portalContainer = document.createElement("div");
|
||||
document.body.appendChild(portalContainer);
|
||||
|
||||
// When
|
||||
render(
|
||||
<Popover open>
|
||||
<PopoverTrigger>Open filters</PopoverTrigger>
|
||||
<PopoverContent container={portalContainer}>
|
||||
Filter content
|
||||
</PopoverContent>
|
||||
</Popover>,
|
||||
);
|
||||
|
||||
// Then
|
||||
expect(screen.getByText("Filter content")).toBeVisible();
|
||||
expect(screen.getByText("Filter content")).toHaveAttribute(
|
||||
"data-slot",
|
||||
"popover-content",
|
||||
);
|
||||
});
|
||||
|
||||
it("uses an intentional open and close motion contract", () => {
|
||||
// Given
|
||||
const portalContainer = document.createElement("div");
|
||||
document.body.appendChild(portalContainer);
|
||||
|
||||
// When
|
||||
render(
|
||||
<Popover open>
|
||||
<PopoverTrigger>Open filters</PopoverTrigger>
|
||||
<PopoverContent container={portalContainer}>
|
||||
Filter content
|
||||
</PopoverContent>
|
||||
</Popover>,
|
||||
);
|
||||
|
||||
// Then
|
||||
expect(screen.getByText("Filter content")).toHaveClass(
|
||||
"origin-(--radix-popover-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 motion for reduced-motion users", () => {
|
||||
// Given
|
||||
const portalContainer = document.createElement("div");
|
||||
document.body.appendChild(portalContainer);
|
||||
|
||||
// When
|
||||
render(
|
||||
<Popover open>
|
||||
<PopoverTrigger>Open filters</PopoverTrigger>
|
||||
<PopoverContent container={portalContainer}>
|
||||
Filter content
|
||||
</PopoverContent>
|
||||
</Popover>,
|
||||
);
|
||||
|
||||
// Then
|
||||
expect(screen.getByText("Filter content")).toHaveClass(
|
||||
"motion-reduce:animate-none",
|
||||
"motion-reduce:transform-none",
|
||||
"motion-reduce:transition-none",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -32,7 +32,7 @@ function PopoverContent({
|
||||
align={align}
|
||||
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 pointer-events-auto z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
||||
"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 pointer-events-auto z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden 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}
|
||||
|
||||
Reference in new issue
Block a user