Skip to content

Commit

Permalink
Merge pull request #13685 from storybookjs/feature/collapseRoot
Browse files Browse the repository at this point in the history
UI: Add collapse roots to sidebar navigation
  • Loading branch information
shilman authored Feb 25, 2021
2 parents df766e2 + 15577cc commit fe97d11
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 23 deletions.
1 change: 1 addition & 0 deletions examples/official-storybook/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ addons.setConfig({
hidden: true,
},
},
collapsedRoots: ['other'],
});
4 changes: 3 additions & 1 deletion lib/api/src/lib/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface Root {
isComponent: false;
isRoot: true;
isLeaf: false;
startCollapsed?: boolean;
}

export interface Group {
Expand Down Expand Up @@ -143,7 +144,7 @@ export const transformStoriesRawToStoriesHash = (

const storiesHashOutOfOrder = values.reduce((acc, item) => {
const { kind, parameters } = item;
const { showRoots } = provider.getConfig();
const { showRoots, collapsedRoots = [] } = provider.getConfig();

const setShowRoots = typeof showRoots !== 'undefined';
if (usesOldHierarchySeparator && !setShowRoots) {
Expand Down Expand Up @@ -176,6 +177,7 @@ export const transformStoriesRawToStoriesHash = (
isComponent: false,
isLeaf: false,
isRoot: true,
startCollapsed: collapsedRoots.includes(id),
});
} else {
list.push({
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/components/sidebar/RefIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ export const RefIndicator = React.memo(
</MessageWrapper>
}
>
<IndicatorClickTarget>
<IndicatorClickTarget data-action="toggle-indicator">
<Icons icon="globe" />
</IndicatorClickTarget>
</WithTooltip>
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/src/components/sidebar/Refs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const Ref: FunctionComponent<RefType & RefProps> = React.memo((props) =>
aria-label={`${isExpanded ? 'Hide' : 'Show'} ${title} stories`}
aria-expanded={isExpanded}
>
<CollapseButton onClick={handleClick}>
<CollapseButton data-action="collapse-ref" onClick={handleClick}>
<CollapseIcon isExpanded={isExpanded} />
<RefTitle title={title}>{title}</RefTitle>
</CollapseButton>
Expand Down
87 changes: 74 additions & 13 deletions lib/ui/src/components/sidebar/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,15 @@ import { Icons } from '@storybook/components';
import { transparentize } from 'polished';
import React, { MutableRefObject, useCallback, useMemo, useRef } from 'react';

import { ComponentNode, DocumentNode, GroupNode, RootNode, StoryNode } from './TreeNode';
import { useExpanded, ExpandAction } from './useExpanded';
import {
ComponentNode,
DocumentNode,
GroupNode,
RootNode,
StoryNode,
CollapseIcon,
} from './TreeNode';
import { useExpanded, ExpandAction, ExpandedState } from './useExpanded';
import { Highlight, Item } from './types';
import { createId, getAncestorIds, getDescendantIds, getLink } from './utils';

Expand All @@ -16,6 +23,7 @@ export const Action = styled.button(({ theme }) => ({
width: 20,
height: 20,
margin: 0,
marginLeft: 'auto',
padding: 0,
outline: 0,
lineHeight: 'normal',
Expand All @@ -42,6 +50,44 @@ export const Action = styled.button(({ theme }) => ({
},
}));

const CollapseButton = styled.button(({ theme }) => ({
// Reset button
background: 'transparent',
border: 'none',
outline: 'none',
boxSizing: 'content-box',
cursor: 'pointer',
position: 'relative',
textAlign: 'left',
lineHeight: 'normal',
font: 'inherit',
color: 'inherit',
letterSpacing: 'inherit',
textTransform: 'inherit',

display: 'flex',
flex: '0 1 auto',
padding: '3px 10px 1px 1px',
margin: 0,
marginLeft: -19,
overflow: 'hidden',
borderRadius: 26,
transition: 'color 150ms, box-shadow 150ms',

'span:first-of-type': {
marginTop: 4,
marginRight: 7,
},

'&:focus': {
boxShadow: `0 0 0 1px ${theme.color.secondary}`,
color: theme.color.secondary,
'span:first-of-type': {
color: theme.color.secondary,
},
},
}));

interface NodeProps {
item: Item;
refId: string;
Expand Down Expand Up @@ -105,20 +151,33 @@ const Node = React.memo<NodeProps>(
data-ref-id={refId}
data-item-id={item.id}
data-nodetype="root"
aria-expanded={isExpanded}
>
{item.name}
<Action
<CollapseButton
type="button"
className="sidebar-subheading-action"
data-action="expand-all"
data-expanded={isFullyExpanded}
data-action="collapse-root"
onClick={(event) => {
event.preventDefault();
setFullyExpanded();
setExpanded({ ids: [item.id], value: !isExpanded });
}}
>
<Icons icon={isFullyExpanded ? 'collapse' : 'expandalt'} />
</Action>
<CollapseIcon isExpanded={isExpanded} />
{item.name}
</CollapseButton>
{isExpanded && (
<Action
type="button"
className="sidebar-subheading-action"
data-action="expand-all"
data-expanded={isFullyExpanded}
onClick={(event) => {
event.preventDefault();
setFullyExpanded();
}}
>
<Icons icon={isFullyExpanded ? 'collapse' : 'expandalt'} />
</Action>
)}
</RootNode>
);
}
Expand Down Expand Up @@ -197,16 +256,17 @@ export const Tree = React.memo<{
const containerRef = useRef<HTMLDivElement>(null);

// Find top-level nodes and group them so we can hoist any orphans and expand any roots.
const [rootIds, orphanIds] = useMemo(
const [rootIds, orphanIds, initialExpanded] = useMemo(
() =>
Object.keys(data).reduce<[string[], string[]]>(
Object.keys(data).reduce<[string[], string[], ExpandedState]>(
(acc, id) => {
const item = data[id];
if (isRoot(item)) acc[0].push(id);
else if (!item.parent) acc[1].push(id);
if (isRoot(item) && item.startCollapsed) acc[2][id] = false;
return acc;
},
[[], []]
[[], [], {}]
),
[data]
);
Expand Down Expand Up @@ -277,6 +337,7 @@ export const Tree = React.memo<{
isBrowsing, // only enable keyboard shortcuts when tree is visible
refId,
data: collapsedData,
initialExpanded,
rootIds,
highlightedRef,
setHighlightedItemId,
Expand Down
9 changes: 6 additions & 3 deletions lib/ui/src/components/sidebar/TreeNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ export const CollapseIcon = styled.span<{ isExpanded: boolean }>(({ theme, isExp
marginTop: 6,
marginLeft: 8,
marginRight: 5,
color: transparentize(0.4, theme.color.mediumdark),
borderTop: '3px solid transparent',
borderBottom: '3px solid transparent',
borderLeft: `3px solid ${transparentize(0.4, theme.color.mediumdark)}`,
borderLeft: `3px solid`,
transform: isExpanded ? 'rotateZ(90deg)' : 'none',
transition: 'transform .1s ease-out',
}));
Expand Down Expand Up @@ -121,11 +122,13 @@ export const Path = styled.span(({ theme }) => ({
},
}));

export const RootNode = styled.span(({ theme }) => ({
export const RootNode = styled.div(({ theme }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
margin: '16px 20px 4px 20px',
padding: '0 20px',
marginTop: 16,
marginBottom: 4,
fontSize: `${theme.typography.size.s1 - 1}px`,
fontWeight: theme.typography.weight.black,
lineHeight: '16px',
Expand Down
13 changes: 9 additions & 4 deletions lib/ui/src/components/sidebar/useExpanded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface ExpandedProps {
isBrowsing: boolean;
refId: string;
data: StoriesHash;
initialExpanded?: ExpandedState;
rootIds: string[];
highlightedRef: MutableRefObject<Highlight>;
setHighlightedItemId: (storyId: string) => void;
Expand All @@ -30,11 +31,13 @@ export interface ExpandedProps {
const initializeExpanded = ({
refId,
data,
initialExpanded,
highlightedRef,
rootIds,
}: {
refId: string;
data: StoriesHash;
initialExpanded?: ExpandedState;
highlightedRef: MutableRefObject<Highlight>;
rootIds: string[];
}) => {
Expand All @@ -43,7 +46,7 @@ const initializeExpanded = ({
? getAncestorIds(data, highlightedRef.current?.itemId)
: [];
return [...rootIds, ...highlightedAncestors].reduce<ExpandedState>(
(acc, id) => Object.assign(acc, { [id]: true }),
(acc, id) => Object.assign(acc, { [id]: id in initialExpanded ? initialExpanded[id] : true }),
{}
);
};
Expand All @@ -55,28 +58,30 @@ export const useExpanded = ({
isBrowsing,
refId,
data,
initialExpanded,
rootIds,
highlightedRef,
setHighlightedItemId,
selectedStoryId,
onSelectStoryId,
}: ExpandedProps): [Record<string, boolean>, Dispatch<ExpandAction>] => {
}: ExpandedProps): [ExpandedState, Dispatch<ExpandAction>] => {
const api = useStorybookApi();

// Track the set of currently expanded nodes within this tree.
// Root nodes are expanded by default (and cannot be collapsed).
// Root nodes are expanded by default.
const [expanded, setExpanded] = useReducer<
React.Reducer<ExpandedState, ExpandAction>,
{
refId: string;
data: StoriesHash;
highlightedRef: MutableRefObject<Highlight>;
rootIds: string[];
initialExpanded: ExpandedState;
}
>(
(state, { ids, value }) =>
ids.reduce((acc, id) => Object.assign(acc, { [id]: value }), { ...state }),
{ refId, data, highlightedRef, rootIds },
{ refId, data, highlightedRef, rootIds, initialExpanded },
initializeExpanded
);

Expand Down

0 comments on commit fe97d11

Please sign in to comment.