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

Add a storybook for the ui package #2504

Merged
merged 23 commits into from
Dec 22, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e77a198
Added first story as POC
tmeasday Nov 27, 2017
e625eb8
Added stories for @storybook/components
tmeasday Nov 27, 2017
2ed0698
Added stories for stories tree
tmeasday Nov 27, 2017
51361a8
Added remaining stories for stories_panel
tmeasday Dec 18, 2017
e50ceaa
Added stories for remaining components
tmeasday Dec 18, 2017
c4bc58b
Merge branch 'release/3.3' into tmeasday/add-stories
ndelangen Dec 18, 2017
04dc8e0
Merge branch 'release/3.3' into tmeasday/add-stories
ndelangen Dec 18, 2017
1de6949
Use linked package for ui storybook dev dependencies
tmeasday Dec 19, 2017
f3d72ad
Use correct storybook version in components
tmeasday Dec 19, 2017
fda8975
Created `examples/official-storybook` with ui/components/addon stories
tmeasday Dec 20, 2017
ae60bb8
Move more complex component stories over
tmeasday Dec 20, 2017
92760d3
Use all addons in official storybook
tmeasday Dec 20, 2017
32acde3
This is required
tmeasday Dec 20, 2017
d093bfd
This wasn't still supposed to be here
tmeasday Dec 20, 2017
f2dbe6d
Merge branch 'release/3.3' into tmeasday/add-stories
ndelangen Dec 20, 2017
3b1d353
Working on moving most storyshots tests over to official-example
tmeasday Dec 21, 2017
432e2db
Merge branch 'release/3.3' into tmeasday/add-stories
ndelangen Dec 21, 2017
3b8be68
Disable ui/SearchBox story in storyshots
tmeasday Dec 21, 2017
913324e
Add snapshots for new stories.
tmeasday Dec 21, 2017
579cde7
Move --copy-files *before* --ignore for babel
tmeasday Dec 21, 2017
e4be9f5
Ignore __snapshots__ when building
tmeasday Dec 21, 2017
8823299
Merge branch 'release/3.3' into tmeasday/add-stories
Dec 21, 2017
1a0e285
Merge branch 'release/3.3' into tmeasday/add-stories
ndelangen Dec 22, 2017
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
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module.exports = {
'**/example/**',
'*.js',
'**/*.test.js',
'**/*.stories.js',
'**/scripts/*.js',
'**/stories/**/*.js',
'**/__tests__/**/*.js',
Expand Down
3 changes: 3 additions & 0 deletions .storybook/addons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not use a /examples/<any> here? Do we really have to add something to the root of the project?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be happy with an examples/official or something, where we have a storybook to demo storybook's UI components.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any problem with that. The only thing is potentially wanting to combine all react-based storybooks in a single storybook (components, ui, cra-vanilla).

[This works better for chromatic for instance. I'm not sure it helps much else -- maybe storyshots?]

Maybe examples/offical-storybook or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or examples/meta[-storybook]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

examples/offical-storybook would get my vote


import '@storybook/addon-actions/register';
14 changes: 14 additions & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved, import/extensions */
import React from 'react';
import { configure } from '@storybook/react';

function loadStories() {
let req;
req = require.context('../lib/ui/src', true, /\.stories\.js$/);
req.keys().forEach(filename => req(filename));

req = require.context('../lib/components/src', true, /\.stories\.js$/);
req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);
4 changes: 4 additions & 0 deletions lib/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@
"peerDependencies": {
"react": "*",
"react-dom": "*"
},
"devDependencies": {
"@storybook/react": "^3.2.16",
"@storybook/addon-actions": "^3.2.16"
}
}
12 changes: 12 additions & 0 deletions lib/components/src/navigation/menu_link.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { storiesOf } from '@storybook/react';

import MenuLink from './menu_link';

storiesOf('components/MenuLink', module)
.add('default', () => <MenuLink href="http://google.com">Link</MenuLink>)
.add('active', () => (
<MenuLink active href="http://google.com">
Link
</MenuLink>
));
10 changes: 10 additions & 0 deletions lib/components/src/navigation/routed_link.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import RoutedLink from './routed_link';

const onClick = action('onClick');
storiesOf('components/RoutedLink', module)
.add('w/ onClick', () => <RoutedLink onClick={onClick}>Link</RoutedLink>)
.add('w/ href', () => <RoutedLink href="http://google.com">Link</RoutedLink>);
4 changes: 4 additions & 0 deletions lib/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
"peerDependencies": {
"react": "*",
"react-dom": "*"
},
"devDependencies": {
"@storybook/react": "^3.2.16",
"@storybook/addon-actions": "^3.2.16"
}
}
29 changes: 29 additions & 0 deletions lib/ui/src/libs/withLifecycleDecorator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';

