mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-05 03:12:14 +00:00
feat(ui): add Drawer content transition
- Animate drawer overlay and directional content states - Preserve reduced-motion behavior - Cover Drawer motion with focused unit tests
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
DrawerDescription,
|
||||
DrawerTitle,
|
||||
DrawerTrigger,
|
||||
} from "./drawer";
|
||||
|
||||
function renderOpenDrawer() {
|
||||
return render(
|
||||
<Drawer open>
|
||||
<DrawerTrigger>Open drawer</DrawerTrigger>
|
||||
<DrawerContent>
|
||||
<DrawerTitle>Resource details</DrawerTitle>
|
||||
<DrawerDescription>Review resource metadata</DrawerDescription>
|
||||
</DrawerContent>
|
||||
</Drawer>,
|
||||
);
|
||||
}
|
||||
|
||||
describe("Drawer", () => {
|
||||
it("renders controlled content through the Vaul Drawer API", () => {
|
||||
// Given
|
||||
renderOpenDrawer();
|
||||
|
||||
// When
|
||||
const drawer = screen.getByRole("dialog", { name: "Resource details" });
|
||||
|
||||
// Then
|
||||
expect(drawer).toBeVisible();
|
||||
expect(drawer).toHaveAttribute("data-slot", "drawer-content");
|
||||
expect(screen.getByText("Review resource metadata")).toBeVisible();
|
||||
});
|
||||
|
||||
it("uses an intentional overlay motion contract", () => {
|
||||
// Given
|
||||
renderOpenDrawer();
|
||||
|
||||
// When
|
||||
const overlay = document.querySelector("[data-slot='drawer-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 direction-aware drawer content motion", () => {
|
||||
// Given
|
||||
renderOpenDrawer();
|
||||
|
||||
// When
|
||||
const drawer = screen.getByRole("dialog", { name: "Resource details" });
|
||||
|
||||
// Then
|
||||
expect(drawer).toHaveClass(
|
||||
"duration-200",
|
||||
"ease-out",
|
||||
"data-[state=open]:animate-in",
|
||||
"data-[state=closed]:animate-out",
|
||||
"data-[state=closed]:duration-100",
|
||||
"data-[state=closed]:ease-in",
|
||||
"data-[vaul-drawer-direction=bottom]:slide-in-from-bottom-full",
|
||||
"data-[vaul-drawer-direction=bottom]:data-[state=closed]:slide-out-to-bottom-full",
|
||||
"data-[vaul-drawer-direction=top]:slide-in-from-top-full",
|
||||
"data-[vaul-drawer-direction=top]:data-[state=closed]:slide-out-to-top-full",
|
||||
"data-[vaul-drawer-direction=right]:slide-in-from-right-full",
|
||||
"data-[vaul-drawer-direction=right]:data-[state=closed]:slide-out-to-right-full",
|
||||
"data-[vaul-drawer-direction=left]:slide-in-from-left-full",
|
||||
"data-[vaul-drawer-direction=left]:data-[state=closed]:slide-out-to-left-full",
|
||||
"motion-reduce:animate-none",
|
||||
"motion-reduce:transform-none",
|
||||
"motion-reduce:transition-none",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -35,7 +35,7 @@ function DrawerOverlay({
|
||||
<DrawerPrimitive.Overlay
|
||||
data-slot="drawer-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}
|
||||
@@ -54,11 +54,11 @@ function DrawerContent({
|
||||
<DrawerPrimitive.Content
|
||||
data-slot="drawer-content"
|
||||
className={cn(
|
||||
"group/drawer-content bg-background fixed z-50 flex h-auto flex-col",
|
||||
"data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
|
||||
"data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
|
||||
"data-[vaul-drawer-direction=right]:border-l-border-neutral-secondary data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:border-l",
|
||||
"data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:border-r",
|
||||
"group/drawer-content bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex h-auto flex-col 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",
|
||||
"data-[vaul-drawer-direction=top]:slide-in-from-top-full data-[vaul-drawer-direction=top]:data-[state=closed]:slide-out-to-top-full data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
|
||||
"data-[vaul-drawer-direction=bottom]:slide-in-from-bottom-full data-[vaul-drawer-direction=bottom]:data-[state=closed]:slide-out-to-bottom-full data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
|
||||
"data-[vaul-drawer-direction=right]:border-l-border-neutral-secondary data-[vaul-drawer-direction=right]:slide-in-from-right-full data-[vaul-drawer-direction=right]:data-[state=closed]:slide-out-to-right-full data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:border-l",
|
||||
"data-[vaul-drawer-direction=left]:slide-in-from-left-full data-[vaul-drawer-direction=left]:data-[state=closed]:slide-out-to-left-full data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:border-r",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user