fix(theme): mobile drawer history blocker should be rendered conditionally (workaround) (#10989)

Add history blocker workaround
This commit is contained in:
Sébastien Lorber 2025-03-14 18:22:00 +01:00 committed by GitHub
parent 7cf94c03a4
commit cb69b40c86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 13 deletions

View file

@ -53,18 +53,6 @@ function useContextValue(): ContextValue {
const [shown, setShown] = useState(false);
// Close mobile sidebar on navigation pop
// Most likely firing when using the Android back button (but not only)
useHistoryPopHandler(() => {
if (shown) {
setShown(false);
// Prevent pop navigation; seems desirable enough
// See https://github.com/facebook/docusaurus/pull/5462#issuecomment-911699846
return false;
}
return undefined;
});
const toggle = useCallback(() => {
setShown((s) => !s);
}, []);
@ -81,13 +69,45 @@ function useContextValue(): ContextValue {
);
}
// A component hook wrapper enables conditional rendering
// See reason here: https://github.com/facebook/docusaurus/issues/10988
function OnHistoryPop({
handler,
}: {
handler: Parameters<typeof useHistoryPopHandler>[0];
}) {
useHistoryPopHandler(handler);
return null;
}
export function NavbarMobileSidebarProvider({
children,
}: {
children: ReactNode;
}): ReactNode {
const value = useContextValue();
return <Context.Provider value={value}>{children}</Context.Provider>;
return (
<>
{
// Close mobile sidebar on navigation pop
// Most likely firing when using the Android back button (but not only)
// Important: we can only have a single history blocker at a time
// That's why this needs to be rendered conditionally
// See bug report https://github.com/facebook/docusaurus/issues/10988
value.shown && (
<OnHistoryPop
handler={() => {
value.toggle();
// Prevent pop navigation; seems desirable enough
// See https://github.com/facebook/docusaurus/pull/5462#issuecomment-911699846
return false;
}}
/>
)
}
<Context.Provider value={value}>{children}</Context.Provider>
</>
);
}
export function useNavbarMobileSidebar(): ContextValue {

View file

@ -0,0 +1,33 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {useEffect, type ReactNode} from 'react';
import {useHistory} from '@docusaurus/router';
import Layout from '@theme/Layout';
import Heading from '@theme/Heading';
// Test for https://github.com/facebook/docusaurus/issues/10988
function BlockNavigation() {
const history = useHistory();
useEffect(() => {
return history.block(() => {
// eslint-disable-next-line no-alert
alert('navigation blocked successfully');
return false;
});
}, [history]);
return false;
}
export default function HistoryTestsPage(): ReactNode {
return (
<Layout>
<Heading as="h1">History tests</Heading>
<p>This page should block navigation</p>
<BlockNavigation />
</Layout>
);
}

View file

@ -39,4 +39,5 @@ import Readme from "../README.mdx"
- [Head metadata tests](/tests/pages/head-metadata)
- [Unlisted page](/tests/pages/unlisted)
- [Analytics](/tests/pages/analytics)
- [History tests](/tests/pages/history-tests)
- [Embeds](/tests/pages/embeds)