From bce75355c01627698dae4c58c5c321f92eb7e29e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Wed, 15 Jul 2026 19:11:27 +0200 Subject: [PATCH] Extract documents page layout into a tv variant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The results container hand-wrote its layout classes and toggled the dimmed state with a string-interpolated conditional. Move both the page shell and the busy/dimmed state into a documentsLayout tv variant, and reuse it in the skeleton so the loading and loaded layouts share one source of truth. Signed-off-by: Émile Ré --- .../src/pages/documents/DocumentsPage.tsx | 10 ++--- .../pages/documents/DocumentsPageSkeleton.tsx | 8 +++- .../src/pages/documents/variants.ts | 39 +++++++++++++++++++ 3 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 apps/compliance-portal/src/pages/documents/variants.ts diff --git a/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx b/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx index 96294406c..e115d0e68 100644 --- a/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx +++ b/apps/compliance-portal/src/pages/documents/DocumentsPage.tsx @@ -38,6 +38,7 @@ import { TrustCenterFileListItem } from "./_components/TrustCenterFileListItem"; import { groupByField } from "./_lib/groupByField"; import { toQueryVariables } from "./_lib/toQueryVariables"; import { useDocumentTab } from "./_lib/useDocumentTab"; +import { documentsLayout } from "./variants"; export const documentsPageQuery = graphql` query DocumentsPageQuery($visibility: TrustCenterVisibility) { @@ -129,16 +130,15 @@ export function DocumentsPage({ queryRef }: DocumentsPageProps) { const fileGroups = groupByField(fileNodes, node => node.category) .sort((a, b) => a.key.localeCompare(b.key)); + const { page, results } = documentsLayout({ busy: isRefetching }); + return ( <> -
-
+
+
startTransition(() => { refetch(toQueryVariables(tab), { fetchPolicy: "network-only", onComplete: done }); diff --git a/apps/compliance-portal/src/pages/documents/DocumentsPageSkeleton.tsx b/apps/compliance-portal/src/pages/documents/DocumentsPageSkeleton.tsx index b7c6e4c0a..eed51dab9 100644 --- a/apps/compliance-portal/src/pages/documents/DocumentsPageSkeleton.tsx +++ b/apps/compliance-portal/src/pages/documents/DocumentsPageSkeleton.tsx @@ -24,10 +24,14 @@ import { TextSkeleton } from "@probo/ui/src/v2/typography/TextSkeleton"; import { HeaderBand } from "#/components/HeaderBand/HeaderBand"; +import { documentsLayout } from "./variants"; + const SECTION_PLACEHOLDERS = ["a", "b"]; const ROW_PLACEHOLDERS = ["x", "y", "z"]; export function DocumentsPageSkeleton() { + const { page, results } = documentsLayout(); + return ( <> @@ -36,8 +40,8 @@ export function DocumentsPageSkeleton() {
-
-
+
+
{SECTION_PLACEHOLDERS.map(section => (
diff --git a/apps/compliance-portal/src/pages/documents/variants.ts b/apps/compliance-portal/src/pages/documents/variants.ts new file mode 100644 index 000000000..10da65c80 --- /dev/null +++ b/apps/compliance-portal/src/pages/documents/variants.ts @@ -0,0 +1,39 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import { tv } from "tailwind-variants/lite"; + +// Documents page shell: a centered content column below the header band. The +// `busy` variant dims the current results while a filtered slice refetches. +export const documentsLayout = tv({ + slots: { + page: "flex w-full flex-col items-center px-8 py-8", + results: "flex w-full max-w-5xl flex-col gap-8 transition-opacity duration-150", + }, + variants: { + busy: { + true: { results: "opacity-60" }, + false: {}, + }, + }, + defaultVariants: { + busy: false, + }, +});