mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
docs: refactor sidebar link
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9922 GitOrigin-RevId: 21a1a62b354ad7eac4fd0daaceb2a565bfc444ae
This commit is contained in:
parent
05cfb65b54
commit
161569dd40
@ -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
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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
|
||||
|
57
docs/src/theme/DocSidebarItem/utils.js
Normal file
57
docs/src/theme/DocSidebarItem/utils.js
Normal 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>
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user