diff --git a/code/ui/manager/src/components/layout/LayoutProvider.tsx b/code/ui/manager/src/components/layout/LayoutProvider.tsx index ae088f6358d0..81c342e0546c 100644 --- a/code/ui/manager/src/components/layout/LayoutProvider.tsx +++ b/code/ui/manager/src/components/layout/LayoutProvider.tsx @@ -1,5 +1,5 @@ import type { FC, PropsWithChildren } from 'react'; -import React, { createContext, useContext, useState } from 'react'; +import React, { createContext, useContext, useMemo, useState } from 'react'; import { useMediaQuery } from '../hooks/useMedia'; import { BREAKPOINT } from '../../constants'; @@ -32,22 +32,29 @@ export const LayoutProvider: FC = ({ children }) => { const isDesktop = useMediaQuery(`(min-width: ${BREAKPOINT}px)`); const isMobile = !isDesktop; - return ( - - {children} - + const contextValue = useMemo( + () => ({ + isMobileMenuOpen, + setMobileMenuOpen, + isMobileAboutOpen, + setMobileAboutOpen, + isMobilePanelOpen, + setMobilePanelOpen, + isDesktop, + isMobile, + }), + [ + isMobileMenuOpen, + setMobileMenuOpen, + isMobileAboutOpen, + setMobileAboutOpen, + isMobilePanelOpen, + setMobilePanelOpen, + isDesktop, + isMobile, + ] ); + return {children}; }; export const useLayout = () => useContext(LayoutContext); diff --git a/code/ui/manager/src/components/sidebar/Search.tsx b/code/ui/manager/src/components/sidebar/Search.tsx index cbbecc8264a6..0df164a2d35b 100644 --- a/code/ui/manager/src/components/sidebar/Search.tsx +++ b/code/ui/manager/src/components/sidebar/Search.tsx @@ -5,7 +5,7 @@ import Downshift from 'downshift'; import type { FuseOptions } from 'fuse.js'; import Fuse from 'fuse.js'; import { global } from '@storybook/global'; -import React, { useMemo, useRef, useState, useCallback } from 'react'; +import React, { useRef, useState, useCallback } from 'react'; import { CloseIcon, SearchIcon } from '@storybook/icons'; import { DEFAULT_REF_ID } from './Sidebar'; import type { @@ -176,8 +176,8 @@ export const Search = React.memo<{ [api, inputRef, showAllComponents, DEFAULT_REF_ID] ); - const list: SearchItem[] = useMemo(() => { - return dataset.entries.reduce((acc, [refId, { index, status }]) => { + const makeFuse = useCallback(() => { + const list = dataset.entries.reduce((acc, [refId, { index, status }]) => { const groupStatus = getGroupStatus(index || {}, status); if (index) { @@ -196,12 +196,12 @@ export const Search = React.memo<{ } return acc; }, []); + return new Fuse(list, options); }, [dataset]); - const fuse = useMemo(() => new Fuse(list, options), [list]); - const getResults = useCallback( (input: string) => { + const fuse = makeFuse(); if (!input) return []; let results: DownshiftItem[] = []; @@ -229,7 +229,7 @@ export const Search = React.memo<{ return results; }, - [allComponents, fuse] + [allComponents, makeFuse] ); const stateReducer = useCallback( diff --git a/code/ui/manager/src/components/sidebar/Tree.tsx b/code/ui/manager/src/components/sidebar/Tree.tsx index d1a566bddf4c..42aa27ce694a 100644 --- a/code/ui/manager/src/components/sidebar/Tree.tsx +++ b/code/ui/manager/src/components/sidebar/Tree.tsx @@ -481,55 +481,73 @@ export const Tree = React.memo<{ const groupStatus = useMemo(() => getGroupStatus(collapsedData, status), [collapsedData, status]); - return ( - 0}> - - {collapsedItems.map((itemId) => { - const item = collapsedData[itemId]; - const id = createId(itemId, refId); - - if (item.type === 'root') { - const descendants = expandableDescendants[item.id]; - const isFullyExpanded = descendants.every((d: string) => expanded[d]); - return ( - // @ts-expect-error (TODO) - - ); - } - - const isDisplayed = !item.parent || ancestry[itemId].every((a: string) => expanded[a]); - const color = groupStatus[itemId] ? statusMapping[groupStatus[itemId]][1] : null; - + const treeItems = useMemo(() => { + return collapsedItems.map((itemId) => { + const item = collapsedData[itemId]; + const id = createId(itemId, refId); + + if (item.type === 'root') { + const descendants = expandableDescendants[item.id]; + const isFullyExpanded = descendants.every((d: string) => expanded[d]); return ( - itemId === oid || itemId.startsWith(`${oid}-`))} - isDisplayed={isDisplayed} + isOrphan={false} + isDisplayed isSelected={selectedStoryId === itemId} isExpanded={!!expanded[itemId]} setExpanded={setExpanded} + isFullyExpanded={isFullyExpanded} + expandableDescendants={descendants} onSelectStoryId={onSelectStoryId} /> ); - })} + } + + const isDisplayed = !item.parent || ancestry[itemId].every((a: string) => expanded[a]); + const color = groupStatus[itemId] ? statusMapping[groupStatus[itemId]][1] : null; + + return ( + itemId === oid || itemId.startsWith(`${oid}-`))} + isDisplayed={isDisplayed} + isSelected={selectedStoryId === itemId} + isExpanded={!!expanded[itemId]} + setExpanded={setExpanded} + onSelectStoryId={onSelectStoryId} + /> + ); + }); + }, [ + ancestry, + api, + collapsedData, + collapsedItems, + docsMode, + expandableDescendants, + expanded, + groupStatus, + onSelectStoryId, + orphanIds, + refId, + selectedStoryId, + setExpanded, + status, + ]); + return ( + 0}> + + {treeItems} ); });