diff --git a/addons/options/README.md b/addons/options/README.md
index 95f6cddbab3e..b000c47fb8a7 100644
--- a/addons/options/README.md
+++ b/addons/options/README.md
@@ -93,6 +93,12 @@ setOptions({
* @type {Boolean}
*/
sidebarAnimations: true,
+
+ /**
+ * id to select an addon panel
+ * @type {String}
+ */
+ selectedAddonPanel: undefined, // The order of addons in the "Addons Panel" is the same as you import them in 'addons.js'. The first panel will be opened by default as you run Storybook
});
storybook.configure(() => require('./stories'), module);
diff --git a/examples/cra-kitchen-sink/src/__snapshots__/storyshots.test.js.snap b/examples/cra-kitchen-sink/src/__snapshots__/storyshots.test.js.snap
index 00f1979bd080..92391a362386 100644
--- a/examples/cra-kitchen-sink/src/__snapshots__/storyshots.test.js.snap
+++ b/examples/cra-kitchen-sink/src/__snapshots__/storyshots.test.js.snap
@@ -260,6 +260,22 @@ exports[`Storyshots Button addons composition 1`] = `
>
+
storiesOf('Button', module)
.addDecorator(withKnobs)
- .add('with text', () =>
Hello Button )
- .add('with some emoji', () =>
😀 😎 👍 💯 )
+ .add('with text', () =>
+
+ {setOptions({ selectedAddonPanel: 'storybook/actions/actions-panel' })}
+ Hello Button
+
+ )
+ .add('with some emoji', () =>
+
+ {setOptions({ selectedAddonPanel: 'storybook/actions/actions-panel' })}
+ 😀 😎 👍 💯
+
+ )
.add('with notes', () =>
- Check my notes in the notes panel
+
+ {setOptions({ selectedAddonPanel: 'storybook/notes/panel' })}
+ Check my notes in the notes panel
+
)
.add('with knobs', () => {
+ setOptions({ selectedAddonPanel: 'storybooks/storybook-addon-knobs' });
const name = text('Name', 'Storyteller');
const age = number('Age', 70, { range: true, min: 0, max: 90, step: 5 });
const fruits = {
@@ -130,6 +145,7 @@ storiesOf('Button', module)
'Use the [info addon](https://github.com/storybooks/storybook/tree/master/addons/info) with its new painless API.'
)(context =>
+ {setOptions({ selectedAddonPanel: 'storybook/info/info-panel' })}
click the label in top right for info about "{context.story}"
)
@@ -139,6 +155,7 @@ storiesOf('Button', module)
withInfo('see Notes panel for composition info')(
withNotes('Composition: Info(Notes())')(context =>
+ {setOptions({ selectedAddonPanel: 'storybook/notes/panel' })}
click the label in top right for info about "{context.story}"
)
diff --git a/lib/ui/README.md b/lib/ui/README.md
index d90c0153220e..b575f41d2698 100644
--- a/lib/ui/README.md
+++ b/lib/ui/README.md
@@ -87,9 +87,8 @@ import { Provider } from '@storybook/ui';
class ReactProvider extends Provider {
handleAPI(api) {
api.setOptions({
- name: 'My Component', // change the name displayed in the left top portion
- url: 'https://github.com/user/my-component', // change its URL
- sortStoriesByKind: true // Sort the list of stories by their "kind"
+ // see available options in
+ // https://github.com/storybooks/storybook/tree/master/addons/options#getting-started
});
}
};
diff --git a/lib/ui/src/modules/api/actions/api.js b/lib/ui/src/modules/api/actions/api.js
index 5c15705aa323..f9c565e3e12f 100755
--- a/lib/ui/src/modules/api/actions/api.js
+++ b/lib/ui/src/modules/api/actions/api.js
@@ -47,6 +47,17 @@ export function ensureStory(storyKinds, selectedKind, selectedStory) {
return kindInfo.stories[0];
}
+export function ensurePanel(panels, selectedPanel, currentPanel) {
+ if (Object.keys(panels).indexOf(selectedPanel) >= 0) return selectedPanel;
+ // if the selected panel is non-existant, select the current panel
+ // and output to console all available panels
+ const logger = console;
+ logger.group('Available Panels ID:');
+ Object.keys(panels).forEach(panelID => logger.log(`${panelID} (${panels[panelID].title})`));
+ logger.groupEnd('Available Panels ID:');
+ return currentPanel;
+}
+
export default {
setStories({ clientStore }, stories) {
clientStore.update(state => {
@@ -77,15 +88,23 @@ export default {
);
},
- setOptions({ clientStore }, options) {
+ setOptions(env, options) {
+ const { clientStore, provider } = env;
clientStore.update(state => {
const newOptions = pick(options, Object.keys(state.uiOptions));
- const updatedOptions = {
+ const updatedUiOptions = {
...state.uiOptions,
...newOptions,
};
-
- return { uiOptions: updatedOptions };
+ const otherOptions = {};
+ if (Object.keys(pick(options, ['selectedAddonPanel'])).length) {
+ otherOptions.selectedAddonPanel = ensurePanel(
+ provider.getPanels(),
+ options.selectedAddonPanel,
+ state.selectedAddonPanel
+ );
+ }
+ return { uiOptions: updatedUiOptions, ...otherOptions };
});
},
diff --git a/lib/ui/src/modules/api/actions/api.test.js b/lib/ui/src/modules/api/actions/api.test.js
index 3536069941d3..568bf358ed37 100755
--- a/lib/ui/src/modules/api/actions/api.test.js
+++ b/lib/ui/src/modules/api/actions/api.test.js
@@ -189,6 +189,57 @@ describe('manager.api.actions.api', () => {
});
});
+ const provider = {
+ getPanels: () => ({
+ 'storybook/actions/actions-panel': {
+ title: 'Action logger',
+ },
+ 'storybooks/storybook-addon-knobs': {
+ title: 'Knobs',
+ },
+ }),
+ };
+
+ it('should update selectedAddonPanel', () => {
+ const clientStore = new MockClientStore();
+ actions.setOptions(
+ { clientStore, provider },
+ { selectedAddonPanel: 'storybooks/storybook-addon-knobs' }
+ );
+
+ const state = {
+ uiOptions: {},
+ selectedAddonPanel: 'storybook/actions/actions-panel',
+ };
+
+ const stateUpdates = clientStore.updateCallback(state);
+ expect(stateUpdates.selectedAddonPanel).toEqual('storybooks/storybook-addon-knobs');
+ });
+
+ it('should keep current downPanel and output panel IDs', () => {
+ const clientStore = new MockClientStore();
+ actions.setOptions({ clientStore, provider }, { selectedAddonPanel: null });
+
+ global.console = {
+ log: jest.fn(),
+ group: jest.fn(),
+ groupEnd: jest.fn(),
+ };
+ const logger = console;
+
+ const state = {
+ uiOptions: {},
+ selectedAddonPanel: 'storybook/actions/actions-panel',
+ };
+
+ const stateUpdates = clientStore.updateCallback(state);
+ expect(stateUpdates.selectedAddonPanel).toEqual('storybook/actions/actions-panel');
+ expect(logger.log.mock.calls).toEqual([
+ ['storybook/actions/actions-panel (Action logger)'],
+ ['storybooks/storybook-addon-knobs (Knobs)'],
+ ]);
+ });
+
it('should only update options for the key already defined', () => {
const clientStore = new MockClientStore();
actions.setOptions({ clientStore }, { abc: 10, notGoingToState: 20 });
diff --git a/lib/ui/src/modules/ui/actions/ui.js b/lib/ui/src/modules/ui/actions/ui.js
index 97e572bc5421..a5a823643ce5 100755
--- a/lib/ui/src/modules/ui/actions/ui.js
+++ b/lib/ui/src/modules/ui/actions/ui.js
@@ -8,6 +8,6 @@ export default {
},
selectDownPanel({ clientStore }, panelName) {
- clientStore.set('selectedDownPanel', panelName);
+ clientStore.set('selectedAddonPanel', panelName);
},
};
diff --git a/lib/ui/src/modules/ui/actions/ui.test.js b/lib/ui/src/modules/ui/actions/ui.test.js
index 5589679d223c..de4df76f35ee 100755
--- a/lib/ui/src/modules/ui/actions/ui.test.js
+++ b/lib/ui/src/modules/ui/actions/ui.test.js
@@ -32,7 +32,7 @@ describe('manager.ui.actions.ui', () => {
const panelName = 'kkkind';
actions.selectDownPanel({ clientStore }, panelName);
- expect(clientStore.set).toHaveBeenCalledWith('selectedDownPanel', panelName);
+ expect(clientStore.set).toHaveBeenCalledWith('selectedAddonPanel', panelName);
});
});
});
diff --git a/lib/ui/src/modules/ui/configs/handle_routing.js b/lib/ui/src/modules/ui/configs/handle_routing.js
index 058d69a6a21a..1ca89a8a021e 100755
--- a/lib/ui/src/modules/ui/configs/handle_routing.js
+++ b/lib/ui/src/modules/ui/configs/handle_routing.js
@@ -15,7 +15,7 @@ export function getUrlState(data) {
downPanelInRight: panelRight,
} = data.shortcutOptions;
- const { selectedDownPanel: downPanel } = data;
+ const { selectedAddonPanel: downPanel } = data;
const urlObj = {
...customQueryParams,
diff --git a/lib/ui/src/modules/ui/configs/handle_routing.test.js b/lib/ui/src/modules/ui/configs/handle_routing.test.js
index f8493a632b7a..aea5bbdd270b 100755
--- a/lib/ui/src/modules/ui/configs/handle_routing.test.js
+++ b/lib/ui/src/modules/ui/configs/handle_routing.test.js
@@ -23,7 +23,7 @@ describe('manager.ui.config.handle_routing', () => {
showLeftPanel: true,
downPanelInRight: true,
},
- selectedDownPanel: 'pp',
+ selectedAddonPanel: 'pp',
};
const clientStore = {
getAll: () => state,
diff --git a/lib/ui/src/modules/ui/containers/down_panel.js b/lib/ui/src/modules/ui/containers/down_panel.js
index 011d6c2d5308..d356dc69c149 100644
--- a/lib/ui/src/modules/ui/containers/down_panel.js
+++ b/lib/ui/src/modules/ui/containers/down_panel.js
@@ -5,7 +5,7 @@ import compose from '../../../compose';
export function mapper(state, props, { context, actions }) {
const panels = context().provider.getPanels();
const actionMap = actions();
- const selectedPanel = state.selectedDownPanel;
+ const selectedPanel = state.selectedAddonPanel;
return {
panels,
diff --git a/lib/ui/src/modules/ui/containers/down_panel.test.js b/lib/ui/src/modules/ui/containers/down_panel.test.js
index 1cc31672e3b5..fb534adca717 100644
--- a/lib/ui/src/modules/ui/containers/down_panel.test.js
+++ b/lib/ui/src/modules/ui/containers/down_panel.test.js
@@ -4,7 +4,7 @@ describe('manager.ui.containers.down_panel', () => {
describe('mapper', () => {
test('should give correct data', () => {
const state = {
- selectedDownPanel: 'sdp',
+ selectedAddonPanel: 'sdp',
};
const selectDownPanel = () => 'selectDownPanel';