UNPKG

@octopusdeploy/design-system-components

Version:
96 lines (95 loc) 5.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PageSideNav = PageSideNav; exports.isPageSideNavLink = isPageSideNavLink; const jsx_runtime_1 = require("react/jsx-runtime"); const css_1 = require("@emotion/css"); const design_system_tokens_1 = require("@octopusdeploy/design-system-tokens"); const routing_1 = require("../../routing"); const Divider_1 = require("../Divider"); function PageSideNav({ items, tourProgress, description, isSticky }) { return ((0, jsx_runtime_1.jsxs)("nav", { "data-amplitude-unmask": true, className: (0, css_1.cx)(pageSideNavStyles, { [pageSideNavStickyStyles]: isSticky }), children: [tourProgress, (0, jsx_runtime_1.jsx)("div", { className: pageSideNavLinksContainerStyles, children: items.map((item, index) => ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(PageSideNavItem, { item: item }) }, index))) }), description && (0, jsx_runtime_1.jsx)("div", { className: descriptionStyles, children: description })] })); } function PageSideNavItem({ item }) { return isPageSideNavLink(item) ? ((0, jsx_runtime_1.jsx)(PageSideNavLink, { item: item })) : ((0, jsx_runtime_1.jsx)("div", { className: dividerWrapper, children: (0, jsx_runtime_1.jsx)(Divider_1.Divider, {}) })); } function PageSideNavLink({ item }) { const Link = (0, routing_1.useOctopusLinkComponent)(); const isUrlActive = (0, routing_1.useIsUrlActive)(); const urlIsActive = isUrlActive(item.path, item.exact ? "if path matches exactly" : "if path partially matches"); const handleClick = (event) => { const target = event.currentTarget; const label = target.innerText ?? target.getAttribute("aria-label") ?? ""; const href = target.href; item?.onClick(label, href); }; return ((0, jsx_runtime_1.jsx)(Link, { href: item.path, className: urlIsActive ? selectedLinkStyles : linkStyles, onClick: handleClick, disableImplicitEventTracking: true, children: item.label })); } function isPageSideNavLink(item) { return item !== "divider"; } const pageSideNavStyles = (0, css_1.css)({ color: design_system_tokens_1.themeTokens.color.text.primary, font: design_system_tokens_1.text.body.regular.medium, display: "flex", flexDirection: "column", flexShrink: 0, gap: design_system_tokens_1.space[16], padding: `${design_system_tokens_1.space[16]} ${design_system_tokens_1.space[16]} ${design_system_tokens_1.space[24]} ${design_system_tokens_1.space[32]}`, width: "15rem", }); const pageSideNavStickyStyles = (0, css_1.css)({ position: "sticky", top: 0, alignSelf: "flex-start", maxHeight: "100vh", overflowY: "auto", }); const pageSideNavLinksContainerStyles = (0, css_1.css)({ display: "flex", flexDirection: "column", gap: design_system_tokens_1.space[2], }); const dividerWrapper = (0, css_1.css)({ padding: `${design_system_tokens_1.space[16]} 0`, marginLeft: design_system_tokens_1.space[8], maxWidth: "5.125rem", }); const descriptionStyles = (0, css_1.css)({ padding: `${design_system_tokens_1.space[24]} ${design_system_tokens_1.space[8]} ${design_system_tokens_1.space[24]} ${design_system_tokens_1.space[8]}`, overflowWrap: "break-word", // The description can contain words that are too long to fit in the sidebar, we should break these words to avoid overflowing font: design_system_tokens_1.text.body.regular.small, }); const linkStyles = (0, css_1.css)({ color: design_system_tokens_1.themeTokens.color.navList.text.default, height: "2rem", display: "flex", alignItems: "center", padding: `0 ${design_system_tokens_1.space[8]} 0 ${design_system_tokens_1.space[12]}`, borderRadius: design_system_tokens_1.borderRadius.small, ":hover": { color: design_system_tokens_1.themeTokens.color.navList.text.hover, backgroundColor: design_system_tokens_1.themeTokens.color.navList.background.hover, }, ":active": { color: design_system_tokens_1.themeTokens.color.navList.text.active, background: design_system_tokens_1.themeTokens.color.navList.background.active, }, ":focus-visible": { boxShadow: design_system_tokens_1.themeTokens.shadow.focused, outline: "none", }, }); const selectedLinkStyles = (0, css_1.cx)(linkStyles, (0, css_1.css)({ color: design_system_tokens_1.themeTokens.color.navList.text.active, background: buildBackgroundGradient(design_system_tokens_1.themeTokens.color.border.selected, design_system_tokens_1.themeTokens.color.navList.background.active), ":hover": { // We need to re-apply the same styles here because we have global css trying to style this hover state color: design_system_tokens_1.themeTokens.color.navList.text.active, background: buildBackgroundGradient(design_system_tokens_1.themeTokens.color.border.selected, design_system_tokens_1.themeTokens.color.navList.background.active), }, })); // This creates a background with a solid border on the left edge function buildBackgroundGradient(borderColor, backgroundColor) { return `linear-gradient(90deg, ${borderColor} 0%, ${borderColor} ${design_system_tokens_1.space[4]}, ${backgroundColor} ${design_system_tokens_1.space[4]}, ${backgroundColor} 100%)`; }