diff --git a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsUtils.test.tsx b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsUtils.test.tsx
index 44916fd33c99..00263ad5907d 100644
--- a/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsUtils.test.tsx
+++ b/packages/docusaurus-plugin-content-docs/src/client/__tests__/docsUtils.test.tsx
@@ -15,6 +15,7 @@ import {
useDocById,
findSidebarCategory,
useCurrentSidebarCategory,
+ useCurrentSidebarSiblings,
useSidebarBreadcrumbs,
isVisibleSidebarItem,
} from '../docsUtils';
@@ -780,3 +781,128 @@ describe('useCurrentSidebarCategory', () => {
);
});
});
+
+describe('useCurrentSidebarSiblings', () => {
+ const createUseCurrentSidebarSiblingsMock =
+ (sidebar?: PropSidebar) => (location: string) =>
+ renderHook(() => useCurrentSidebarSiblings(), {
+ wrapper: ({children}) => (
+
+ {children}
+
+ ),
+ }).result.current;
+
+ it('works for sidebar category', () => {
+ const category: PropSidebarItemCategory = testCategory({
+ href: '/cat',
+ items: [testLink(), testLink()],
+ });
+ const sidebar: PropSidebar = [
+ testLink(),
+ testLink(),
+ category,
+ testCategory(),
+ ];
+
+ const mockUseCurrentSidebarCategory =
+ createUseCurrentSidebarSiblingsMock(sidebar);
+
+ expect(mockUseCurrentSidebarCategory('/cat')).toEqual(category.items);
+ });
+
+ it('works for sidebar root', () => {
+ const category: PropSidebarItemCategory = testCategory({
+ href: '/cat',
+ items: [testLink(), testLink()],
+ });
+ const sidebar: PropSidebar = [
+ testLink({href: '/rootLink'}),
+ testLink(),
+ category,
+ testCategory(),
+ ];
+
+ const mockUseCurrentSidebarCategory =
+ createUseCurrentSidebarSiblingsMock(sidebar);
+
+ expect(mockUseCurrentSidebarCategory('/rootLink')).toEqual(sidebar);
+ });
+
+ it('works for nested sidebar category', () => {
+ const category2: PropSidebarItemCategory = testCategory({
+ href: '/cat2',
+ items: [testLink(), testCategory()],
+ });
+ const category1: PropSidebarItemCategory = testCategory({
+ href: '/cat1',
+ items: [testLink(), testLink(), category2, testCategory()],
+ });
+ const sidebar: PropSidebar = [
+ testLink(),
+ testLink(),
+ category1,
+ testCategory(),
+ ];
+
+ const mockUseCurrentSidebarCategory =
+ createUseCurrentSidebarSiblingsMock(sidebar);
+
+ expect(mockUseCurrentSidebarCategory('/cat2')).toEqual(category2.items);
+ });
+
+ it('works for category link item', () => {
+ const link = testLink({href: '/my/link/path'});
+ const category: PropSidebarItemCategory = testCategory({
+ href: '/cat1',
+ items: [testLink(), testLink(), link, testCategory()],
+ });
+ const sidebar: PropSidebar = [
+ testLink(),
+ testLink(),
+ category,
+ testCategory(),
+ ];
+
+ const mockUseCurrentSidebarCategory =
+ createUseCurrentSidebarSiblingsMock(sidebar);
+
+ expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(
+ category.items,
+ );
+ });
+
+ it('works for nested category link item', () => {
+ const link = testLink({href: '/my/link/path'});
+ const category2: PropSidebarItemCategory = testCategory({
+ href: '/cat2',
+ items: [testLink(), testLink(), link, testCategory()],
+ });
+ const category1: PropSidebarItemCategory = testCategory({
+ href: '/cat1',
+ items: [testLink(), testLink(), category2, testCategory()],
+ });
+ const sidebar: PropSidebar = [
+ testLink(),
+ testLink(),
+ category1,
+ testCategory(),
+ ];
+
+ const mockUseCurrentSidebarCategory =
+ createUseCurrentSidebarSiblingsMock(sidebar);
+
+ expect(mockUseCurrentSidebarCategory('/my/link/path')).toEqual(
+ category2.items,
+ );
+ });
+
+ it('throws when sidebar is missing', () => {
+ const mockUseCurrentSidebarCategory = createUseCurrentSidebarSiblingsMock();
+ expect(() =>
+ mockUseCurrentSidebarCategory('/cat'),
+ ).toThrowErrorMatchingInlineSnapshot(
+ `"Unexpected: cant find current sidebar in context"`,
+ );
+ });
+});
diff --git a/packages/docusaurus-plugin-content-docs/src/client/docsUtils.tsx b/packages/docusaurus-plugin-content-docs/src/client/docsUtils.tsx
index 0fff426231a8..aa00df851034 100644
--- a/packages/docusaurus-plugin-content-docs/src/client/docsUtils.tsx
+++ b/packages/docusaurus-plugin-content-docs/src/client/docsUtils.tsx
@@ -132,6 +132,25 @@ export function useCurrentSidebarCategory(): PropSidebarItemCategory {
return deepestCategory;
}
+/**
+ * Gets the category associated with the current location. Should only be used
+ * on category index pages.
+ */
+export function useCurrentSidebarSiblings(): PropSidebarItem[] {
+ const {pathname} = useLocation();
+ const sidebar = useDocsSidebar();
+ if (!sidebar) {
+ throw new Error('Unexpected: cant find current sidebar in context');
+ }
+ const categoryBreadcrumbs = getSidebarBreadcrumbs({
+ sidebarItems: sidebar.items,
+ pathname,
+ onlyCategories: true,
+ });
+ const deepestCategory = categoryBreadcrumbs.slice(-1)[0];
+ return deepestCategory?.items ?? sidebar.items;
+}
+
const isActive = (testedPath: string | undefined, activePath: string) =>
typeof testedPath !== 'undefined' && isSamePath(testedPath, activePath);
const containsActiveSidebarItem = (
diff --git a/packages/docusaurus-plugin-content-docs/src/client/index.ts b/packages/docusaurus-plugin-content-docs/src/client/index.ts
index f60ba572faef..6734431adca7 100644
--- a/packages/docusaurus-plugin-content-docs/src/client/index.ts
+++ b/packages/docusaurus-plugin-content-docs/src/client/index.ts
@@ -33,6 +33,7 @@ export {
useLayoutDocsSidebar,
useDocRootMetadata,
useCurrentSidebarCategory,
+ useCurrentSidebarSiblings,
filterDocCardListItems,
} from './docsUtils';
diff --git a/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx b/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx
index a45ee6e9801f..62374763ca71 100644
--- a/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx
+++ b/packages/docusaurus-theme-classic/src/theme/DocCardList/index.tsx
@@ -8,15 +8,15 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import {
- useCurrentSidebarCategory,
+ useCurrentSidebarSiblings,
filterDocCardListItems,
} from '@docusaurus/plugin-content-docs/client';
import DocCard from '@theme/DocCard';
import type {Props} from '@theme/DocCardList';
function DocCardListForCurrentSidebarCategory({className}: Props) {
- const category = useCurrentSidebarCategory();
- return ;
+ const items = useCurrentSidebarSiblings();
+ return ;
}
export default function DocCardList(props: Props): ReactNode {
diff --git a/website/_dogfooding/_docs tests/index.mdx b/website/_dogfooding/_docs tests/index.mdx
index a97ed434eff9..8ff3cccab6e1 100644
--- a/website/_dogfooding/_docs tests/index.mdx
+++ b/website/_dogfooding/_docs tests/index.mdx
@@ -13,3 +13,9 @@ This Docusaurus docs plugin instance is meant to test fancy edge-cases that regu
- [/tests/docs](/tests/docs)
- [/tests/blog](/tests/blog)
- [/tests/pages](/tests/pages)
+
+---
+
+import DocCardList from '@theme/DocCardList';
+
+