// A small utility to add before/afterEach to stories.
class WithLifecyle extends Component {
componentWillMount() {
this.props.beforeEach();
}
componentWillUnmount() {
this.props.afterEach();
}
render() {
return this.props.storyFn();
}
}

WithLifecyle.propTypes = {
storyFn: PropTypes.func.isRequired,
beforeEach: PropTypes.func,
afterEach: PropTypes.func,
};
WithLifecyle.defaultProps = {
beforeEach: () => {},
afterEach: () => {},
};

export default ({ beforeEach, afterEach }) => storyFn => (
<WithLifecyle beforeEach={beforeEach} afterEach={afterEach} storyFn={storyFn} />
);
28 changes: 28 additions & 0 deletions lib/ui/src/modules/ui/components/addon_panel/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import AddonPanel from './index';

const panels = {
test1: {
title: 'Test 1',
render() {
return <div id="test1">TEST 1</div>;
},
},
test2: {
title: 'Test 2',
render() {
return <div id="test2">TEST 2</div>;
},
},
};

const onPanelSelect = action('onPanelSelect');
storiesOf('ui/AddonPanel', module)
.addDecorator(s => <div style={{ height: '100px', display: 'flex' }}>{s()}</div>)
.add('default', () => (
<AddonPanel panels={panels} onPanelSelect={onPanelSelect} selectedPanel="test2" />
))
.add('no panels', () => <AddonPanel panels={{}} onPanelSelect={onPanelSelect} />);
72 changes: 72 additions & 0 deletions lib/ui/src/modules/ui/components/layout/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { storiesOf } from '@storybook/react';

import Layout from './index';

const panelStyle = {
position: 'absolute',
height: '100%',
width: '100%',
color: 'white',
};

const mockStoriesPanel = () => <div style={{ ...panelStyle, background: '#4abdac' }}>Stories</div>;
const mockAddonPanel = () => <div style={{ ...panelStyle, background: '#fc4a1a' }}>Addon</div>;
const mockPreviewPanel = () => <div style={{ ...panelStyle, background: '#f7b733' }}>Preview</div>;

storiesOf('ui/Layout', module)
.add('default', () => (
<Layout
showStoriesPanel
showAddonPanel
goFullScreen={false}
addonPanelInRight={false}
storiesPanel={mockStoriesPanel}
addonPanel={mockAddonPanel}
preview={mockPreviewPanel}
/>
))
.add('full screen', () => (
<Layout
showStoriesPanel={false}
showAddonPanel={false}
goFullScreen
addonPanelInRight={false}
storiesPanel={mockStoriesPanel}
addonPanel={mockAddonPanel}
preview={mockPreviewPanel}
/>
))
.add('no stories panel', () => (
<Layout
showStoriesPanel={false}
showAddonPanel
goFullScreen={false}
addonPanelInRight={false}
storiesPanel={mockStoriesPanel}
addonPanel={mockAddonPanel}
preview={mockPreviewPanel}
/>
))
.add('no addon panel', () => (
<Layout
showStoriesPanel
showAddonPanel={false}
goFullScreen={false}
addonPanelInRight={false}
storiesPanel={mockStoriesPanel}
addonPanel={mockAddonPanel}
preview={mockPreviewPanel}
/>
))
.add('addon panel in right', () => (
<Layout
showStoriesPanel
showAddonPanel
goFullScreen={false}
addonPanelInRight
storiesPanel={mockStoriesPanel}
addonPanel={mockAddonPanel}
preview={mockPreviewPanel}
/>
));
11 changes: 11 additions & 0 deletions lib/ui/src/modules/ui/components/menu_item.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import MenuItem from './menu_item';

storiesOf('ui/MenuItem', module).add('default', () => (
<MenuItem title="title" onClick={action('onClick')}>
Content
</MenuItem>
));
19 changes: 19 additions & 0 deletions lib/ui/src/modules/ui/components/search_box.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import SearchBox from './search_box';

const stories = [
{
kind: 'a',
stories: ['b', 'c'],
},
];
const onSelectStory = action('onSelectStory');
const onClose = action('onClose');
storiesOf('ui/SearchBox', module)
.add('default', () => <SearchBox showSearchBox onSelectStory={onSelectStory} onClose={onClose} />)
.add('with stories', () => (
<SearchBox showSearchBox onSelectStory={onSelectStory} onClose={onClose} stories={stories} />
));
10 changes: 10 additions & 0 deletions lib/ui/src/modules/ui/components/stories_panel/header.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import Header from './header';

