Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Add viewMode parameter to control story nav UI #9090

Merged
merged 7 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions addons/docs/docs/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,31 @@ User writes documentation & stories side-by-side in a single MDX file, and wants
</Story>
```

## Controlling a story's view mode

Storybook's default story navigation behavior is to preserve the existing view mode. In other words, if a user is viewing a story in "docs" mode, and clicks on another story, they will navigate to the other story in "docs" mode. If they are viewing a story in "story" mode (i.e. "canvas" in the UI) they will navigate to another story in "story" mode (with the exception of "docs-only" pages, which are always shown in "docs" mode).

Based on user feedback, it's also possible to control the view mode for an individual story using the `viewMode` story parameter. In the following example, the nav link will always set the view mode to story:

```js
export const Foo = () => <Component />;
Foo.story = {
parameters: {
// reset the view mode to "story" whenever the user navigates to this story
viewMode: 'story',
},
};
```

This can also be applied globally in `preview.js`:

```js
// always reset the view mode to "docs" whenever the user navigates
addParameters({
viewMode: 'docs',
});
```

## More resources

Want to learn more? Here are some more articles on Storybook Docs:
Expand Down
2 changes: 1 addition & 1 deletion examples/cra-react15/.storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ module.exports = {
addons: [
'@storybook/preset-create-react-app',
'@storybook/addon-actions',
'@storybook/addon-links'
'@storybook/addon-links',
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ButtonGroup } from '../../components/ButtonGroup';
export default {
title: 'Addons/Docs/ButtonGroup',
component: ButtonGroup,
parameters: { viewMode: 'docs' },
subcomponents: { DocgenButton },
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import Button, { Type } from '../../components/TsButton';
export default {
title: 'Addons/Docs/TsButton',
component: Button,
parameters: {
viewMode: 'story',
},
};

type Story = () => any;
Expand Down
3 changes: 3 additions & 0 deletions lib/api/src/modules/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ interface Group {
isComponent: boolean;
isRoot: boolean;
isLeaf: boolean;
// MDX stories are "Group" type
parameters?: any;
}

interface StoryInput {
Expand Down Expand Up @@ -286,6 +288,7 @@ Did you create a path that uses the separator char accidentally, such as 'Vue <d
isComponent: false,
isLeaf: false,
isRoot: !!root && index === 0,
parameters,
};
return soFar.concat([result]);
}, [] as GroupsList);
Expand Down
19 changes: 19 additions & 0 deletions lib/ui/src/components/sidebar/SidebarStories.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { viewMode } from './SidebarStories';

describe('viewMode', () => {
it('always links to parameters.viewMode if one is provided', () => {
expect(viewMode('foo', true, { viewMode: 'bar' })).toEqual('bar');
});
it('links to "docs" view mode for docs-only stories', () => {
expect(viewMode('foo', true, undefined)).toEqual('docs');
});
it('links to "story" viewMode there is no viewMode specified or not on a docs page', () => {
expect(viewMode(undefined, false, undefined)).toEqual('story');
expect(viewMode('settings', false, undefined)).toEqual('story');
});
it('links to the current viewMode by default', () => {
expect(viewMode('foo', false, undefined)).toEqual('foo');
expect(viewMode('story', false, undefined)).toEqual('story');
expect(viewMode('docs', false, undefined)).toEqual('docs');
});
});
27 changes: 20 additions & 7 deletions lib/ui/src/components/sidebar/SidebarStories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,22 @@ const PlainLink = styled.a(plain);

const Wrapper = styled.div({});

const refinedViewMode = (viewMode: string | undefined, isDocsOnly: boolean) => {
if (isDocsOnly) {
return 'docs';
export const viewMode = (
currentViewMode: string | undefined,
isDocsOnly: boolean,
parameters: { viewMode?: string } = {}
) => {
const { viewMode: paramViewMode } = parameters;
switch (true) {
case typeof paramViewMode === 'string':
return paramViewMode;
case isDocsOnly:
return 'docs';
case currentViewMode === 'settings' || !currentViewMode:
return 'story';
default:
return currentViewMode;
}
return viewMode === 'settings' || !viewMode ? 'story' : viewMode;
};

const targetId = (childIds?: string[]) =>
Expand All @@ -73,14 +84,17 @@ export const Link = ({
onKeyUp,
childIds,
isExpanded,
parameters,
}) => {
return isLeaf || (isComponent && !isExpanded) ? (
<Location>
{({ viewMode }) => (
{({ viewMode: currentViewMode }) => (
<PlainRouterLink
title={name}
id={prefix + id}
to={`/${refinedViewMode(viewMode, isLeaf && isComponent)}/${targetId(childIds) || id}`}
to={`/${viewMode(currentViewMode, isLeaf && isComponent, parameters)}/${targetId(
childIds
) || id}`}
onKeyUp={onKeyUp}
onClick={onClick}
>
Expand Down Expand Up @@ -161,7 +175,6 @@ const SidebarStories: FunctionComponent<StoriesProps> = memo(
</Wrapper>
);
}

return (
<Wrapper className={className}>
<TreeState
Expand Down