From 27fa9af9593d750a51f34f5f0b8ff3517896594a Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Sat, 5 Sep 2026 17:28:45 +0100 Subject: [PATCH] fix: public page print (#2476) * fix pdf-print for public pages * fix print in dark mode --- .../components/docs/docs-shell.tsx | 41 ++++++++++++++ .../components/docs/docs.module.css | 56 +++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/apps/client/src/features/public-space/components/docs/docs-shell.tsx b/apps/client/src/features/public-space/components/docs/docs-shell.tsx index 1b630644f..4aa48c623 100644 --- a/apps/client/src/features/public-space/components/docs/docs-shell.tsx +++ b/apps/client/src/features/public-space/components/docs/docs-shell.tsx @@ -25,6 +25,8 @@ import { SearchMobileControl } from "@/features/search/components/search-control import styles from "./docs.module.css"; const MemoizedDocsSidebarTree = React.memo(DocsSidebarTree); +const MANTINE_COLOR_SCHEME_ATTRIBUTE = "data-mantine-color-scheme"; +const DOCS_PRINT_COLOR_SCHEME_ATTRIBUTE = "data-docs-print-color-scheme"; type DocsShellProps = { surface: DocsSurface; @@ -47,6 +49,45 @@ export default function DocsShell({ ); const [mobileTocOpen, setMobileTocOpen] = useAtom(docsMobileTocAtom); + React.useEffect(() => { + const root = document.documentElement; + let previousColorScheme: string | null = null; + let isPrinting = false; + + const restoreColorScheme = () => { + if (!isPrinting) return; + + if (previousColorScheme === null) { + root.removeAttribute(MANTINE_COLOR_SCHEME_ATTRIBUTE); + } else { + root.setAttribute(MANTINE_COLOR_SCHEME_ATTRIBUTE, previousColorScheme); + } + root.removeAttribute(DOCS_PRINT_COLOR_SCHEME_ATTRIBUTE); + isPrinting = false; + }; + + const useLightPrintTheme = () => { + if (isPrinting) return; + + previousColorScheme = root.getAttribute(MANTINE_COLOR_SCHEME_ATTRIBUTE); + root.setAttribute( + DOCS_PRINT_COLOR_SCHEME_ATTRIBUTE, + previousColorScheme ?? "light", + ); + root.setAttribute(MANTINE_COLOR_SCHEME_ATTRIBUTE, "light"); + isPrinting = true; + }; + + window.addEventListener("beforeprint", useLightPrintTheme); + window.addEventListener("afterprint", restoreColorScheme); + + return () => { + window.removeEventListener("beforeprint", useLightPrintTheme); + window.removeEventListener("afterprint", restoreColorScheme); + restoreColorScheme(); + }; + }, []); + return (
diff --git a/apps/client/src/features/public-space/components/docs/docs.module.css b/apps/client/src/features/public-space/components/docs/docs.module.css index 6f008a429..2822bc4ce 100644 --- a/apps/client/src/features/public-space/components/docs/docs.module.css +++ b/apps/client/src/features/public-space/components/docs/docs.module.css @@ -900,3 +900,59 @@ display: flex; flex-direction: column; } + +/* ---------- Print ---------- */ + +@page public-doc { + background-color: #fff; +} + +/* Only the article prints; the body grid collapses so it takes the page width. */ +@media print { + :global(html):has(.root), + :global(body):has(.root) { + page: public-doc; + background-color: #fff !important; + } + + :global(html[data-docs-print-color-scheme="dark"]) + .root.root + :global(.codeBlock svg) { + filter: invert(1) hue-rotate(180deg); + } + + .header, + .sidebar, + .toc, + .articleActions, + .breadcrumbs, + .pageNav, + .footer { + display: none !important; + } + + .root { + --docs-bg: #fff; + --docs-fg: #1f1f1f; + --docs-content-fg: var(--docs-fg); + --docs-nav-fg: #495057; + --docs-muted: #5f6368; + --docs-hover: #f1f3f5; + --docs-faint: #868e96; + --docs-border: #dee2e6; + --docs-header-bg: #fff; + + min-height: 0; + background-color: #fff; + color: var(--docs-fg); + } + + .body { + display: block; + } + + .article { + max-width: none; + padding: 0; + } +}