From b5756e16b50f5743402815679c268e67a9dd5244 Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Tue, 9 Jun 2026 15:09:37 +0200 Subject: [PATCH] refactor(web): shared DetailDrawer; objects-page uses it (#58) --- web/src/components/detail-drawer.test.tsx | 20 ++++++++++++++++++ .../detail-drawer.tsx} | 21 +++++++++---------- web/src/objects/objects-page.tsx | 15 +++++-------- 3 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 web/src/components/detail-drawer.test.tsx rename web/src/{objects/object-detail-drawer.tsx => components/detail-drawer.tsx} (62%) diff --git a/web/src/components/detail-drawer.test.tsx b/web/src/components/detail-drawer.test.tsx new file mode 100644 index 0000000..193032a --- /dev/null +++ b/web/src/components/detail-drawer.test.tsx @@ -0,0 +1,20 @@ +import { expect, test, vi } from "vitest"; +import { within } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import { renderApp } from "../test/render"; +import { DetailDrawer } from "./detail-drawer"; + +test("renders children in a named drawer and closes via the close button", async () => { + const onClose = vi.fn(); + renderApp( + +

detail body

+
, + ); + + const body = within(document.body); + expect(await body.findByText("detail body")).toBeInTheDocument(); + await userEvent.click(body.getByRole("button", { name: /close detail/i })); + expect(onClose).toHaveBeenCalled(); +}); diff --git a/web/src/objects/object-detail-drawer.tsx b/web/src/components/detail-drawer.tsx similarity index 62% rename from web/src/objects/object-detail-drawer.tsx rename to web/src/components/detail-drawer.tsx index 84cc341..6932f8b 100644 --- a/web/src/objects/object-detail-drawer.tsx +++ b/web/src/components/detail-drawer.tsx @@ -1,21 +1,22 @@ -import { Outlet } from "react-router-dom"; +import type { ReactNode } from "react"; import { useTranslation } from "react-i18next"; import { X } from "lucide-react"; import { Drawer, DrawerClose, DrawerContent } from "@/components/ui/drawer"; import { Button } from "@/components/ui/button"; -/** - * Narrow-viewport object detail: the nested inside a Base UI Drawer that - * slides from the right. Lazy-loaded so Base UI's drawer code (swipe/snap machinery) - * splits out of the main entry chunk — the wide pane path never pays for it. - */ -export function ObjectDetailDrawer({ +/** A right-sliding Base UI Drawer for a master/detail "detail" on narrow viewports. + * Provides the close affordance + an accessible dialog name; the caller supplies the content. */ +export function DetailDrawer({ open, onClose, + ariaLabel, + children, }: { open: boolean; onClose: () => void; + ariaLabel: string; + children: ReactNode; }) { const { t } = useTranslation(); @@ -27,7 +28,7 @@ export function ObjectDetailDrawer({ }} swipeDirection="right" > - +
-
- -
+
{children}
); diff --git a/web/src/objects/objects-page.tsx b/web/src/objects/objects-page.tsx index ad823e6..0976942 100644 --- a/web/src/objects/objects-page.tsx +++ b/web/src/objects/objects-page.tsx @@ -1,19 +1,15 @@ -import { lazy, Suspense } from "react"; import { Outlet, useMatch, useNavigate, useSearchParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { X } from "lucide-react"; import { ObjectsTable } from "./objects-table"; +import { DetailDrawer } from "../components/detail-drawer"; import { useMediaQuery } from "../lib/use-media-query"; import { useDocumentTitle } from "../lib/use-document-title"; import { useBreadcrumb } from "../shell/use-breadcrumb"; import { Button } from "@/components/ui/button"; import { PageTitle } from "@/components/ui/page-title"; -const ObjectDetailDrawer = lazy(() => - import("./object-detail-drawer").then((m) => ({ default: m.ObjectDetailDrawer })), -); - export function ObjectsPage() { const { t } = useTranslation(); const navigate = useNavigate(); @@ -66,15 +62,14 @@ export function ObjectsPage() { ); } - // Narrow: the detail lives in a Drawer, lazy-loaded so Base UI's drawer code stays - // out of the main entry chunk. + // Narrow: the detail lives in a Drawer sliding from the right. return (
{table} {open && ( - - - + + + )}
);