mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-29 02:08:36 +02:00
fix(theme): Fix <DocCardList>
usage on docs at root of a sidebar (#10847)
Fix `<DocCardList>` usage on docs at root of a sidebar
This commit is contained in:
parent
e59355be76
commit
67207bc5e5
5 changed files with 155 additions and 3 deletions
|
@ -15,6 +15,7 @@ import {
|
||||||
useDocById,
|
useDocById,
|
||||||
findSidebarCategory,
|
findSidebarCategory,
|
||||||
useCurrentSidebarCategory,
|
useCurrentSidebarCategory,
|
||||||
|
useCurrentSidebarSiblings,
|
||||||
useSidebarBreadcrumbs,
|
useSidebarBreadcrumbs,
|
||||||
isVisibleSidebarItem,
|
isVisibleSidebarItem,
|
||||||
} from '../docsUtils';
|
} from '../docsUtils';
|
||||||
|
@ -780,3 +781,128 @@ describe('useCurrentSidebarCategory', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('useCurrentSidebarSiblings', () => {
|
||||||
|
const createUseCurrentSidebarSiblingsMock =
|
||||||
|
(sidebar?: PropSidebar) => (location: string) =>
|
||||||
|
renderHook(() => useCurrentSidebarSiblings(), {
|
||||||
|
wrapper: ({children}) => (
|
||||||
|
<DocsSidebarProvider name="sidebarName" items={sidebar}>
|
||||||
|
<StaticRouter location={location}>{children}</StaticRouter>
|
||||||
|
</DocsSidebarProvider>
|
||||||
|
),
|
||||||
|
}).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"`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -132,6 +132,25 @@ export function useCurrentSidebarCategory(): PropSidebarItemCategory {
|
||||||
return deepestCategory;
|
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) =>
|
const isActive = (testedPath: string | undefined, activePath: string) =>
|
||||||
typeof testedPath !== 'undefined' && isSamePath(testedPath, activePath);
|
typeof testedPath !== 'undefined' && isSamePath(testedPath, activePath);
|
||||||
const containsActiveSidebarItem = (
|
const containsActiveSidebarItem = (
|
||||||
|
|
|
@ -33,6 +33,7 @@ export {
|
||||||
useLayoutDocsSidebar,
|
useLayoutDocsSidebar,
|
||||||
useDocRootMetadata,
|
useDocRootMetadata,
|
||||||
useCurrentSidebarCategory,
|
useCurrentSidebarCategory,
|
||||||
|
useCurrentSidebarSiblings,
|
||||||
filterDocCardListItems,
|
filterDocCardListItems,
|
||||||
} from './docsUtils';
|
} from './docsUtils';
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
import React, {type ReactNode} from 'react';
|
import React, {type ReactNode} from 'react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import {
|
import {
|
||||||
useCurrentSidebarCategory,
|
useCurrentSidebarSiblings,
|
||||||
filterDocCardListItems,
|
filterDocCardListItems,
|
||||||
} from '@docusaurus/plugin-content-docs/client';
|
} from '@docusaurus/plugin-content-docs/client';
|
||||||
import DocCard from '@theme/DocCard';
|
import DocCard from '@theme/DocCard';
|
||||||
import type {Props} from '@theme/DocCardList';
|
import type {Props} from '@theme/DocCardList';
|
||||||
|
|
||||||
function DocCardListForCurrentSidebarCategory({className}: Props) {
|
function DocCardListForCurrentSidebarCategory({className}: Props) {
|
||||||
const category = useCurrentSidebarCategory();
|
const items = useCurrentSidebarSiblings();
|
||||||
return <DocCardList items={category.items} className={className} />;
|
return <DocCardList items={items} className={className} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DocCardList(props: Props): ReactNode {
|
export default function DocCardList(props: Props): ReactNode {
|
||||||
|
|
|
@ -13,3 +13,9 @@ This Docusaurus docs plugin instance is meant to test fancy edge-cases that regu
|
||||||
- [/tests/docs](/tests/docs)
|
- [/tests/docs](/tests/docs)
|
||||||
- [/tests/blog](/tests/blog)
|
- [/tests/blog](/tests/blog)
|
||||||
- [/tests/pages](/tests/pages)
|
- [/tests/pages](/tests/pages)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
import DocCardList from '@theme/DocCardList';
|
||||||
|
|
||||||
|
<DocCardList />
|
||||||
|
|
Loading…
Add table
Reference in a new issue