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

[WIP] Redux ui #1334

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9c87d54
wip
alexandrebodin Jun 18, 2017
bbebd47
create new ui and keep old
alexandrebodin Jun 21, 2017
b2c88b0
Add searchBox
alexandrebodin Jun 21, 2017
8a325f1
add layout
alexandrebodin Jun 21, 2017
c1b4138
add left panel base
alexandrebodin Jun 21, 2017
1b0e17f
start using glamorous
alexandrebodin Jun 21, 2017
c561f5d
add Stories component
alexandrebodin Jun 21, 2017
c9530c9
handle hierarchy
alexandrebodin Jun 21, 2017
00c904c
clean hierarchy handler
alexandrebodin Jun 21, 2017
fb61024
handle string nesting
alexandrebodin Jun 21, 2017
379c546
Clean action
alexandrebodin Jun 22, 2017
71a35f0
remove useless check on kind
alexandrebodin Jun 22, 2017
a1e3b17
merge reducers for easier state managment for now
alexandrebodin Jun 22, 2017
6e3a00b
put thunk first so logger only logs realy dispatch
alexandrebodin Jun 22, 2017
6db50b3
add shortcuts help
alexandrebodin Jun 22, 2017
6a6e08e
add platform back to shortcuts help
alexandrebodin Jun 22, 2017
ff4fbdd
filter
alexandrebodin Jun 22, 2017
2fe06bd
add down panel
alexandrebodin Jun 22, 2017
1932ad4
Merge branch 'master' into redux-ui
alexandrebodin Jun 26, 2017
514d489
Merge branch 'master' of github.com:storybooks/storybook into redux-ui
alexandrebodin Jun 28, 2017
c8bcb6b
init plugin work
alexandrebodin Jun 28, 2017
54ff3d1
add reducing , map state and middlware interaction
alexandrebodin Jun 28, 2017
daae7dc
handle some keybindings in the manager
alexandrebodin Jun 28, 2017
182284c
handle shortcuts in preview
alexandrebodin Jun 28, 2017
1b86a35
clean keymappings
alexandrebodin Jun 29, 2017
c9f5596
rename file to pass it into uppercase
alexandrebodin Jul 13, 2017
dd7bf12
rename
alexandrebodin Jul 13, 2017
67b374b
adding all current keyboard shortcuts
alexandrebodin Jul 14, 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 app/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"json-stringify-safe": "^5.0.1",
"json5": "^0.5.1",
"lodash.pick": "^4.4.0",
"mousetrap": "1.6.1",
"postcss-flexbugs-fixes": "^3.0.0",
"postcss-loader": "^2.0.5",
"prop-types": "^15.5.10",
Expand Down
4 changes: 2 additions & 2 deletions app/react/src/client/manager/provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export default class ReactProvider extends Provider {
this.channel.on('selectStory', data => {
api.selectStory(data.kind, data.story);
});
this.channel.on('applyShortcut', data => {
api.handleShortcut(data.event);
this.channel.on('applyShortcut', key => {
api.handleShortcut(key);
});
addons.loadAddons(api);
}
Expand Down
16 changes: 8 additions & 8 deletions app/react/src/client/preview/init.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import keyEvents from '@storybook/ui/dist/libs/key_events';
import keymap from '@storybook/ui/dist/new/keymap';
import Mousetrap from 'mousetrap';
import { selectStory } from './actions';

export default function(context) {
Expand All @@ -8,11 +9,10 @@ export default function(context) {
reduxStore.dispatch(selectStory(queryParams.selectedKind, queryParams.selectedStory));
}

// Handle keyEvents and pass them to the parent.
window.onkeydown = e => {
const parsedEvent = keyEvents(e);
if (parsedEvent) {
channel.emit('applyShortcut', { event: parsedEvent });
}
};
const keys = new Mousetrap(document);
keymap.forEach(({ key, action }) => {
keys.bind(key, () => {
channel.emit('applyShortcut', action);
});
});
}
2 changes: 1 addition & 1 deletion app/react/src/server/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function() {
test: /\.jsx?$/,
loader: require.resolve('babel-loader'),
query: babelLoaderConfig,
include: includePaths,
// include: includePaths,
exclude: excludePaths,
},
],
Expand Down
2 changes: 2 additions & 0 deletions examples/cra-kitchen-sink/.storybook/addons.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ import '@storybook/addon-events/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-options/register';
import '@storybook/addon-knobs/register';

import '../../../plugins/viewports';
4 changes: 3 additions & 1 deletion examples/cra-kitchen-sink/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,22 @@
"prop-types": "^15.5.10",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"redux-logger": "3.0.6",
"uuid": "^3.0.1"
},
"devDependencies": {
"@storybook/addon-actions": "^3.0.0",
"@storybook/addon-centered": "^3.0.0",
"@storybook/addon-events": "^3.0.0",
"@storybook/addon-knobs": "^3.0.0",
"@storybook/addon-info": "^3.0.0",
"@storybook/addon-knobs": "^3.0.0",
"@storybook/addon-links": "^3.0.0",
"@storybook/addon-notes": "^3.0.0",
"@storybook/addon-options": "^3.0.0",
"@storybook/addon-storyshots": "^3.0.0",
"@storybook/addons": "^3.0.0",
"@storybook/react": "^3.0.0",
"@storybook/ui": "^3.0.0",
"react-scripts": "1.0.1"
},
"private": true
Expand Down
9 changes: 9 additions & 0 deletions examples/cra-kitchen-sink/src/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,17 @@ const EVENTS = {
const emiter = new EventEmiter();
const emit = emiter.emit.bind(emiter);

storiesOf('Welcome/Sub/Sub2/Sub3', module).add('to Storybook 1', () => <Welcome showApp={linkTo('Button')} />);
storiesOf('Welcome/Sub/Sub2/Sub3', module).add('to Storybook 2', () => <Welcome showApp={linkTo('Button')} />);
storiesOf('Welcome/Sub/Sub2/Sub3', module).add('to Storybook 3', () => <Welcome showApp={linkTo('Button')} />);

storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);

