diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main/index.tsx
similarity index 95%
rename from packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx
rename to packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main/index.tsx
index 7ae0124695..3cc4f0479e 100644
--- a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main/index.tsx
@@ -10,7 +10,7 @@ import React from 'react';
import {useDocsSidebar} from '@docusaurus/theme-common';
import clsx from 'clsx';
-import styles from './Main.module.css';
+import styles from './styles.module.css';
import type {Props} from '@theme/DocPage/Layout/Main';
export default function DocPageLayoutMain({
diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.module.css b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main/styles.module.css
similarity index 100%
rename from packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main.module.css
rename to packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Main/styles.module.css
diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.tsx b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton/index.tsx
similarity index 96%
rename from packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.tsx
rename to packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton/index.tsx
index 69dcd5937e..7d68031577 100644
--- a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton/index.tsx
@@ -10,7 +10,7 @@ import IconArrow from '@theme/IconArrow';
import {translate} from '@docusaurus/Translate';
import type {Props} from '@theme/DocPage/Layout/Sidebar/ExpandButton';
-import styles from './ExpandButton.module.css';
+import styles from './styles.module.css';
export default function DocPageLayoutSidebarExpandButton({
toggleSidebar,
diff --git a/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.module.css b/packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton/styles.module.css
similarity index 100%
rename from packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton.module.css
rename to packages/docusaurus-theme-classic/src/theme/DocPage/Layout/Sidebar/ExpandButton/styles.module.css
diff --git a/packages/docusaurus-theme-classic/src/theme/TOCItems/Tree.tsx b/packages/docusaurus-theme-classic/src/theme/TOCItems/Tree.tsx
index 85786b9079..04ab3fc93b 100644
--- a/packages/docusaurus-theme-classic/src/theme/TOCItems/Tree.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/TOCItems/Tree.tsx
@@ -9,7 +9,6 @@ import React from 'react';
import type {Props} from '@theme/TOCItems/Tree';
// Recursive component rendering the toc tree
-/* eslint-disable jsx-a11y/control-has-associated-label */
function TOCItemTree({
toc,
className,
@@ -23,6 +22,7 @@ function TOCItemTree({
{toc.map((heading) => (
-
+ {/* eslint-disable-next-line jsx-a11y/control-has-associated-label */}
- name && items
- ? {
- name,
- items,
- }
- : null,
+ () => (name && items ? {name, items} : null),
[name, items],
);
return {children};
diff --git a/packages/docusaurus-theme-common/src/utils/a11yUtils.ts b/packages/docusaurus-theme-common/src/hooks/useSkipToContent.ts
similarity index 61%
rename from packages/docusaurus-theme-common/src/utils/a11yUtils.ts
rename to packages/docusaurus-theme-common/src/hooks/useSkipToContent.ts
index 3ee8a8b1a1..54e6a42f3a 100644
--- a/packages/docusaurus-theme-common/src/utils/a11yUtils.ts
+++ b/packages/docusaurus-theme-common/src/hooks/useSkipToContent.ts
@@ -8,8 +8,8 @@
import type React from 'react';
import {useCallback, useRef} from 'react';
import {useHistory} from '@docusaurus/router';
-import {useLocationChange} from './useLocationChange';
-import {ThemeClassNames} from './ThemeClassNames';
+import {useLocationChange} from '../utils/useLocationChange';
+import {ThemeClassNames} from '../utils/ThemeClassNames';
function programmaticFocus(el: HTMLElement) {
el.setAttribute('tabindex', '-1');
@@ -17,8 +17,21 @@ function programmaticFocus(el: HTMLElement) {
el.removeAttribute('tabindex');
}
+/** This hook wires the logic for a skip-to-content link. */
export function useSkipToContent(): {
+ /**
+ * The ref to the container. On page transition, the container will be focused
+ * so that keyboard navigators can instantly interact with the link and jump
+ * to content. **Note:** the type is `RefObject` only because
+ * the typing for refs don't reflect that the `ref` prop is contravariant, so
+ * using `HTMLElement` causes type-checking to fail. You can plug the ref into
+ * any HTML element, as long as it can be focused.
+ */
containerRef: React.RefObject;
+ /**
+ * Callback fired when the skip to content link has been interacted with. It
+ * will programmatically focus the main content.
+ */
handleSkip: (e: React.MouseEvent) => void;
} {
const containerRef = useRef(null);
diff --git a/packages/docusaurus-theme-common/src/index.ts b/packages/docusaurus-theme-common/src/index.ts
index d086b65426..424aff10b0 100644
--- a/packages/docusaurus-theme-common/src/index.ts
+++ b/packages/docusaurus-theme-common/src/index.ts
@@ -58,8 +58,6 @@ export {
useDocRouteMetadata,
} from './utils/docsUtils';
-export {useSkipToContent} from './utils/a11yUtils';
-
export {useTitleFormatter} from './utils/generalUtils';
export {usePluralForm} from './utils/usePluralForm';
@@ -162,3 +160,4 @@ export {useLockBodyScroll} from './hooks/useLockBodyScroll';
export {useWindowSize} from './hooks/useWindowSize';
export {useSearchPage} from './hooks/useSearchPage';
export {useCodeWordWrap} from './hooks/useCodeWordWrap';
+export {useSkipToContent} from './hooks/useSkipToContent';
diff --git a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx
index 3927cc6b9e..706504118b 100644
--- a/packages/docusaurus-theme-common/src/utils/docsUtils.tsx
+++ b/packages/docusaurus-theme-common/src/utils/docsUtils.tsx
@@ -20,9 +20,9 @@ import type {
PropSidebarItem,
PropSidebarItemCategory,
PropVersionDoc,
- PropVersionMetadata,
PropSidebarBreadcrumbsItem,
} from '@docusaurus/plugin-content-docs';
+import type {Props as DocPageProps} from '@theme/DocPage';
import {useDocsPreferredVersion} from '../contexts/docsPreferredVersion';
import {useDocsVersion} from '../contexts/docsVersion';
import {useDocsSidebar} from '../contexts/docsSidebar';
@@ -30,7 +30,6 @@ import {uniq} from './jsUtils';
import {isSamePath} from './routesUtils';
import {matchPath, useLocation} from '@docusaurus/router';
import renderRoutes from '@docusaurus/renderRoutes';
-import type {RouteConfig} from 'react-router-config';
// TODO not ideal, see also "useDocs"
export const isDocsPluginEnabled: boolean = !!useAllDocsData;
@@ -286,20 +285,32 @@ Available doc ids are:
}
// TODO later read version/route directly from context
+/**
+ * The docs plugin creates nested routes, with the top-level route providing the
+ * version metadata, and the subroutes creating individual doc pages. This hook
+ * will match the current location against all known sub-routes.
+ *
+ * @param props The props received by `@theme/DocPage`
+ * @returns The data of the relevant document at the current location, or `null`
+ * if no document associated with the current location can be found.
+ */
export function useDocRouteMetadata({
route,
versionMetadata,
-}: {
- route: RouteConfig;
- versionMetadata: PropVersionMetadata;
-}): null | {
+}: DocPageProps): null | {
+ /** The element that should be rendered at the current location. */
docElement: JSX.Element;
+ /**
+ * The name of the sidebar associated with the current doc. `sidebarName` and
+ * `sidebarItems` correspond to the value of {@link useDocsSidebar}.
+ */
sidebarName: string | undefined;
+ /** The items of the sidebar associated with the current doc. */
sidebarItems: PropSidebar | undefined;
} {
const location = useLocation();
- const docRoutes = route.routes;
- const currentDocRoute = docRoutes!.find((docRoute) =>
+ const docRoutes = route.routes!;
+ const currentDocRoute = docRoutes.find((docRoute) =>
matchPath(location.pathname, docRoute),
);
if (!currentDocRoute) {
@@ -313,9 +324,7 @@ export function useDocRouteMetadata({
? versionMetadata.docsSidebars[sidebarName]
: undefined;
- const docElement = renderRoutes(route.routes!, {
- versionMetadata,
- });
+ const docElement = renderRoutes(docRoutes, {versionMetadata});
return {
docElement,