diff --git a/examples/cra-kitchen-sink/.storybook/config.js b/examples/cra-kitchen-sink/.storybook/config.js
index 3ee683d25cd..f0d45642698 100644
--- a/examples/cra-kitchen-sink/.storybook/config.js
+++ b/examples/cra-kitchen-sink/.storybook/config.js
@@ -8,14 +8,14 @@ setOptions({
name: 'CRA Kitchen Sink',
url: 'https://github.com/storybooks/storybook/tree/master/examples/cra-kitchen-sink',
goFullScreen: false,
- showStoriesPanel: true,
+ // showStoriesPanel: true,
showAddonsPanel: true,
showSearchBox: false,
addonPanelInRight: true,
sortStoriesByKind: false,
hierarchySeparator: /\./,
hierarchyRootSeparator: /\|/,
-});
+}, 'shit');
// deprecated usage of infoAddon
setAddon(infoAddon);
diff --git a/lib/ui/src/modules/shortcuts/index.js b/lib/ui/src/modules/shortcuts/index.js
index b8c3b8fa659..c24a03e05b3 100755
--- a/lib/ui/src/modules/shortcuts/index.js
+++ b/lib/ui/src/modules/shortcuts/index.js
@@ -1,11 +1,16 @@
import actions from './actions';
+import checkIfMobileDevice from '../ui/libs/is_mobile_device';
+
+const { userAgent } = global.window.navigator;
+const isMobileDevice = checkIfMobileDevice(userAgent);
export default {
actions,
defaultState: {
+ isMobileDevice,
shortcutOptions: {
goFullScreen: false,
- showStoriesPanel: true,
+ showStoriesPanel: !isMobileDevice,
showAddonPanel: true,
showSearchBox: false,
addonPanelInRight: false,
diff --git a/lib/ui/src/modules/ui/components/__snapshots__/header.stories.storyshot b/lib/ui/src/modules/ui/components/__snapshots__/header.stories.storyshot
new file mode 100644
index 00000000000..e52a73ab1c0
--- /dev/null
+++ b/lib/ui/src/modules/ui/components/__snapshots__/header.stories.storyshot
@@ -0,0 +1,30 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots ui/stories/Header simple 1`] = `
+
+`;
diff --git a/lib/ui/src/modules/ui/components/stories_panel/header.js b/lib/ui/src/modules/ui/components/header.js
similarity index 52%
rename from lib/ui/src/modules/ui/components/stories_panel/header.js
rename to lib/ui/src/modules/ui/components/header.js
index 35a941ac8d8..91750c3b1e1 100755
--- a/lib/ui/src/modules/ui/components/stories_panel/header.js
+++ b/lib/ui/src/modules/ui/components/header.js
@@ -1,12 +1,13 @@
import PropTypes from 'prop-types';
import React from 'react';
import { baseFonts } from '@storybook/components';
+// import isMobileDevice from '../libs/is_mobile_device';
-const wrapperStyle = {
- background: '#F7F7F7',
- marginBottom: 10,
+const wrapperStyle = isMobileDevice => ({
+ background: isMobileDevice ? 'none' : '#F7F7F7',
+ margin: isMobileDevice ? '10px 0' : '0 0 10px',
display: 'flex',
-};
+});
const headingStyle = {
...baseFonts,
@@ -22,7 +23,7 @@ const headingStyle = {
overflow: 'hidden',
};
-const shortcutIconStyle = {
+const iconStyle = isMobileDevice => ({
textTransform: 'uppercase',
fontSize: 12,
fontWeight: 'bolder',
@@ -33,29 +34,39 @@ const shortcutIconStyle = {
cursor: 'pointer',
display: 'inlineBlock',
padding: 0,
- margin: '0 0 0 5px',
+ margin: isMobileDevice ? '0 15px' : '0 0 0 5px',
backgroundColor: 'inherit',
outline: 0,
width: 30,
flexShrink: 0,
+});
+
+const burgerIconStyle = {
+ ...iconStyle(true),
+ paddingBottom: 2,
};
-const linkStyle = {
+const linkStyle = isMobileDevice => ({
textDecoration: 'none',
flexGrow: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
- border: '1px solid rgb(193, 193, 193)',
+ border: isMobileDevice ? 'none' : '1px solid rgb(193, 193, 193)',
borderRadius: 2,
-};
+});
-const Header = ({ openShortcutsHelp, name, url }) => (
-
-
+const Header = ({ openShortcutsHelp, onBurgerButtonClick, name, url, isMobileDevice }) => (
+
+ {isMobileDevice && (
+
+ )}
+
{name}
-
@@ -63,14 +74,18 @@ const Header = ({ openShortcutsHelp, name, url }) => (
Header.defaultProps = {
openShortcutsHelp: null,
+ onBurgerButtonClick: null,
name: '',
url: '',
+ isMobileDevice: false,
};
Header.propTypes = {
openShortcutsHelp: PropTypes.func,
+ onBurgerButtonClick: PropTypes.func,
name: PropTypes.string,
url: PropTypes.string,
+ isMobileDevice: PropTypes.bool,
};
export default Header;
diff --git a/lib/ui/src/modules/ui/components/stories_panel/header.stories.js b/lib/ui/src/modules/ui/components/header.stories.js
similarity index 100%
rename from lib/ui/src/modules/ui/components/stories_panel/header.stories.js
rename to lib/ui/src/modules/ui/components/header.stories.js
diff --git a/lib/ui/src/modules/ui/components/stories_panel/header.test.js b/lib/ui/src/modules/ui/components/header.test.js
similarity index 100%
rename from lib/ui/src/modules/ui/components/stories_panel/header.test.js
rename to lib/ui/src/modules/ui/components/header.test.js
diff --git a/lib/ui/src/modules/ui/components/layout/index.js b/lib/ui/src/modules/ui/components/layout/index.js
index e3e3864356f..94ebb0f6b77 100755
--- a/lib/ui/src/modules/ui/components/layout/index.js
+++ b/lib/ui/src/modules/ui/components/layout/index.js
@@ -98,7 +98,11 @@ const defaultSizes = {
},
};
-const saveSizes = sizes => {
+const saveSizes = (sizes, isMobileDevice) => {
+ if (isMobileDevice) {
+ return true;
+ }
+
try {
localStorage.setItem('panelSizes', JSON.stringify(sizes));
return true;
@@ -107,7 +111,11 @@ const saveSizes = sizes => {
}
};
-const getSavedSizes = sizes => {
+const getSavedSizes = (sizes, isMobileDevice) => {
+ if (isMobileDevice) {
+ return sizes;
+ }
+
try {
const panelSizes = localStorage.getItem('panelSizes');
if (panelSizes) {
@@ -125,7 +133,7 @@ class Layout extends React.Component {
constructor(props) {
super(props);
- this.layerSizes = getSavedSizes(defaultSizes);
+ this.layerSizes = getSavedSizes(defaultSizes, props.isMobileDevice);
this.state = {
previewPanelDimensions: {
@@ -159,7 +167,7 @@ class Layout extends React.Component {
onResize(pane, mode) {
return size => {
this.layerSizes[pane][mode] = size;
- saveSizes(this.layerSizes);
+ saveSizes(this.layerSizes, this.props.isMobileDevice);
const { clientWidth, clientHeight } = this.previewPanelRef;
@@ -177,13 +185,15 @@ class Layout extends React.Component {
goFullScreen,
showStoriesPanel,
showAddonPanel,
- addonPanelInRight,
addonPanel,
storiesPanel,
preview,
+ isMobileDevice,
} = this.props;
const { previewPanelDimensions } = this.state;
+ const addonPanelInRight = isMobileDevice ? 0 : this.props.addonPanelInRight;
+
const storiesPanelOnTop = false;
let previewStyle = normalPreviewStyle;
@@ -192,7 +202,7 @@ class Layout extends React.Component {
previewStyle = fullScreenPreviewStyle;
}
- const sizes = getSavedSizes(this.layerSizes);
+ const sizes = getSavedSizes(this.layerSizes, isMobileDevice);
const storiesPanelDefaultSize = !storiesPanelOnTop
? sizes.storiesPanel.left
@@ -209,7 +219,7 @@ class Layout extends React.Component {
-
+ {!isMobileDevice && }
onStoryFilter('')}
diff --git a/lib/ui/src/modules/ui/components/stories_panel/index.test.js b/lib/ui/src/modules/ui/components/stories_panel/index.test.js
index f88a6705777..70ffd9fbd5d 100755
--- a/lib/ui/src/modules/ui/components/stories_panel/index.test.js
+++ b/lib/ui/src/modules/ui/components/stories_panel/index.test.js
@@ -1,7 +1,7 @@
import React from 'react';
import { shallow } from 'enzyme';
import StoriesPanel from './index';
-import Header from './header';
+import Header from '../header';
import TextFilter from './text_filter';
import Stories from './stories_tree';
import { createHierarchies } from '../../libs/hierarchy';
diff --git a/lib/ui/src/modules/ui/containers/header.js b/lib/ui/src/modules/ui/containers/header.js
new file mode 100755
index 00000000000..6637dcc049e
--- /dev/null
+++ b/lib/ui/src/modules/ui/containers/header.js
@@ -0,0 +1,38 @@
+import pick from 'lodash.pick';
+import Header from '../components/header';
+import genPoddaLoader from '../libs/gen_podda_loader';
+import compose from '../../../compose';
+
+export const headerMapper = (state, props, { actions }) => {
+ const currentOptions = pick(
+ state.shortcutOptions,
+ 'showStoriesPanel',
+ 'showAddonPanel',
+ 'goFullScreen',
+ 'addonPanelInRight'
+ );
+
+ const actionMap = actions();
+ const { uiOptions, isMobileDevice } = state;
+ const { name, url } = uiOptions;
+
+ const handleBurgerButtonClick = () => {
+ actionMap.shortcuts.setOptions({
+ showStoriesPanel: !currentOptions.showStoriesPanel,
+ });
+ };
+
+ const addonPanelInRight = isMobileDevice ? false : currentOptions.addonPanelInRight;
+
+ return {
+ name,
+ url,
+ ...currentOptions,
+ openShortcutsHelp: actionMap.ui.toggleShortcutsHelp,
+ onBurgerButtonClick: handleBurgerButtonClick,
+ isMobileDevice,
+ addonPanelInRight,
+ };
+};
+
+export default compose(genPoddaLoader(headerMapper))(Header);
diff --git a/lib/ui/src/modules/ui/containers/header.test.js b/lib/ui/src/modules/ui/containers/header.test.js
new file mode 100755
index 00000000000..734ea22f60a
--- /dev/null
+++ b/lib/ui/src/modules/ui/containers/header.test.js
@@ -0,0 +1,39 @@
+import { headerMapper } from './header';
+
+describe('manager.ui.containers.header', () => {
+ describe('headerMapper', () => {
+ test('should give correct data', () => {
+ const uiOptions = {
+ name: 'foo',
+ url: 'bar',
+ };
+ const shortcutOptions = {
+ showStoriesPanel: 'aa',
+ showAddonPanel: 'bb',
+ goFullScreen: 'cc',
+ addonPanelInRight: true,
+ };
+ const toggleShortcutsHelp = () => 'toggleShortcutsHelp';
+ const props = {};
+ const env = {
+ actions: () => ({
+ ui: {
+ toggleShortcutsHelp,
+ },
+ }),
+ };
+ const state = {
+ uiOptions,
+ shortcutOptions,
+ };
+
+ const result = headerMapper(state, props, env);
+
+ expect(result.showStoriesPanel).toEqual('aa');
+ expect(result.showAddonPanel).toEqual('bb');
+ expect(result.goFullScreen).toEqual('cc');
+ expect(result.addonPanelInRight).toEqual('lalala');
+ expect(result.openShortcutsHelp).toBe(toggleShortcutsHelp);
+ });
+ });
+});
diff --git a/lib/ui/src/modules/ui/containers/layout.js b/lib/ui/src/modules/ui/containers/layout.js
index cb89879735e..4ed41635229 100755
--- a/lib/ui/src/modules/ui/containers/layout.js
+++ b/lib/ui/src/modules/ui/containers/layout.js
@@ -2,8 +2,21 @@ import pick from 'lodash.pick';
import Layout from '../components/layout';
import genPoddaLoader from '../libs/gen_podda_loader';
import compose from '../../../compose';
+import isMobileDevice from '../libs/is_mobile_device';
-export const mapper = ({ shortcutOptions }) =>
- pick(shortcutOptions, 'showStoriesPanel', 'showAddonPanel', 'goFullScreen', 'addonPanelInRight');
+export const shortcutMapper = state => {
+ const currentOptions = pick(
+ state.shortcutOptions,
+ 'showStoriesPanel',
+ 'showAddonPanel',
+ 'goFullScreen',
+ 'addonPanelInRight'
+ );
-export default compose(genPoddaLoader(mapper))(Layout);
+ return {
+ ...currentOptions,
+ isMobileDevice,
+ };
+};
+
+export default compose(genPoddaLoader(shortcutMapper))(Layout);
diff --git a/lib/ui/src/modules/ui/containers/layout.test.js b/lib/ui/src/modules/ui/containers/layout.test.js
index 2aabf74f37d..e656cccdff3 100755
--- a/lib/ui/src/modules/ui/containers/layout.test.js
+++ b/lib/ui/src/modules/ui/containers/layout.test.js
@@ -1,7 +1,7 @@
-import { mapper } from './layout';
+import { shortcutMapper } from './layout';
describe('manager.ui.containers.layout', () => {
- describe('mapper', () => {
+ describe('shortcutMapper', () => {
test('should give correct data', () => {
const state = {
shortcutOptions: {
@@ -10,7 +10,7 @@ describe('manager.ui.containers.layout', () => {
goFullScreen: 'cc',
},
};
- const data = mapper(state);
+ const data = shortcutMapper(state);
expect(data).toEqual(state.shortcutOptions);
});
diff --git a/lib/ui/src/modules/ui/containers/stories_panel.js b/lib/ui/src/modules/ui/containers/stories_panel.js
index bf0f0a6f07a..5dbd7f4a471 100755
--- a/lib/ui/src/modules/ui/containers/stories_panel.js
+++ b/lib/ui/src/modules/ui/containers/stories_panel.js
@@ -15,8 +15,6 @@ export const mapper = (state, props, { actions }) => {
const { stories, selectedKind, selectedStory, uiOptions, storyFilter } = state;
const {
- name,
- url,
sortStoriesByKind,
hierarchySeparator,
hierarchyRootSeparator,
@@ -52,10 +50,7 @@ export const mapper = (state, props, { actions }) => {
storyFilter,
onStoryFilter: actionMap.ui.setStoryFilter,
- openShortcutsHelp: actionMap.ui.toggleShortcutsHelp,
sidebarAnimations,
- name,
- url,
};
};
diff --git a/lib/ui/src/modules/ui/containers/stories_panel.test.js b/lib/ui/src/modules/ui/containers/stories_panel.test.js
index a95ff17d36a..0623be9ff58 100755
--- a/lib/ui/src/modules/ui/containers/stories_panel.test.js
+++ b/lib/ui/src/modules/ui/containers/stories_panel.test.js
@@ -12,7 +12,6 @@ describe('manager.ui.containers.stories_panel', () => {
url: 'bar',
};
const selectStory = () => 'selectStory';
- const toggleShortcutsHelp = () => 'toggleShortcutsHelp';
const setStoryFilter = () => 'setStoryFilter';
const props = {};
const env = {
@@ -21,7 +20,6 @@ describe('manager.ui.containers.stories_panel', () => {
selectStory,
},
ui: {
- toggleShortcutsHelp,
setStoryFilter,
},
}),
@@ -57,7 +55,6 @@ describe('manager.ui.containers.stories_panel', () => {
expect(result.storyFilter).toBe(null);
expect(result.onSelectStory).toBe(selectStory);
expect(result.onStoryFilter).toBe(setStoryFilter);
- expect(result.openShortcutsHelp).toBe(toggleShortcutsHelp);
});
test('should filter stories according to the given filter', () => {
diff --git a/lib/ui/src/modules/ui/libs/is_mobile_device.js b/lib/ui/src/modules/ui/libs/is_mobile_device.js
new file mode 100644
index 00000000000..ede024a60b8
--- /dev/null
+++ b/lib/ui/src/modules/ui/libs/is_mobile_device.js
@@ -0,0 +1,7 @@
+export default userAgent => {
+ if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent)) {
+ return true;
+ }
+
+ return false;
+};
diff --git a/lib/ui/src/modules/ui/libs/is_mobile_device.test.js b/lib/ui/src/modules/ui/libs/is_mobile_device.test.js
new file mode 100644
index 00000000000..379759f80db
--- /dev/null
+++ b/lib/ui/src/modules/ui/libs/is_mobile_device.test.js
@@ -0,0 +1,28 @@
+import isMobileDevice from './is_mobile_device';
+
+describe('manager.ui.libs.is_mobile_device', () => {
+ it('should detect if storybook is open on mobile device', () => {
+ // chrome
+ expect(
+ isMobileDevice(
+ 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19'
+ )
+ ).toEqual(true);
+
+ expect(
+ isMobileDevice('Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0')
+ ).toEqual(true);
+
+ expect(
+ isMobileDevice(
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
+ )
+ ).toEqual(false);
+
+ expect(
+ isMobileDevice(
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/604.5.6 (KHTML, like Gecko) Version/11.0.3 Safari/604.5.6'
+ )
+ ).toEqual(false);
+ });
+});
diff --git a/lib/ui/src/modules/ui/routes.js b/lib/ui/src/modules/ui/routes.js
index 79929c70408..dccbae7cdb4 100755
--- a/lib/ui/src/modules/ui/routes.js
+++ b/lib/ui/src/modules/ui/routes.js
@@ -6,11 +6,12 @@ import StoriesPanel from './containers/stories_panel';
import AddonPanel from './containers/addon_panel';
import ShortcutsHelp from './containers/shortcuts_help';
import SearchBox from './containers/search_box';
+import Header from './containers/header';
export default function(injectDeps, { clientStore, provider, domNode }) {
+ const state = clientStore.getAll();
// generate preview
const Preview = () => {
- const state = clientStore.getAll();
const preview = provider.renderPreview(state.selectedKind, state.selectedStory);
return preview;
};
@@ -20,6 +21,7 @@ export default function(injectDeps, { clientStore, provider, domNode }) {
const root = (
+ {state.isMobileDevice &&
}
}
preview={() => }