storiesOf('Welcome/Sub', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
storiesOf('Welcome/Sub', module).add('to Storybook 2', () => <Welcome showApp={linkTo('Button')} />);
storiesOf('Welcome/Sub', module).add('to Storybook 3', () => <Welcome showApp={linkTo('Button')} />);
storiesOf('Welcome/Sub', module).add('to Storybook 4', () => <Welcome showApp={linkTo('Button')} />);

storiesOf('Button', module)
.addDecorator(withKnobs)
.add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
Expand Down
3 changes: 2 additions & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"addons/*",
"app/*",
"lib/*",
"examples/*"
"examples/*",
"plugins/*"
],
"concurrency": 1,
"version": "3.1.7"
Expand Down
10 changes: 8 additions & 2 deletions lib/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "3.1.6",
"description": "Core Storybook UI",
"license": "MIT",
"main": "dist/index.js",
"main": "dist/new/index.js",
"repository": {
"type": "git",
"url": "https://github.com/storybooks/storybook.git"
Expand All @@ -19,20 +19,26 @@
"deep-equal": "^1.0.1",
"events": "^1.1.1",
"fuzzysearch": "^1.0.3",
"glamor": "2.20.25",
"glamorous": "3.23.3",
"global": "^4.3.2",
"json-stringify-safe": "^5.0.1",
"keycode": "^2.1.8",
"lodash.pick": "^4.4.0",
"lodash.set": "4.3.2",
"lodash.sortby": "^4.7.0",
"mantra-core": "^1.7.0",
"mousetrap": "1.6.1",
"podda": "^1.2.2",
"prop-types": "^15.5.8",
"qs": "^6.4.0",
"react-inspector": "^2.0.0",
"react-komposer": "^2.0.0",
"react-modal": "^1.7.6",
"react-redux": "5.0.5",
"react-split-pane": "^0.1.63",
"redux": "^3.6.0"
"redux": "3.7.0",
"redux-thunk": "2.2.0"
},
"devDependencies": {
"enzyme": "^2.8.2"
Expand Down
82 changes: 82 additions & 0 deletions lib/ui/src/new/actions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { TOGGLE_FULLSCREEN, TOGGLE_SHORTCUTSHELP, TOGGLE_SEARCHBOX } from '../constants/actions';

const findNewSelectedStory = ({ stories }, kind, story) => {
let newKind = kind;
let newStory = story;

if (!kind) {
newKind = stories[0].kind;
}

if (!story) {
const matchingStories = stories
.filter(s => s.kind.indexOf(newKind) >= 0)
.filter(s => s.stories && s.stories.length > 0)
.sort((a, b) => a.kind.length - b.kind.length);

newStory = matchingStories ? matchingStories[0].stories[0] : '';
newKind = matchingStories[0].kind;
}

return {
newKind,
newStory,
};
};

export const loadStories = stories => {
return (dispatch, getState) => {
dispatch({
type: 'LOAD_STORIES',
stories,
});

const { selectedKind, selectedStory } = getState().ui;
const { newKind, newStory } = findNewSelectedStory(getState(), selectedKind, selectedStory);

if (selectedKind !== newKind || selectedStory !== newStory) {
dispatch({
type: 'SELECT_STORY',
kind: newKind,
story: newStory,
});
}
};
};

export const toggleFullScreen = value => ({
type: TOGGLE_FULLSCREEN,
value,
});

export const toggleSearchBox = value => ({
type: TOGGLE_SEARCHBOX,
value,
});

export const changeStoryFilter = filter => ({
type: 'CHANGE_STORYFILTER',
filter,
});

export const selectStory = (kind, story) => {
return (dispatch, getState) => {
const { newKind, newStory } = findNewSelectedStory(getState(), kind, story);

dispatch({
type: 'SELECT_STORY',
kind: newKind,
story: newStory,
});
};
};

export const toggleShortcutsHelp = value => ({
type: TOGGLE_SHORTCUTSHELP,
value,
});

export const selectPanel = panelName => ({
type: 'SELECT_PANEL',
panelName,
});
138 changes: 138 additions & 0 deletions lib/ui/src/new/components/DownPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { baseFonts } from './theme';

const style = {
empty: {
flex: 1,
display: 'flex',
...baseFonts,
fontSize: 11,
letterSpacing: '1px',
textTransform: 'uppercase',
alignItems: 'center',
justifyContent: 'center',
},

wrapper: {
flex: 1,
display: 'flex',
flexDirection: 'column',
background: 'white',
borderRadius: 4,
border: 'solid 1px rgb(236, 236, 236)',
marginTop: 5,
width: '100%',
},

tabbar: {
display: 'flex',
flexWrap: 'wrap',
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
borderBottom: 'solid 1px #eaeaea',
},

content: {
flex: 1,
position: 'relative',
display: 'flex',
overflow: 'auto',
},

tablink: {
...baseFonts,
fontSize: 11,
letterSpacing: '1px',
padding: '10px 15px',
textDecoration: 'none',
textTransform: 'uppercase',
transition: 'opacity 0.3s',
opacity: 0.5,
maxHeight: 60,
overflow: 'hidden',
cursor: 'pointer',
},

activetab: {
opacity: 1,
},
};

class DownPanel extends Component {
renderTab(name, panel) {
let tabStyle = style.tablink;
if (this.props.selectedPanel === name) {
tabStyle = Object.assign({}, style.tablink, style.activetab);
}

const onClick = () => e => {
e.preventDefault();
this.props.onPanelSelect(name);
};

let title = panel.title;
if (typeof title === 'function') {
title = title();
}

return (
<a key={name} style={tabStyle} onClick={onClick()} role="tab" tabIndex="0">
{title}
</a>
);
}

renderTabs() {
return Object.keys(this.props.panels).map(name => {
const panel = this.props.panels[name];
return this.renderTab(name, panel);
});
}

renderPanels() {
return Object.keys(this.props.panels).sort().map(name => {
const panelStyle = { display: 'none' };
const panel = this.props.panels[name];
if (name === this.props.selectedPanel) {
Object.assign(panelStyle, { flex: 1, display: 'flex' });
}
return <div key={name} style={panelStyle} role="tabpanel">{panel.render()}</div>;
});
}

renderEmpty() {
return (
<div style={style.empty}>
no panels available
</div>
);
}

render() {
if (!this.props.panels || !Object.keys(this.props.panels).length) {
return this.renderEmpty();
}
return (
<div style={style.wrapper}>
<div style={style.tabbar} role="tablist">{this.renderTabs()}</div>
<div style={style.content}>{this.renderPanels()}</div>
</div>
);
}
}

DownPanel.defaultProps = {
panels: {},
onPanelSelect: () => {},
selectedPanel: null,
};

DownPanel.propTypes = {
panels: PropTypes.object, // eslint-disable-line react/forbid-prop-types
onPanelSelect: PropTypes.func,
selectedPanel: PropTypes.string,
};

export default DownPanel;
Loading