UNPKG

shelving

Version:

Toolkit for using data in JavaScript.

30 lines (29 loc) 2.46 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/solid"; import { useEffect, useState } from "react"; import { Button } from "../form/Button.js"; import { requireMetaURL } from "../misc/MetaContext.js"; import { getClass } from "../util/css.js"; import { LAYOUT_CLASS } from "./Layout.js"; import SIDEBAR_LAYOUT_CSS from "./SidebarLayout.module.css"; /** * Layout with a fixed-width side column (typically navigation) next to a scrollable main content column. * - The sidebar is rendered as `<nav>` — it almost always contains the page's primary navigation. * - On narrow viewports the sidebar becomes an off-canvas drawer toggled by a single menu button that switches between a burger and a close icon. * - While the drawer is open an overlay dims the rest of the page; clicking the overlay closes the drawer. * - Inside a `<Navigation>` the drawer closes itself whenever the route changes (e.g. tapping a sidebar link). * - Use the `--sidebar-layout-width`, `--sidebar-layout-bg`, `--sidebar-layout-border`, and `--sidebar-layout-color-border` custom properties to override defaults. */ export function SidebarLayout({ sidebar, children, right = false }) { const { path } = requireMetaURL(); const [open, setOpen] = useState(false); // Close the drawer whenever navigation changes the URL — covers tapping a link inside the sidebar. useEffect(() => { if (path) setOpen(false); }, [path]); const sidebarEl = (_jsx("nav", { className: getClass(SIDEBAR_LAYOUT_CSS.sidebar, open && SIDEBAR_LAYOUT_CSS.open), children: sidebar }, "sidebar")); const contentEl = (_jsxs("div", { className: getClass(LAYOUT_CLASS, SIDEBAR_LAYOUT_CSS.content), children: [_jsx("div", { className: SIDEBAR_LAYOUT_CSS.toggle, children: _jsx(Button, { fit: true, title: open ? "Close menu" : "Show menu", onClick: () => setOpen(o => !o), children: open ? _jsx(XMarkIcon, {}) : _jsx(Bars3Icon, {}) }) }), _jsx("div", { className: SIDEBAR_LAYOUT_CSS.contentInner, children: children })] }, path)); const overlayEl = open && (_jsx("button", { type: "button", className: SIDEBAR_LAYOUT_CSS.overlay, "aria-label": "Close menu", onClick: () => setOpen(false) }, "overlay")); return (_jsx("main", { className: getClass(SIDEBAR_LAYOUT_CSS.main, LAYOUT_CLASS), children: right ? [contentEl, sidebarEl, overlayEl] : [sidebarEl, contentEl, overlayEl] })); }