Skip to content

Commit

Permalink
Merge pull request #26184 from literalpie/literalpie/switching-storie…
Browse files Browse the repository at this point in the history
…s-performance

UI: Improve sidebar performance when switching stories
  • Loading branch information
ndelangen authored Feb 27, 2024
2 parents 670c58c + e5e51b4 commit 5771455
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 61 deletions.
39 changes: 23 additions & 16 deletions code/ui/manager/src/components/layout/LayoutProvider.tsx
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -32,22 +32,29 @@ export const LayoutProvider: FC<PropsWithChildren> = ({ children }) => {
const isDesktop = useMediaQuery(`(min-width: ${BREAKPOINT}px)`);
const isMobile = !isDesktop;

return (
<LayoutContext.Provider
value={{
isMobileMenuOpen,
setMobileMenuOpen,
isMobileAboutOpen,
setMobileAboutOpen,
isMobilePanelOpen,
setMobilePanelOpen,
isDesktop,
isMobile,
}}
>
{children}
</LayoutContext.Provider>
const contextValue = useMemo(
() => ({
isMobileMenuOpen,
setMobileMenuOpen,
isMobileAboutOpen,
setMobileAboutOpen,
isMobilePanelOpen,
setMobilePanelOpen,
isDesktop,
isMobile,
}),
[
isMobileMenuOpen,
setMobileMenuOpen,
isMobileAboutOpen,
setMobileAboutOpen,
isMobilePanelOpen,
setMobilePanelOpen,
isDesktop,
isMobile,
]
);
return <LayoutContext.Provider value={contextValue}>{children}</LayoutContext.Provider>;
};

export const useLayout = () => useContext(LayoutContext);
12 changes: 6 additions & 6 deletions code/ui/manager/src/components/sidebar/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -176,8 +176,8 @@ export const Search = React.memo<{
[api, inputRef, showAllComponents, DEFAULT_REF_ID]
);

const list: SearchItem[] = useMemo(() => {
return dataset.entries.reduce<SearchItem[]>((acc, [refId, { index, status }]) => {
const makeFuse = useCallback(() => {
const list = dataset.entries.reduce<SearchItem[]>((acc, [refId, { index, status }]) => {
const groupStatus = getGroupStatus(index || {}, status);

if (index) {
Expand All @@ -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[] = [];
Expand Down Expand Up @@ -229,7 +229,7 @@ export const Search = React.memo<{

return results;
},
[allComponents, fuse]
[allComponents, makeFuse]
);

const stateReducer = useCallback(
Expand Down
96 changes: 57 additions & 39 deletions code/ui/manager/src/components/sidebar/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -481,55 +481,73 @@ export const Tree = React.memo<{

const groupStatus = useMemo(() => getGroupStatus(collapsedData, status), [collapsedData, status]);

return (
<Container ref={containerRef} hasOrphans={isMain && orphanIds.length > 0}>
<IconSymbols />
{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)
<Root
key={id}
item={item}
refId={refId}
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;

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 (
<Node
api={api}
// @ts-expect-error (TODO)
<Root
key={id}
item={item}
status={status?.[itemId]}
refId={refId}
color={color}
docsMode={docsMode}
isOrphan={orphanIds.some((oid) => 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 (
<Node
api={api}
key={id}
item={item}
status={status?.[itemId]}
refId={refId}
color={color}
docsMode={docsMode}
isOrphan={orphanIds.some((oid) => 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 (
<Container ref={containerRef} hasOrphans={isMain && orphanIds.length > 0}>
<IconSymbols />
{treeItems}
</Container>
);
});

0 comments on commit 5771455

Please sign in to comment.