diff --git a/src/components/platformSelector/index.tsx b/src/components/platformSelector/index.tsx index 85a97fcbf270d1..8463900d678afd 100644 --- a/src/components/platformSelector/index.tsx +++ b/src/components/platformSelector/index.tsx @@ -20,7 +20,7 @@ import {uniqByReference} from 'sentry-docs/utils'; import styles from './style.module.scss'; -import {SidebarLink} from '../sidebarLink'; +import {SidebarLink, SidebarSeparator} from '../sidebar/sidebarLink'; export function PlatformSelector({ platforms, @@ -240,19 +240,14 @@ export function PlatformSelector({ {showStoredPlatform && ( -
- -
+
+ +
)}
diff --git a/src/components/sidebarLink.tsx b/src/components/sidebar/collapsibleSidebarLink.tsx similarity index 52% rename from src/components/sidebarLink.tsx rename to src/components/sidebar/collapsibleSidebarLink.tsx index db38cf81ae8cd6..345c6e94c95859 100644 --- a/src/components/sidebarLink.tsx +++ b/src/components/sidebar/collapsibleSidebarLink.tsx @@ -1,11 +1,10 @@ 'use client'; import {Children, useState} from 'react'; -import styled from '@emotion/styled'; import {getUnversionedPath} from 'sentry-docs/versioning'; -import {SmartLink} from './smartLink'; +import {SidebarLink} from './sidebarLink'; interface SidebarLinkProps { /** @@ -29,7 +28,11 @@ interface SidebarLinkProps { collapsed?: boolean | null; } -export function SidebarLink({ +/** + * This client component is used to render a collapsible sidebar link. + * It is only used by the DynamicNav component. + */ +export function CollapsibleSidebarLink({ to, title, children, @@ -45,55 +48,20 @@ export function SidebarLink({ return (
  • - { // Allow toggling the sidebar subtree only if the item is selected if (path === to) { setShowSubtree(v => enableSubtree && !v); } }} - > - {title || children} - {hasSubtree && } - - {title && children && } + /> + {showSubtree && }
  • ); } - -const SidebarNavItem = styled(SmartLink)` - display: flex; - align-items: center; - justify-content: space-between; - gap: 4px; -`; - -const rotation = { - down: 0, - right: 270, -} as const; - -interface ChevronProps extends React.SVGAttributes { - direction: keyof typeof rotation; -} - -const Chevron = styled(({direction: _, ...props}: ChevronProps) => ( - - - -))` - transition: transform 200ms; - transform: rotate(${p => rotation[p.direction]}deg); -`; diff --git a/src/components/sidebar/defaultSidebar.tsx b/src/components/sidebar/defaultSidebar.tsx deleted file mode 100644 index 215c604a4af474..00000000000000 --- a/src/components/sidebar/defaultSidebar.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import {Fragment} from 'react'; -import {Link} from 'react-feather'; - -import styles from './style.module.scss'; - -import {NavChevron} from './navChevron'; -import {DefaultSidebarProps, SidebarNode} from './types'; - -export function DefaultSidebar({node, path}: DefaultSidebarProps) { - const activeClassName = (n: SidebarNode, baseClassName = '') => { - const className = n.path === path.join('/') ? 'active' : ''; - return `${baseClassName} ${className}`; - }; - - const renderChildren = (children: SidebarNode[]) => - children && ( - - ); - - return ( - - ); -} diff --git a/src/components/sidebar/developDocsSidebar.tsx b/src/components/sidebar/developDocsSidebar.tsx index d96194e4088b8d..e62dc34dcdc228 100644 --- a/src/components/sidebar/developDocsSidebar.tsx +++ b/src/components/sidebar/developDocsSidebar.tsx @@ -2,9 +2,8 @@ import {DocNode, nodeForPath} from 'sentry-docs/docTree'; import styles from './style.module.scss'; -import {SidebarLink} from '../sidebarLink'; - import {DynamicNav, toTree} from './dynamicNav'; +import {SidebarLink, SidebarSeparator} from './sidebarLink'; import {NavNode} from './types'; import {docNodeToNavNode, getNavNodes} from './utils'; @@ -23,7 +22,6 @@ const devDocsMenuItems: {root: string; title: string}[] = [ ]; export function DevelopDocsSidebar({ - path, rootNode, sidebarToggleId, }: { @@ -55,18 +53,13 @@ export function DevelopDocsSidebar({ /> ))} -
    + diff --git a/src/components/sidebar/dynamicNav.tsx b/src/components/sidebar/dynamicNav.tsx index 10e2ee66435f8f..bf144120f871b0 100644 --- a/src/components/sidebar/dynamicNav.tsx +++ b/src/components/sidebar/dynamicNav.tsx @@ -4,12 +4,8 @@ import {serverContext} from 'sentry-docs/serverContext'; import {sortPages} from 'sentry-docs/utils'; import {getUnversionedPath, VERSION_INDICATOR} from 'sentry-docs/versioning'; -import styles from './style.module.scss'; - -import {SidebarLink} from '../sidebarLink'; -import {SmartLink} from '../smartLink'; - -import {NavChevron} from './navChevron'; +import {CollapsibleSidebarLink} from './collapsibleSidebarLink'; +import {SidebarLink} from './sidebarLink'; type Node = { [key: string]: any; @@ -83,7 +79,7 @@ export const renderChildren = ( return null; } return ( - {renderChildren(nodeChildren, exclude, path, showDepth, depth + 1)} - + ); }); }; @@ -142,6 +138,9 @@ export function DynamicNav({ if (!title && entity.node) { title = entity.node.context.sidebar_title || entity.node.context.title || ''; } + if (!title) { + return null; + } const parentNode = entity.children?.find((n: EntityTree) => n.name === ''); if (!parentNode) { @@ -153,15 +152,14 @@ export function DynamicNav({ const linkPath = `/${path.join('/')}/`; const header = ( - - {title} - {collapsible && } - + /> ); return ( diff --git a/src/components/sidebar/index.tsx b/src/components/sidebar/index.tsx index 08188f92f2ec58..dcb5b3a0089767 100644 --- a/src/components/sidebar/index.tsx +++ b/src/components/sidebar/index.tsx @@ -15,7 +15,7 @@ import {PlatformSelector} from '../platformSelector'; import {VersionSelector} from '../versionSelector'; import {DevelopDocsSidebar} from './developDocsSidebar'; -import {SidebarLinks} from './sidebarLinks'; +import {SidebarNavigation} from './sidebarNavigation'; import {SidebarProps} from './types'; const activeLinkSelector = `.${styles.sidebar} .toc-item .active`; @@ -100,7 +100,7 @@ export async function Sidebar({path, versions}: SidebarProps) {
    - +
    diff --git a/src/components/sidebar/productSidebar.tsx b/src/components/sidebar/productSidebar.tsx index a43d48f1142a16..0425a4a0440c1a 100644 --- a/src/components/sidebar/productSidebar.tsx +++ b/src/components/sidebar/productSidebar.tsx @@ -1,8 +1,7 @@ import {nodeForPath} from 'sentry-docs/docTree'; -import {SidebarLink} from '../sidebarLink'; - import {DynamicNav, toTree} from './dynamicNav'; +import {SidebarLink, SidebarSeparator} from './sidebarLink'; import {NavNode, ProductSidebarProps} from './types'; import {docNodeToNavNode, getNavNodes} from './utils'; @@ -34,26 +33,20 @@ export function ProductSidebar({rootNode, items}: ProductSidebarProps) { ); })} -
    +
      • - - - + + +
    • diff --git a/src/components/sidebar/sidebarLink.tsx b/src/components/sidebar/sidebarLink.tsx new file mode 100644 index 00000000000000..10b50564545b0a --- /dev/null +++ b/src/components/sidebar/sidebarLink.tsx @@ -0,0 +1,44 @@ +import Link from 'next/link'; + +import styles from './style.module.scss'; + +import {ExternalLink} from '../externalLink'; + +import {NavChevron} from './navChevron'; + +export function SidebarLink({ + title, + href, + isActive, + collapsible, + onClick, + topLevel = false, +}: { + href: string; + title: string; + collapsible?: boolean; + isActive?: boolean; + onClick?: () => void; + topLevel?: boolean; +}) { + const isRemote = href.includes('://'); + const LinkComponent = isRemote ? ExternalLink : Link; + + return ( + +
      {title}
      + {collapsible && } +
      + ); +} + +export function SidebarSeparator() { + return
      ; +} diff --git a/src/components/sidebar/sidebarLinks.tsx b/src/components/sidebar/sidebarNavigation.tsx similarity index 85% rename from src/components/sidebar/sidebarLinks.tsx rename to src/components/sidebar/sidebarNavigation.tsx index a22e65a1f75f4f..fb2502e3de077b 100644 --- a/src/components/sidebar/sidebarLinks.tsx +++ b/src/components/sidebar/sidebarNavigation.tsx @@ -2,10 +2,10 @@ import {Fragment} from 'react'; import {getDocsRootNode, nodeForPath} from 'sentry-docs/docTree'; -import {DefaultSidebar} from './defaultSidebar'; import {DynamicNav, toTree} from './dynamicNav'; import {PlatformSidebar} from './platformSidebar'; import {ProductSidebar} from './productSidebar'; +import {SidebarSeparator} from './sidebarLink'; import {NavNode} from './types'; import {docNodeToNavNode, getNavNodes} from './utils'; @@ -46,14 +46,16 @@ const productSidebarItems = [ }, ]; -export async function SidebarLinks({path}: {path: string[]}) { +export async function SidebarNavigation({path}: {path: string[]}) { const rootNode = await getDocsRootNode(); + // product docs and platform-redirect page if ( productSidebarItems.some(el => el.root === path[0]) || path[0] === 'platform-redirect' ) { return ; } + // /platforms/:platformName/guides/:guideName if (path[0] === 'platforms') { const platformName = path[1]; @@ -67,13 +69,15 @@ export async function SidebarLinks({path}: {path: string[]}) { guideName={guideName} rootNode={rootNode} /> -
      + )} ); } + + // contributing pages if (path[0] === 'contributing') { const contribNode = nodeForPath(rootNode, 'contributing'); if (contribNode) { @@ -89,6 +93,7 @@ export async function SidebarLinks({path}: {path: string[]}) { ); } } - // render the default sidebar if no special case is met - return ; + + // This should never happen, all cases need to be handled above + throw new Error(`Unknown path: ${path.join('/')} - cannot render sidebar`); } diff --git a/src/components/sidebar/style.module.scss b/src/components/sidebar/style.module.scss index c55c50e0a8eaa0..2c0b5c169833b5 100644 --- a/src/components/sidebar/style.module.scss +++ b/src/components/sidebar/style.module.scss @@ -62,9 +62,7 @@ } } - ul + hr { - margin-top: 1rem; - margin-bottom: 1rem; + .sidebar-separator { border-top: 1px solid var(--border-color); } @@ -114,25 +112,21 @@ } } -.sidebar-title { +.sidebar-link-top-level { font-weight: 500; - margin-bottom: 2px; + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 0.2px; + color: inherit; +} + +.sidebar-link { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.25rem; &.active { background-color: var(--brandDecoration); - - strong { - color: #fff; - } - } - - strong { - display: block; - margin-bottom: 0; - font-size: 0.8rem; - text-transform: uppercase; - letter-spacing: 0.2px; - color: inherit; - font-weight: inherit; } }