const openShortcutsHelp = action('openShortcutsHelp');
storiesOf('ui/stories/Header', module).add('simple', () => (
<Header name="name" url="http://google.com" openShortcutsHelp={openShortcutsHelp} />
));
54 changes: 54 additions & 0 deletions lib/ui/src/modules/ui/components/stories_panel/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import StoriesPanel from './index';
import { createHierarchy } from '../../libs/hierarchy';
import withLifecyle from '../../../../libs/withLifecycleDecorator';
import { setContext } from '../../../../compose';

const decorator = withLifecyle({
beforeEach() {
setContext({
clientStore: {
getAll() {
return { shortcutOptions: {} };
},
subscribe() {},
},
});
},
afterEach() {
setContext(null);
},
});

const storiesHierarchy = createHierarchy([{ kind: 'kk', namespaces: ['kk'], stories: ['bb'] }]);
const openShortcutsHelp = action('openShortcutsHelp');
const onStoryFilter = action('onStoryFilter');
storiesOf('ui/stories/StoriesPanel', module)
.addDecorator(decorator)
.add('default', () => (
<StoriesPanel
filter="xxxxx"
openShortcutsHelp={openShortcutsHelp}
onStoryFilter={onStoryFilter}
/>
))
.add('with storiesHierarchy prop', () => (
<StoriesPanel
storiesHierarchy={storiesHierarchy}
selectedKind="kk"
selectedStory="bb"
selectedHierarchy={['kk']}
openShortcutsHelp={openShortcutsHelp}
onStoryFilter={onStoryFilter}
/>
))
.add('storiesHierarchy exists but is empty', () => (
<StoriesPanel
storiesHierarchy={createHierarchy([])}
openShortcutsHelp={openShortcutsHelp}
onStoryFilter={onStoryFilter}
/>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react';
import { storiesOf } from '@storybook/react';

import Stories from './index';
import { setContext } from '../../../../../compose';
import { createHierarchy, prepareStoriesForHierarchy } from '../../../libs/hierarchy';
import { storyFilter } from '../../../libs/filters';
import withLifecyle from '../../../../../libs/withLifecycleDecorator';

const data = createHierarchy([
{ kind: 'a', name: 'a', namespaces: ['a'], stories: ['a1', 'a2'] },
{ kind: 'b', name: 'b', namespaces: ['b'], stories: ['b1', 'b2'] },
]);

const initialData = [
{
kind: 'some.name.item1',
stories: ['a1', 'a2'],
},
{
kind: 'another.space.20',
stories: ['b1', 'b2'],
},
];
const dataWithoutSeparator = createHierarchy(prepareStoriesForHierarchy(initialData));
const dataWithSeparator = createHierarchy(prepareStoriesForHierarchy(initialData, '\\.'));

const filter = 'th';
const selectedKind = 'another.space.20';

const filteredData = storyFilter(
prepareStoriesForHierarchy(initialData, '\\.'),
filter,
selectedKind
);

const filteredDataHierarchy = createHierarchy(filteredData);

const decorator = withLifecyle({
beforeEach() {
setContext({
clientStore: {
getAll() {
return { shortcutOptions: {} };
},
subscribe() {},
},
});
},
afterEach() {
setContext(null);
},
});

storiesOf('ui/stories/Stories', module)
.addDecorator(decorator)
.add('empty', () => (
<Stories
storiesHierarchy={createHierarchy([])}
selectedKind=""
selectedStory=""
selectedHierarchy={[]}
/>
))
.add('simple', () => (
<Stories
storiesHierarchy={data}
selectedKind="b"
selectedStory="b2"
selectedHierarchy={['b']}
/>
))
.add('with hierarchy - hierarchySeparator is defined', () => (
<Stories
storiesHierarchy={dataWithSeparator}
selectedKind="another.space.20"
selectedStory="b2"
selectedHierarchy={['another', 'space', '20']}
/>
))
.add('without hierarchy - hierarchySeparator is defined', () => (
<Stories
storiesHierarchy={dataWithoutSeparator}
selectedKind="another.space.20"
selectedStory="b2"
selectedHierarchy={['another.space.20']}
/>
))
.add('with highlighting when storiesFilter is provided', () => (
<Stories
storiesHierarchy={filteredDataHierarchy}
selectedKind={selectedKind}
selectedStory="b2"
selectedHierarchy={['another', 'space', '20']}
storyFilter={filter}
/>
));
Loading