docs: refactor sidebar link

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9922
GitOrigin-RevId: 21a1a62b354ad7eac4fd0daaceb2a565bfc444ae
This commit is contained in:
Rikin Kachhia 2023-07-20 18:15:37 +05:30 committed by hasura-bot
parent 05cfb65b54
commit 161569dd40
4 changed files with 133 additions and 135 deletions

View File

@ -1,6 +1,12 @@
import React, { useState, useEffect, useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import clsx from 'clsx';
import { ThemeClassNames, useThemeConfig, usePrevious, Collapsible, useCollapsible } from '@docusaurus/theme-common';
import {
ThemeClassNames,
useThemeConfig,
usePrevious,
Collapsible,
useCollapsible,
} from '@docusaurus/theme-common';
import {
isActiveSidebarItem,
findFirstCategoryLink,
@ -11,12 +17,8 @@ import Link from '@docusaurus/Link';
import { translate } from '@docusaurus/Translate';
import useIsBrowser from '@docusaurus/useIsBrowser';
import DocSidebarItems from '@theme/DocSidebarItems';
import { useColorMode } from '@docusaurus/theme-common';
import styles from './styles.module.scss';
import EnterpriseLight from '@site/static/icons/enterprise-dark.svg';
import EnterpriseDark from '@site/static/icons/enterprise-light.svg';
import CloudLight from '@site/static/icons/cloud-dark.svg';
import CloudDark from '@site/static/icons/cloud-light.svg';
import { addIconsToLabel } from '../utils';
// If we navigate to a category and it becomes active, it should automatically
// expand itself
@ -29,6 +31,7 @@ function useAutoExpandActiveCategory({ isActive, collapsed, updateCollapsed }) {
}
}, [isActive, wasActive, collapsed, updateCollapsed]);
}
/**
* When a collapsible category has no link, we still link it to its first child
* during SSR as a temporary fallback. This allows to be able to navigate inside
@ -51,6 +54,7 @@ function useCategoryHrefWithSSRFallback(item) {
return findFirstCategoryLink(item);
}, [item, isBrowser]);
}
function CollapseButton({ categoryLabel, onClick }) {
return (
<button
@ -58,7 +62,8 @@ function CollapseButton({ categoryLabel, onClick }) {
{
id: 'theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel',
message: "Toggle the collapsible sidebar category '{label}'",
description: 'The ARIA label to toggle the collapsible sidebar category',
description:
'The ARIA label to toggle the collapsible sidebar category',
},
{ label: categoryLabel }
)}
@ -68,49 +73,27 @@ function CollapseButton({ categoryLabel, onClick }) {
/>
);
}
export default function DocSidebarItemCategory({ item, onItemClick, activePath, level, index, ...props }) {
export default function DocSidebarItemCategory({
item,
onItemClick,
activePath,
level,
index,
...props
}) {
const { items, label, collapsible, className, href } = item;
const { colorMode } = useColorMode();
const [definedColorMode, setDefinedColorMode] = useState('');
useEffect(() => {
setDefinedColorMode(colorMode);
}, [colorMode]);
// Conditional rendering for sidebar icons
function addIcons(className) {
switch (className) {
case 'enterprise-icon':
return definedColorMode === 'dark' ? <EnterpriseDark /> : <EnterpriseLight />;
case 'cloud-icon':
return definedColorMode === 'dark' ? <CloudDark /> : <CloudLight />;
case 'cloud-and-enterprise-icon':
return (
<div className={styles['cloud-ee-container']}>
{definedColorMode === 'dark' ? (
<>
<CloudDark /> <EnterpriseDark />{' '}
</>
) : (
<>
<CloudLight /> <EnterpriseLight />
</>
)}
</div>
);
default:
return null;
}
}
const {
docs: {
sidebar: { autoCollapseCategories },
},
} = useThemeConfig();
const hrefWithSSRFallback = useCategoryHrefWithSSRFallback(item);
const isActive = isActiveSidebarItem(item, activePath);
const isCurrentPage = isSamePath(href, activePath);
const { collapsed, setCollapsed } = useCollapsible({
// Active categories are always initialized as expanded. The default
// (`item.collapsed`) is only used for non-active categories.
@ -121,18 +104,29 @@ export default function DocSidebarItemCategory({ item, onItemClick, activePath,
return isActive ? false : item.collapsed;
},
});
const { expandedItem, setExpandedItem } = useDocSidebarItemsExpandedState();
// Use this instead of `setCollapsed`, because it is also reactive
const updateCollapsed = (toCollapsed = !collapsed) => {
setExpandedItem(toCollapsed ? null : index);
setCollapsed(toCollapsed);
};
useAutoExpandActiveCategory({ isActive, collapsed, updateCollapsed });
useEffect(() => {
if (collapsible && expandedItem != null && expandedItem !== index && autoCollapseCategories) {
if (
collapsible &&
expandedItem != null &&
expandedItem !== index &&
autoCollapseCategories
) {
setCollapsed(true);
}
}, [collapsible, expandedItem, index, setCollapsed, autoCollapseCategories]);
const labelWithIcons = addIconsToLabel(label, className);
return (
<li
className={clsx(
@ -180,8 +174,7 @@ export default function DocSidebarItemCategory({ item, onItemClick, activePath,
href={collapsible ? hrefWithSSRFallback ?? '#' : hrefWithSSRFallback}
{...props}
>
{label}
{addIcons(className)}
{labelWithIcons}
</Link>
{href && collapsible && (
<CollapseButton

View File

@ -4,82 +4,43 @@ import { ThemeClassNames } from '@docusaurus/theme-common';
import { isActiveSidebarItem } from '@docusaurus/theme-common/internal';
import Link from '@docusaurus/Link';
import isInternalUrl from '@docusaurus/isInternalUrl';
import IconExternalLink from '@theme/Icon/ExternalLink';
import styles from './styles.module.scss';
import { useColorMode } from '@docusaurus/theme-common';
import EnterpriseLight from '@site/static/icons/enterprise-dark.svg';
import EnterpriseDark from '@site/static/icons/enterprise-light.svg';
import CloudLight from '@site/static/icons/cloud-dark.svg';
import CloudDark from '@site/static/icons/cloud-light.svg';
import BetaTag from '@site/src/components/BetaTag/BetaTag';
export default function DocSidebarItemLink({ item, onItemClick, activePath, level, index, ...props }) {
import { addIconsToLabel } from '../utils';
export default function DocSidebarItemLink({
item,
onItemClick,
activePath,
level,
index,
...props
}) {
const { href, label, className, autoAddBaseUrl } = item;
const isActive = isActiveSidebarItem(item, activePath);
const isInternalLink = isInternalUrl(href);
const { colorMode } = useColorMode();
// Conditional rendering for sidebar icons
function addIcons(className) {
switch (className) {
case 'enterprise-icon':
return colorMode === 'dark' ? <EnterpriseDark /> : <EnterpriseLight />;
case 'cloud-icon':
return colorMode === 'dark' ? <CloudDark /> : <CloudLight />;
case 'enterprise-icon-and-beta':
return (
<div className={styles['sidebar_link_wrapper']}>
{colorMode === 'dark' ? (
<>
<EnterpriseDark /> <BetaTag />
</>
) : (
<>
<EnterpriseLight /> <BetaTag />
</>
)}
</div>
);
case 'cloud-and-enterprise-icon':
return (
<div className={styles['cloud-ee-container']}>
{colorMode === 'dark' ? (
<>
<CloudDark /> <EnterpriseDark />{' '}
</>
) : (
<>
<CloudLight /> <EnterpriseLight />
</>
)}
</div>
);
case 'beta-icon':
return (
<div className={styles['sidebar_link_wrapper']}>
<BetaTag />
</div>
);
default:
return null;
}
}
const labelWithIcons = addIconsToLabel(label, className);
if (className != 'sidebar_heading') {
return (
<li
className={clsx(
ThemeClassNames.docs.docSidebarItemLink,
ThemeClassNames.docs.docSidebarItemLinkLevel(level),
'menu__list-item',
className,
styles[`sidebar_link_wrapper`]
)}
key={label}
>
return (
<li
className={clsx(
ThemeClassNames.docs.docSidebarItemLink,
ThemeClassNames.docs.docSidebarItemLinkLevel(level),
'menu__list-item',
className,
styles[`sidebar_link_wrapper`]
)}
key={label}
>
{className !== 'sidebar_heading' ? (
<Link
className={clsx('menu__link', !isInternalLink && styles.menuExternalLink, {
'menu__link--active': isActive,
})}
className={clsx(
'menu__link',
!isInternalLink && styles.menuExternalLink,
{
'menu__link--active': isActive,
}
)}
autoAddBaseUrl={autoAddBaseUrl}
aria-current={isActive ? 'page' : undefined}
to={href}
@ -88,26 +49,11 @@ export default function DocSidebarItemLink({ item, onItemClick, activePath, leve
})}
{...props}
>
{label}
{addIcons(className)}
{labelWithIcons}
</Link>
</li>
);
} else {
return (
<li
className={clsx(
ThemeClassNames.docs.docSidebarItemLink,
ThemeClassNames.docs.docSidebarItemLinkLevel(level),
'menu__list-item',
className,
styles[`sidebar_link_wrapper`]
)}
key={label}
>
{label}
{addIcons(className)}
</li>
);
}
) : (
<>{labelWithIcons}</>
)}
</li>
);
}

View File

@ -13,7 +13,9 @@ export default function DocSidebarItem({ item, ...props }) {
// if there is no custom sidebar_pathname, use the label with our regex
// and apparently deal with the Wiki as a special case
if (item.label != 'Docs Wiki') {
item.href = `/docs/latest/${item.label.toLowerCase().replace(/\s/g, '-')}/overview/`;
item.href = `/docs/latest/${item.label
.toLowerCase()
.replace(/\s/g, '-')}/overview/`;
}
} else {
// if it already has a href (such as any category that has an index within the dir), use it

View File

@ -0,0 +1,57 @@
import React, { useEffect, useState } from 'react';
import EnterpriseDark from '@site/static/icons/enterprise-light.svg';
import EnterpriseLight from '@site/static/icons/enterprise-dark.svg';
import CloudDark from '@site/static/icons/cloud-light.svg';
import CloudLight from '@site/static/icons/cloud-dark.svg';
import BetaTag from '@site/src/components/BetaTag/BetaTag';
import styles from '@site/src/theme/DocSidebarItem/Category/styles.module.scss';
import { useColorMode } from '@docusaurus/theme-common';
export function addIconsToLabel(label, className) {
const { colorMode } = useColorMode();
const [definedColorMode, setDefinedColorMode] = useState('');
useEffect(() => {
setDefinedColorMode(colorMode);
}, [colorMode]);
const isDarkMode = definedColorMode === 'dark';
const enterpriseIcon = isDarkMode ? <EnterpriseDark /> : <EnterpriseLight />;
const cloudIcon = isDarkMode ? <CloudDark /> : <CloudLight />;
const betaIcon = <BetaTag />;
// Conditional rendering for sidebar icons
let icons;
switch (className) {
case 'enterprise-icon':
icons = enterpriseIcon;
break;
case 'cloud-icon':
icons = cloudIcon;
break;
case 'enterprise-icon-and-beta':
icons = (
<>
{enterpriseIcon} {betaIcon}
</>
);
break;
case 'cloud-and-enterprise-icon':
icons = (
<>
{cloudIcon} {enterpriseIcon}
</>
);
break;
case 'beta-icon':
icons = betaIcon;
break;
}
return (
<div className={styles['sidebar_link_wrapper']}>
{label} {icons}
</div>
);
}