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', () => ) - .add('with some emoji', () => ) + .add('with text', () => + + ) + .add('with some emoji', () => + + ) .add('with notes', () => - + ) .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';