From 656cfbe32aad350d807556ea40c148d9817f1f78 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Tue, 30 Jun 2026 11:21:08 +0200 Subject: [PATCH 01/15] Stop review mode from mutating sidebar/panel chrome visibility. Review entry and exit now only snapshot and restore sidebar filters; entering a review no longer collapses or restores nav/panel layout state. --- .../components/review/review-actions.ts | 2 +- .../components/review/review-mode.test.ts | 36 +++++------- .../manager/components/review/review-mode.ts | 56 ++++--------------- .../sidebar/ReviewWidget.stories.tsx | 2 - 4 files changed, 27 insertions(+), 69 deletions(-) diff --git a/code/core/src/manager/components/review/review-actions.ts b/code/core/src/manager/components/review/review-actions.ts index a10b7f668908..3e12fe1eb59f 100644 --- a/code/core/src/manager/components/review/review-actions.ts +++ b/code/core/src/manager/components/review/review-actions.ts @@ -41,7 +41,7 @@ export const navigateToReviewSummary = ( /** * Leave review mode and return to the pre-review canvas. Shared by the summary - * back-to-Storybook link and review dismissal; restores chrome/filters via + * back-to-Storybook link and review dismissal; restores filters via * {@link exitReviewMode} and navigates to the captured return search. */ export const navigateOutOfReview = ( diff --git a/code/core/src/manager/components/review/review-mode.test.ts b/code/core/src/manager/components/review/review-mode.test.ts index d2c589d4fac7..23ad2273f68c 100644 --- a/code/core/src/manager/components/review/review-mode.test.ts +++ b/code/core/src/manager/components/review/review-mode.test.ts @@ -17,16 +17,9 @@ const emptyFilters: ReviewModeFilters = { excludedTagFilters: [], }; -const makeApi = ( - overrides: Partial<{ getIsNavShown: () => boolean; getIsPanelShown: () => boolean }> = {} -) => ({ - toggleNav: vi.fn(), - togglePanel: vi.fn(), - getIsNavShown: () => true, - getIsPanelShown: () => true, +const makeApi = () => ({ setAllStatusFilters: vi.fn(async () => {}), setAllTagFilters: vi.fn(async () => {}), - ...overrides, }); beforeEach(() => { @@ -34,12 +27,10 @@ beforeEach(() => { }); describe('enterReviewMode', () => { - it('collapses chrome, narrows filters to reviewing, and sets the flag', async () => { + it('narrows filters to reviewing and sets the flag without changing chrome', async () => { const api = makeApi(); await enterReviewMode(api, emptyFilters); - expect(api.toggleNav).toHaveBeenCalledWith(false); - expect(api.togglePanel).toHaveBeenCalledWith(false); expect(api.setAllTagFilters).toHaveBeenCalledWith([], []); expect(api.setAllStatusFilters).toHaveBeenCalledWith(['status-value:reviewing'], []); expect(isReviewModeActive()).toBe(true); @@ -62,36 +53,37 @@ describe('enterReviewMode', () => { expect(api.setAllStatusFilters).toHaveBeenCalledWith(['status-value:error'], []); }); - it('does not re-collapse chrome or re-apply filters when already in review mode', async () => { + it('does not re-apply filters when already in review mode', async () => { const api = makeApi(); await enterReviewMode(api, emptyFilters); vi.clearAllMocks(); await enterReviewMode(api, emptyFilters); - expect(api.toggleNav).not.toHaveBeenCalled(); - expect(api.togglePanel).not.toHaveBeenCalled(); expect(api.setAllTagFilters).not.toHaveBeenCalled(); expect(api.setAllStatusFilters).not.toHaveBeenCalled(); }); }); describe('exitReviewMode', () => { - it('restores only the chrome that was shown before entry and clears the flag', async () => { - await enterReviewMode( - makeApi({ getIsNavShown: () => true, getIsPanelShown: () => false }), - emptyFilters - ); + it('restores snapshotted filters and clears the flag', async () => { + const preReviewFilters: ReviewModeFilters = { + includedStatusFilters: ['status-value:error' as StatusValue], + excludedStatusFilters: [], + includedTagFilters: ['play-fn'], + excludedTagFilters: [], + }; + await enterReviewMode(makeApi(), preReviewFilters); const api = makeApi(); await exitReviewMode(api); - expect(api.toggleNav).toHaveBeenCalledWith(true); - expect(api.togglePanel).not.toHaveBeenCalledWith(true); + expect(api.setAllTagFilters).toHaveBeenCalledWith(['play-fn'], []); + expect(api.setAllStatusFilters).toHaveBeenCalledWith(['status-value:error'], []); expect(isReviewModeActive()).toBe(false); }); it('is inert when there is no snapshot to restore', async () => { const api = makeApi(); await exitReviewMode(api); - expect(api.toggleNav).not.toHaveBeenCalled(); + expect(api.setAllTagFilters).not.toHaveBeenCalled(); expect(isReviewModeActive()).toBe(false); }); }); diff --git a/code/core/src/manager/components/review/review-mode.ts b/code/core/src/manager/components/review/review-mode.ts index c804dd38be1a..5498ffae77cd 100644 --- a/code/core/src/manager/components/review/review-mode.ts +++ b/code/core/src/manager/components/review/review-mode.ts @@ -10,10 +10,6 @@ import { sessionStore } from './session-store.ts'; // this key. const REVIEW_MODE_SESSION_KEY = `${REVIEW_NAMESPACE}/review-mode`; -// Snapshot of the manager chrome (sidebar/addon panel visibility) taken when -// review mode is entered, so the exact pre-review layout can be restored on exit. -const CHROME_SNAPSHOT_SESSION_KEY = `${REVIEW_NAMESPACE}/chrome-snapshot`; - // Snapshot of the sidebar filters taken when review mode is entered, so the // pre-review filters can be restored on exit. const FILTERS_SNAPSHOT_SESSION_KEY = `${REVIEW_NAMESPACE}/filters-snapshot`; @@ -26,15 +22,7 @@ export interface ReviewModeFilters { excludedTagFilters: string[]; } -type ReviewModeApi = Pick< - API, - | 'toggleNav' - | 'togglePanel' - | 'getIsNavShown' - | 'getIsPanelShown' - | 'setAllStatusFilters' - | 'setAllTagFilters' ->; +type ReviewModeApi = Pick; /** Whether the manager is currently in review mode (persisted across reloads). */ export const isReviewModeActive = (): boolean => sessionStore.read(REVIEW_MODE_SESSION_KEY) === '1'; @@ -52,55 +40,35 @@ const readJson = (key: string): T | null => { }; /** - * Enter review mode: the single place chrome collapse and filter narrowing - * happen. On the first entry it snapshots the current chrome and filters so - * {@link exitReviewMode} can restore them. Idempotent: re-entering while already - * in review mode is a no-op so in-review navigation does not re-collapse chrome. + * Enter review mode: snapshot sidebar filters and narrow to reviewing stories. + * Idempotent — re-entering while already in review mode is a no-op. */ export const enterReviewMode = async ( api: ReviewModeApi, filters: ReviewModeFilters ): Promise => { - const alreadyInReviewMode = isReviewModeActive(); + if (isReviewModeActive()) { + return; + } - if (!alreadyInReviewMode) { - sessionStore.write( - CHROME_SNAPSHOT_SESSION_KEY, - JSON.stringify({ - nav: api.getIsNavShown(), - panel: api.getIsPanelShown(), - }) - ); - sessionStore.write(FILTERS_SNAPSHOT_SESSION_KEY, JSON.stringify(filters)); - sessionStore.write(REVIEW_MODE_SESSION_KEY, '1'); + sessionStore.write(FILTERS_SNAPSHOT_SESSION_KEY, JSON.stringify(filters)); + sessionStore.write(REVIEW_MODE_SESSION_KEY, '1'); - api.toggleNav(false); - api.togglePanel(false); - await api.setAllTagFilters([], []); - await api.setAllStatusFilters([REVIEWING_STATUS_VALUE], []); - } + await api.setAllTagFilters([], []); + await api.setAllStatusFilters([REVIEWING_STATUS_VALUE], []); }; /** - * Exit review mode: restore the chrome and filters captured on entry and clear - * the persisted review-mode flag. Always restores the pre-review snapshot. + * Exit review mode: restore the filters captured on entry and clear the + * persisted review-mode flag. */ export const exitReviewMode = async (api: ReviewModeApi): Promise => { - const chrome = readJson<{ nav: boolean; panel: boolean }>(CHROME_SNAPSHOT_SESSION_KEY); - if (chrome?.nav) { - api.toggleNav(true); - } - if (chrome?.panel) { - api.togglePanel(true); - } - const filters = readJson(FILTERS_SNAPSHOT_SESSION_KEY); if (filters) { await api.setAllTagFilters(filters.includedTagFilters, filters.excludedTagFilters); await api.setAllStatusFilters(filters.includedStatusFilters, filters.excludedStatusFilters); } - sessionStore.remove(CHROME_SNAPSHOT_SESSION_KEY); sessionStore.remove(FILTERS_SNAPSHOT_SESSION_KEY); sessionStore.remove(REVIEW_MODE_SESSION_KEY); }; diff --git a/code/core/src/manager/components/sidebar/ReviewWidget.stories.tsx b/code/core/src/manager/components/sidebar/ReviewWidget.stories.tsx index 495060dcab79..a25597c31750 100644 --- a/code/core/src/manager/components/sidebar/ReviewWidget.stories.tsx +++ b/code/core/src/manager/components/sidebar/ReviewWidget.stories.tsx @@ -258,8 +258,6 @@ export const OpenReview: Story = { }, play: async ({ canvas }) => { await userEvent.click(canvas.getByRole('button', { name: /Review 2 stories/i })); - await expect(toggleNavMock).toHaveBeenCalledWith(false); - await expect(togglePanelMock).toHaveBeenCalledWith(false); await expect(setAllTagFiltersMock).toHaveBeenCalledWith([], []); await expect(setAllStatusFiltersMock).toHaveBeenCalledWith(['status-value:reviewing'], []); await expect(setQueryParamsMock).toHaveBeenCalledWith({ From 2b0e26ca5ae78105a7be74ebf7771354b8136d9b Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Tue, 30 Jun 2026 11:22:45 +0200 Subject: [PATCH 02/15] Hide sidebar on the review summary page. The review route no longer renders the sidebar (desktop or mobile menu), and sidebar keyboard shortcuts are ignored there. --- .../core/src/manager-api/modules/shortcuts.ts | 18 ++++++- .../components/layout/Layout.stories.tsx | 2 +- .../src/manager/components/layout/Layout.tsx | 34 ++++++++++---- .../mobile/navigation/MobileNavigation.tsx | 47 +++++++++++-------- 4 files changed, 71 insertions(+), 30 deletions(-) diff --git a/code/core/src/manager-api/modules/shortcuts.ts b/code/core/src/manager-api/modules/shortcuts.ts index 75e8d6c6f8d5..54143eabc34b 100644 --- a/code/core/src/manager-api/modules/shortcuts.ts +++ b/code/core/src/manager-api/modules/shortcuts.ts @@ -11,11 +11,13 @@ import copy from 'copy-to-clipboard'; import type { KeyboardEventLike } from '../lib/shortcut.ts'; import { eventToShortcut, shortcutMatchesShortcut } from '../lib/shortcut.ts'; -import type { ModuleFn } from '../lib/types.tsx'; +import type { ModuleFn, State } from '../lib/types.tsx'; import { focusableUIElements } from './layout.ts'; const { navigator, document } = global; +const isSidebarShortcutBlocked = (state: State) => state.viewMode === 'review'; + function wasFocusInElement(element: HTMLElement | null) { return document.activeElement && element?.contains(document.activeElement); } @@ -257,16 +259,19 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => { // warning: event might not have a full prototype chain because it may originate from the channel handleShortcutFeature(feature, event) { + const state = store.getState(); const { ui: { enableShortcuts }, storyId, refId, viewMode, - } = store.getState(); + } = state; if (!enableShortcuts) { return; } + const sidebarShortcutBlocked = isSidebarShortcutBlocked(state); + // Event.prototype.preventDefault is missing when received from the MessageChannel. if (event?.preventDefault) { event.preventDefault(); @@ -287,6 +292,9 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => { break; case 'focusNav': { + if (sidebarShortcutBlocked) { + break; + } if (fullAPI.getIsFullscreen()) { fullAPI.toggleFullscreen(false); } @@ -298,6 +306,9 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => { } case 'search': { + if (sidebarShortcutBlocked) { + break; + } if (fullAPI.getIsFullscreen()) { fullAPI.toggleFullscreen(false); } @@ -391,6 +402,9 @@ export const init: ModuleFn = ({ store, fullAPI, provider }) => { } case 'toggleNav': { + if (sidebarShortcutBlocked) { + break; + } const wasNavShown = fullAPI.getIsNavShown(); const sidebarElement = document.getElementById(focusableUIElements.sidebarRegion); diff --git a/code/core/src/manager/components/layout/Layout.stories.tsx b/code/core/src/manager/components/layout/Layout.stories.tsx index cd4326dfb68e..869293f22eb2 100644 --- a/code/core/src/manager/components/layout/Layout.stories.tsx +++ b/code/core/src/manager/components/layout/Layout.stories.tsx @@ -515,7 +515,7 @@ export const MobileReview: Story = { managerLayoutState: { ...defaultState, viewMode: 'review' }, }, play: async ({ canvas }) => { - expect(canvas.getByLabelText('Open navigation menu')).toBeInTheDocument(); + expect(canvas.queryByLabelText('Open navigation menu')).not.toBeInTheDocument(); expect(canvas.getByTestId('preview')).toBeInTheDocument(); }, }; diff --git a/code/core/src/manager/components/layout/Layout.tsx b/code/core/src/manager/components/layout/Layout.tsx index be4daf4eb0dc..01a747221e61 100644 --- a/code/core/src/manager/components/layout/Layout.tsx +++ b/code/core/src/manager/components/layout/Layout.tsx @@ -110,6 +110,7 @@ const useLayoutSyncingState = ({ managerLayoutState.viewMode !== 'docs' && managerLayoutState.viewMode !== 'review'; const isPanelShown = managerLayoutState.viewMode === 'story' && !hasTab; + const showSidebar = managerLayoutState.viewMode !== 'review'; const { navSize, rightPanelWidth, bottomPanelHeight } = internalDraggingSizeState.isDragging ? internalDraggingSizeState @@ -138,6 +139,7 @@ const useLayoutSyncingState = ({ panelMaxSize, showPages: isPagesShown, showPanel: customisedShowPanel, + showSidebar, isDragging: internalDraggingSizeState.isDragging, }; }; @@ -161,6 +163,7 @@ export const Layout = ({ managerLayoutState, setManagerLayoutState, hasTab, ...s panelMaxSize, showPages, showPanel, + showSidebar, } = useLayoutSyncingState({ api, managerLayoutState, setManagerLayoutState, isDesktop, hasTab }); // Install landmark navigation listener in parent container of all landmarks. @@ -170,6 +173,7 @@ export const Layout = ({ managerLayoutState, setManagerLayoutState, hasTab, ...s <> - {isDesktop && ( + {isDesktop && showSidebar && ( )} @@ -222,7 +227,8 @@ export const Layout = ({ managerLayoutState, setManagerLayoutState, hasTab, ...s const LayoutContainer = styled.div<{ panelPosition: LayoutState['panelPosition']; showPanel: boolean; -}>(({ panelPosition, showPanel }) => ({ + showSidebar: boolean; +}>(({ panelPosition, showPanel, showSidebar }) => ({ width: '100%', height: ['100vh', '100dvh'], overflow: 'hidden', @@ -233,21 +239,33 @@ const LayoutContainer = styled.div<{ [MEDIA_DESKTOP_BREAKPOINT]: { display: 'grid', gap: 0, - // This uses CSS variables to prevent Emotion from generating a new CSS className for every possible value - gridTemplateColumns: `minmax(0, var(--nav-width)) minmax(${MINIMUM_CONTENT_WIDTH_PX}px, 1fr) minmax(0, var(--right-panel-width))`, + gridTemplateColumns: showSidebar + ? `minmax(0, var(--nav-width)) minmax(${MINIMUM_CONTENT_WIDTH_PX}px, 1fr) minmax(0, var(--right-panel-width))` + : `minmax(${MINIMUM_CONTENT_WIDTH_PX}px, 1fr) minmax(0, var(--right-panel-width))`, gridTemplateRows: `1fr minmax(0, var(--bottom-panel-height))`, gridTemplateAreas: (() => { + if (!showSidebar && !showPanel) { + return `"content content" + "content content"`; + } + if (!showSidebar && showPanel) { + if (panelPosition === 'right') { + return `"content panel" + "content panel"`; + } + return `"content content" + "panel panel"`; + } if (!showPanel) { - // showPanel is false by default when viewMode is not 'story', but can be overridden by the user return `"sidebar content content" - "sidebar content content"`; + "sidebar content content"`; } if (panelPosition === 'right') { return `"sidebar content panel" - "sidebar content panel"`; + "sidebar content panel"`; } return `"sidebar content content" - "sidebar panel panel"`; + "sidebar panel panel"`; })(), }, })); diff --git a/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx b/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx index 05c442b090a4..f9e33d59f61b 100644 --- a/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx +++ b/code/core/src/manager/components/mobile/navigation/MobileNavigation.tsx @@ -18,6 +18,7 @@ import { MobileMenuDrawer } from './MobileMenuDrawer.tsx'; interface MobileNavigationProps { menu?: React.ReactNode; panel?: React.ReactNode; + showMenu?: boolean; showPanel: boolean; } @@ -75,6 +76,7 @@ interface MobileBottomBarContentProps { setMobileMenuOpen: (isOpen: boolean) => void; isMobilePanelOpen: boolean; setMobilePanelOpen: (isOpen: boolean) => void; + showMenu: boolean; showPanel: boolean; } @@ -91,6 +93,7 @@ const MobileBottomBarContent: FC = ({ setMobileMenuOpen, isMobilePanelOpen, setMobilePanelOpen, + showMenu, showPanel, }) => { const headingId = useId(); @@ -105,17 +108,19 @@ const MobileBottomBarContent: FC = ({

Navigation controls

- setMobileMenuOpen(!isMobileMenuOpen)} - ariaLabel="Open navigation menu" - aria-expanded={isMobileMenuOpen} - aria-controls="storybook-mobile-menu" - > - - {fullStoryName} - + {showMenu && ( + setMobileMenuOpen(!isMobileMenuOpen)} + ariaLabel="Open navigation menu" + aria-expanded={isMobileMenuOpen} + aria-controls="storybook-mobile-menu" + > + + {fullStoryName} + + )} {fullStoryName} @@ -138,6 +143,7 @@ const MobileBottomBarContent: FC = ({ export const MobileNavigation: FC> = ({ menu, panel, + showMenu = true, showPanel, ...props }) => { @@ -147,13 +153,15 @@ export const MobileNavigation: FC - - {menu} - + {showMenu && ( + + {menu} + + )} - {!isMobilePanelOpen && ( + {!isMobilePanelOpen && (showMenu || showPanel) && ( )} From 17826d9b8e3547458599fc1fdc34ad01c961a554 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Tue, 30 Jun 2026 11:25:21 +0200 Subject: [PATCH 03/15] Hide sidebar and show review header only on collection stories. Curated review story URLs suppress sidebar rendering and sidebar shortcuts, hide the toolbar show-sidebar control, and gate the review toolbar header on the collection query param. --- code/core/src/manager-api/modules/shortcuts.ts | 7 +++++-- code/core/src/manager/components/layout/Layout.tsx | 9 +++++---- code/core/src/manager/components/preview/Preview.tsx | 6 +++++- code/core/src/manager/components/preview/tools/menu.tsx | 8 +++++--- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/code/core/src/manager-api/modules/shortcuts.ts b/code/core/src/manager-api/modules/shortcuts.ts index 54143eabc34b..d0c71f55c6a9 100644 --- a/code/core/src/manager-api/modules/shortcuts.ts +++ b/code/core/src/manager-api/modules/shortcuts.ts @@ -11,12 +11,15 @@ import copy from 'copy-to-clipboard'; import type { KeyboardEventLike } from '../lib/shortcut.ts'; import { eventToShortcut, shortcutMatchesShortcut } from '../lib/shortcut.ts'; -import type { ModuleFn, State } from '../lib/types.tsx'; +import type { ModuleFn } from '../lib/types.tsx'; +import type { State } from '../root.tsx'; +import { isReviewManagerRoute } from '../../shared/review/routes.ts'; import { focusableUIElements } from './layout.ts'; const { navigator, document } = global; -const isSidebarShortcutBlocked = (state: State) => state.viewMode === 'review'; +const isSidebarShortcutBlocked = (state: State) => + isReviewManagerRoute(state.path, state.customQueryParams); function wasFocusInElement(element: HTMLElement | null) { return document.activeElement && element?.contains(document.activeElement); diff --git a/code/core/src/manager/components/layout/Layout.tsx b/code/core/src/manager/components/layout/Layout.tsx index 01a747221e61..f50bc2373c79 100644 --- a/code/core/src/manager/components/layout/Layout.tsx +++ b/code/core/src/manager/components/layout/Layout.tsx @@ -3,9 +3,11 @@ import React, { useEffect, useLayoutEffect, useState } from 'react'; import type { API_Layout, API_ViewMode } from 'storybook/internal/types'; -import { useStorybookApi, type API } from 'storybook/manager-api'; +import { useStorybookApi, useStorybookState, type API } from 'storybook/manager-api'; import { styled } from 'storybook/theming'; +import { isReviewManagerRoute } from '../../../shared/review/routes.ts'; + import { MEDIA_DESKTOP_BREAKPOINT, MINIMUM_CONTENT_WIDTH_PX } from '../../constants.ts'; import { Notifications } from '../../container/Notifications.tsx'; import { MobileNavigation } from '../mobile/navigation/MobileNavigation.tsx'; @@ -110,7 +112,6 @@ const useLayoutSyncingState = ({ managerLayoutState.viewMode !== 'docs' && managerLayoutState.viewMode !== 'review'; const isPanelShown = managerLayoutState.viewMode === 'story' && !hasTab; - const showSidebar = managerLayoutState.viewMode !== 'review'; const { navSize, rightPanelWidth, bottomPanelHeight } = internalDraggingSizeState.isDragging ? internalDraggingSizeState @@ -139,7 +140,6 @@ const useLayoutSyncingState = ({ panelMaxSize, showPages: isPagesShown, showPanel: customisedShowPanel, - showSidebar, isDragging: internalDraggingSizeState.isDragging, }; }; @@ -151,6 +151,8 @@ const OrderedMobileNavigation = styled(MobileNavigation)({ export const Layout = ({ managerLayoutState, setManagerLayoutState, hasTab, ...slots }: Props) => { const { isDesktop, isMobile } = useLayout(); const api = useStorybookApi(); + const { path, customQueryParams } = useStorybookState(); + const showSidebar = !isReviewManagerRoute(path, customQueryParams); const { navSize, @@ -163,7 +165,6 @@ export const Layout = ({ managerLayoutState, setManagerLayoutState, hasTab, ...s panelMaxSize, showPages, showPanel, - showSidebar, } = useLayoutSyncingState({ api, managerLayoutState, setManagerLayoutState, isDesktop, hasTab }); // Install landmark navigation listener in parent container of all landmarks. diff --git a/code/core/src/manager/components/preview/Preview.tsx b/code/core/src/manager/components/preview/Preview.tsx index b030bca9eaee..6f88b53e34d9 100644 --- a/code/core/src/manager/components/preview/Preview.tsx +++ b/code/core/src/manager/components/preview/Preview.tsx @@ -13,6 +13,7 @@ import { Helmet } from 'react-helmet-async'; import { Consumer, addons, merge, types, type Combo } from 'storybook/manager-api'; import { useLandmark } from '../../hooks/useLandmark.ts'; +import { REVIEW_COLLECTION_QUERY_PARAM } from '../../../shared/review/routes.ts'; import { ReviewToolbarHeader } from '../review/components/ReviewToolbarHeader.tsx'; import { FramesRenderer } from './FramesRenderer.tsx'; import { ToolbarComp } from './Toolbar.tsx'; @@ -59,6 +60,7 @@ const Preview = React.memo(function Preview(props) { tabs, wrappers, tabId, + queryParams, } = props; // SB11: remove code @@ -90,6 +92,8 @@ const Preview = React.memo(function Preview(props) { const shouldScale = viewMode === 'story'; const { showToolbar } = options; const customisedShowToolbar = api.getShowToolbarWithCustomisations(showToolbar); + const isReviewCollectionStory = + viewMode === 'story' && queryParams?.[REVIEW_COLLECTION_QUERY_PARAM] !== undefined; const previousStoryId = useRef(storyId); @@ -128,7 +132,7 @@ const Preview = React.memo(function Preview(props) { )} - {customisedShowToolbar && viewMode === 'story' ? : null} + {customisedShowToolbar && isReviewCollectionStory ? : null} ({ isVisible: api.getIsNavShown(), singleStory: state.singleStory, - viewMode: state.viewMode, + isReviewCollectionStory: isReviewManagerRoute(state.path, state.customQueryParams), showSidebar: async (forceFocus: boolean) => { api.toggleNav(true); api.focusOnUIElement(focusableUIElements.sidebarRegion, { @@ -32,9 +33,10 @@ export const menuTool: Addon_BaseType = { render: () => { return ( - {({ isVisible, showSidebar, singleStory }) => + {({ isVisible, showSidebar, singleStory, isReviewCollectionStory }) => !singleStory && - !isVisible && ( + !isVisible && + !isReviewCollectionStory && ( <>