mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-05 03:12:14 +00:00
feat(ui): add Dialog content transition
- Animate dialog overlay and content states - Preserve reduced-motion behavior - Cover Dialog motion with focused unit tests
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "./dialog";
|
||||
|
||||
function renderOpenDialog() {
|
||||
return render(
|
||||
<Dialog open>
|
||||
<DialogTrigger>Open modal</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogTitle>Launch scan</DialogTitle>
|
||||
<DialogDescription>Configure scan settings</DialogDescription>
|
||||
</DialogContent>
|
||||
</Dialog>,
|
||||
);
|
||||
}
|
||||
|
||||
describe("Dialog", () => {
|
||||
it("renders controlled content through the Radix Dialog API", () => {
|
||||
// Given
|
||||
renderOpenDialog();
|
||||
|
||||
// When
|
||||
const dialog = screen.getByRole("dialog", { name: "Launch scan" });
|
||||
|
||||
// Then
|
||||
expect(dialog).toBeVisible();
|
||||
expect(dialog).toHaveAttribute("data-slot", "dialog-content");
|
||||
expect(screen.getByText("Configure scan settings")).toBeVisible();
|
||||
});
|
||||
|
||||
it("uses an intentional overlay motion contract", () => {
|
||||
// Given
|
||||
renderOpenDialog();
|
||||
|
||||
// When
|
||||
const overlay = document.querySelector("[data-slot='dialog-overlay']");
|
||||
|
||||
// Then
|
||||
expect(overlay).toHaveClass(
|
||||
"duration-200",
|
||||
"ease-out",
|
||||
"data-[state=open]:animate-in",
|
||||
"data-[state=open]:fade-in-0",
|
||||
"data-[state=closed]:animate-out",
|
||||
"data-[state=closed]:fade-out-0",
|
||||
"data-[state=closed]:duration-100",
|
||||
"data-[state=closed]:ease-in",
|
||||
"motion-reduce:animate-none",
|
||||
"motion-reduce:transition-none",
|
||||
);
|
||||
});
|
||||
|
||||
it("uses an intentional content motion contract", () => {
|
||||
// Given
|
||||
renderOpenDialog();
|
||||
|
||||
// When
|
||||
const dialog = screen.getByRole("dialog", { name: "Launch scan" });
|
||||
|
||||
// Then
|
||||
expect(dialog).toHaveClass(
|
||||
"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",
|
||||
"motion-reduce:animate-none",
|
||||
"motion-reduce:transform-none",
|
||||
"motion-reduce:transition-none",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -37,7 +37,7 @@ function DialogOverlay({
|
||||
<DialogPrimitive.Overlay
|
||||
data-slot="dialog-overlay"
|
||||
className={cn(
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
||||
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50 duration-200 ease-out data-[state=closed]:duration-100 data-[state=closed]:ease-in motion-reduce:animate-none motion-reduce:transition-none",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -59,7 +59,7 @@ function DialogContent({
|
||||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||
"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg 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 sm:max-w-lg",
|
||||
className,
|
||||
)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
|
||||
Reference in New Issue
Block a user