import React from "react"; import { ActionIcon, Drawer, Tooltip } from "@mantine/core"; import { Link } from "react-router-dom"; import { useAtom } from "jotai"; import { useTranslation } from "react-i18next"; import { IconList, IconMenu2 } from "@tabler/icons-react"; import clsx from "clsx"; import { docsMobileSidebarAtom, docsMobileTocAtom, } from "@/features/public-space/atoms/public-space-atoms.ts"; import { DocsSurface, DocsSurfaceProvider, } from "@/features/public-space/components/docs/docs-surface-context.tsx"; import DocsSidebarTree from "@/features/public-space/components/docs/docs-sidebar-tree.tsx"; import DocsToc from "@/features/public-space/components/docs/docs-toc.tsx"; import DocsEditPage from "@/features/public-space/components/docs/docs-edit-page.tsx"; import DocsCopyPage from "@/features/public-space/components/docs/docs-copy-page.tsx"; import DocsSearchButton from "@/features/public-space/components/docs/docs-search-button.tsx"; import DocsThemeToggle from "@/features/public-space/components/docs/docs-theme-toggle.tsx"; import DocsFooterBranding from "@/features/public-space/components/docs/docs-footer-branding.tsx"; import { MAIN_CONTENT_ID, SkipToMain } from "@/components/ui/skip-to-main.tsx"; import { SearchMobileControl } from "@/features/search/components/search-control.tsx"; 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; onSearchOpen?: () => void; searchSpotlight?: React.ReactNode; children: React.ReactNode; }; export default function DocsShell({ surface, onSearchOpen, searchSpotlight, children, }: DocsShellProps) { const { t } = useTranslation(); const { hasSidebar, siteName, homeUrl, showBranding, showEditPage } = surface; const [mobileSidebarOpen, setMobileSidebarOpen] = useAtom( docsMobileSidebarAtom, ); 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 (
{hasSidebar && ( setMobileSidebarOpen((value) => !value)} aria-label={t("Toggle sidebar")} aria-expanded={mobileSidebarOpen} > )} {!hasSidebar && siteName && homeUrl && ( {siteName} )}
{onSearchOpen && (
)}
{onSearchOpen && ( )}
setMobileTocOpen(true)} size="md" aria-label={t("Table of contents")} >
{children} {showBranding && ( )}
setMobileSidebarOpen(false)} title={siteName} size={300} padding="sm" >
{hasSidebar && }
setMobileTocOpen(false)} position="right" size={300} padding="md" > {showEditPage && } {searchSpotlight}
); }