From a8e6d1bcd90c0869a803110a79b13226086e59c8 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Fri, 31 May 2019 09:45:42 +0200 Subject: [PATCH 1/9] feat: disable option for addon tab --- addons/a11y/src/register.tsx | 3 ++- addons/actions/src/constants.ts | 1 + addons/actions/src/manager.tsx | 3 ++- addons/events/src/constants.js | 2 ++ addons/events/src/manager.js | 3 ++- addons/jest/src/register.tsx | 3 ++- addons/jest/src/shared.ts | 1 + addons/knobs/src/register.js | 3 ++- addons/knobs/src/shared.js | 1 + addons/ondevice-actions/src/index.tsx | 3 ++- addons/ondevice-backgrounds/src/constants.js | 1 + addons/ondevice-backgrounds/src/register.js | 3 ++- addons/ondevice-knobs/src/index.js | 1 + addons/ondevice-notes/src/register.js | 1 + lib/addons/src/index.ts | 1 + lib/ui/src/containers/panel.js | 19 ++++++++++++++++++- 16 files changed, 41 insertions(+), 8 deletions(-) diff --git a/addons/a11y/src/register.tsx b/addons/a11y/src/register.tsx index a0995ab4fcee..9b360ec97d4c 100644 --- a/addons/a11y/src/register.tsx +++ b/addons/a11y/src/register.tsx @@ -2,7 +2,7 @@ import React, { Fragment, FunctionComponent } from 'react'; import { styled } from '@storybook/theming'; import { addons, types } from '@storybook/addons'; -import { ADDON_ID, PANEL_ID } from './constants'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './constants'; import { ColorBlindness } from './components/ColorBlindness'; import { A11YPanel } from './components/A11YPanel'; @@ -94,6 +94,7 @@ addons.register(ADDON_ID, api => { title: 'Accessibility', type: types.PANEL, render: ({ active, key }) => , + paramKey: PARAM_KEY, }); addons.add(PANEL_ID, { diff --git a/addons/actions/src/constants.ts b/addons/actions/src/constants.ts index 1bc018e8d9ba..9bc6f11ef5c4 100644 --- a/addons/actions/src/constants.ts +++ b/addons/actions/src/constants.ts @@ -1,3 +1,4 @@ +export const PARAM_KEY = 'actions'; export const ADDON_ID = 'storybook/actions'; export const PANEL_ID = `${ADDON_ID}/panel`; export const EVENT_ID = `${ADDON_ID}/action-event`; diff --git a/addons/actions/src/manager.tsx b/addons/actions/src/manager.tsx index be1e6f8e1261..d77272be077b 100644 --- a/addons/actions/src/manager.tsx +++ b/addons/actions/src/manager.tsx @@ -1,13 +1,14 @@ import React from 'react'; import addons from '@storybook/addons'; import ActionLogger from './containers/ActionLogger'; -import { ADDON_ID, PANEL_ID } from '.'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './constants'; export function register() { addons.register(ADDON_ID, api => { addons.addPanel(PANEL_ID, { title: 'Actions', render: ({ active, key }) => , + paramKey: PARAM_KEY, }); }); } diff --git a/addons/events/src/constants.js b/addons/events/src/constants.js index cf57a2570904..3d765994293b 100644 --- a/addons/events/src/constants.js +++ b/addons/events/src/constants.js @@ -1,3 +1,5 @@ +export const PARAM_KEY = 'events'; + export const ADDON_ID = 'storybook/events'; export const PANEL_ID = `${ADDON_ID}/panel`; diff --git a/addons/events/src/manager.js b/addons/events/src/manager.js index 6d8bea634686..d7cab5bfc338 100644 --- a/addons/events/src/manager.js +++ b/addons/events/src/manager.js @@ -2,7 +2,7 @@ import React from 'react'; import addons from '@storybook/addons'; import Panel from './components/Panel'; -import { ADDON_ID, PANEL_ID } from './constants'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './constants'; export function register() { addons.register(ADDON_ID, api => { @@ -10,6 +10,7 @@ export function register() { title: 'Events', // eslint-disable-next-line react/prop-types render: ({ active, key }) => , + paramKey: PARAM_KEY, }); }); } diff --git a/addons/jest/src/register.tsx b/addons/jest/src/register.tsx index b3058d321dd6..a8d3b2c97bad 100644 --- a/addons/jest/src/register.tsx +++ b/addons/jest/src/register.tsx @@ -1,6 +1,6 @@ import React from 'react'; import addons from '@storybook/addons'; -import { ADDON_ID, PANEL_ID } from './shared'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './shared'; import Panel from './components/Panel'; @@ -8,5 +8,6 @@ addons.register(ADDON_ID, api => { addons.addPanel(PANEL_ID, { title: 'tests', render: ({ active, key }) => , + paramKey: PARAM_KEY, }); }); diff --git a/addons/jest/src/shared.ts b/addons/jest/src/shared.ts index 48e804cefe01..7028ab5ce2a8 100644 --- a/addons/jest/src/shared.ts +++ b/addons/jest/src/shared.ts @@ -1,4 +1,5 @@ // addons, panels and events get unique names using a prefix +export const PARAM_KEY = 'test'; export const ADDON_ID = 'storybooks/test'; export const PANEL_ID = `${ADDON_ID}/panel`; diff --git a/addons/knobs/src/register.js b/addons/knobs/src/register.js index e8eeddb512c1..2808815b3958 100644 --- a/addons/knobs/src/register.js +++ b/addons/knobs/src/register.js @@ -1,12 +1,13 @@ import React from 'react'; import addons from '@storybook/addons'; import Panel from './components/Panel'; -import { ADDON_ID, PANEL_ID } from './shared'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './shared'; addons.register(ADDON_ID, api => { addons.addPanel(PANEL_ID, { title: 'Knobs', // eslint-disable-next-line react/prop-types render: ({ active, key }) => , + paramKey: PARAM_KEY, }); }); diff --git a/addons/knobs/src/shared.js b/addons/knobs/src/shared.js index 6aca6fe000fa..f8e3bfc0312b 100644 --- a/addons/knobs/src/shared.js +++ b/addons/knobs/src/shared.js @@ -1,4 +1,5 @@ // addons, panels and events get unique names using a prefix +export const PARAM_KEY = 'knobs'; export const ADDON_ID = 'storybooks/knobs'; export const PANEL_ID = `${ADDON_ID}/panel`; diff --git a/addons/ondevice-actions/src/index.tsx b/addons/ondevice-actions/src/index.tsx index 76602d22ae9c..63b71d68a676 100644 --- a/addons/ondevice-actions/src/index.tsx +++ b/addons/ondevice-actions/src/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; import addons from '@storybook/addons'; -import { ADDON_ID, PANEL_ID } from '@storybook/addon-actions'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from '@storybook/addon-actions'; import ActionLogger from './containers/ActionLogger'; export function register() { @@ -8,6 +8,7 @@ export function register() { addons.addPanel(PANEL_ID, { title: 'Actions', render: ({ active, key }) => , + paramKey: PARAM_KEY, }); }); } diff --git a/addons/ondevice-backgrounds/src/constants.js b/addons/ondevice-backgrounds/src/constants.js index 7e0fcc42dae1..4c8f09259143 100644 --- a/addons/ondevice-backgrounds/src/constants.js +++ b/addons/ondevice-backgrounds/src/constants.js @@ -1,3 +1,4 @@ +export const PARAM_KEY = 'background'; export const ADDON_ID = 'storybook-addon-background'; export const PANEL_ID = `${ADDON_ID}/background-panel`; diff --git a/addons/ondevice-backgrounds/src/register.js b/addons/ondevice-backgrounds/src/register.js index 0bd614430dae..2714689abb25 100644 --- a/addons/ondevice-backgrounds/src/register.js +++ b/addons/ondevice-backgrounds/src/register.js @@ -1,7 +1,7 @@ import React from 'react'; import addons from '@storybook/addons'; -import { ADDON_ID, PANEL_ID } from './constants'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './constants'; import BackgroundPanel from './BackgroundPanel'; addons.register(ADDON_ID, api => { @@ -10,5 +10,6 @@ addons.register(ADDON_ID, api => { title: 'Backgrounds', // eslint-disable-next-line react/prop-types render: ({ active }) => , + paramKey: PARAM_KEY, }); }); diff --git a/addons/ondevice-knobs/src/index.js b/addons/ondevice-knobs/src/index.js index 8286083ad1ed..9e46af4a4071 100644 --- a/addons/ondevice-knobs/src/index.js +++ b/addons/ondevice-knobs/src/index.js @@ -9,6 +9,7 @@ export function register() { title: 'Knobs', // eslint-disable-next-line react/prop-types render: ({ active, key }) => , + paramKey: 'knobs', }); }); } diff --git a/addons/ondevice-notes/src/register.js b/addons/ondevice-notes/src/register.js index 1ed3a38bfcdf..530eaac2354e 100644 --- a/addons/ondevice-notes/src/register.js +++ b/addons/ondevice-notes/src/register.js @@ -50,5 +50,6 @@ addons.register('storybook/notes', api => { addons.addPanel('storybook/notes/panel', { title: 'Notes', render: ({ active, key }) => , + paramKey: PARAM_KEY, }); }); diff --git a/lib/addons/src/index.ts b/lib/addons/src/index.ts index 4e593d6e8c3e..14f077b686da 100644 --- a/lib/addons/src/index.ts +++ b/lib/addons/src/index.ts @@ -24,6 +24,7 @@ export interface Addon { route?: (routeOptions: RouteOptions) => string; match?: (matchOptions: MatchOptions) => boolean; render: (renderOptions: RenderOptions) => ReactElement; + paramKey?: string; } export type Loader = (api: API) => void; diff --git a/lib/ui/src/containers/panel.js b/lib/ui/src/containers/panel.js index de4d62f233f2..2c8e60bfa041 100644 --- a/lib/ui/src/containers/panel.js +++ b/lib/ui/src/containers/panel.js @@ -10,8 +10,25 @@ const createPanelActions = memoize(1)(api => ({ togglePosition: () => api.togglePanelPosition(), })); +const filterPanel = (panels, storyParameters) => { + if (!panels || !storyParameters) { + return panels; + } + + const filteredPanels = {}; + Object.entries(panels).forEach(([id, panel]) => { + const { paramKey } = panel; + const panelParameters = paramKey && storyParameters[paramKey]; + if (!panelParameters || !panelParameters.disabled) { + filteredPanels[id] = panel; + } + }); + + return filteredPanels; +}; + const mapper = ({ state, api }) => ({ - panels: api.getPanels(), + panels: filterPanel(api.getPanels(), api.getParameters(state.storyId)), selectedPanel: api.getSelectedPanel(), panelPosition: state.layout.panelPosition, actions: createPanelActions(api), From 82f241e2c007496eb8b0f0f049ba48eaee7e0f7e Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Tue, 11 Jun 2019 23:21:34 +0200 Subject: [PATCH 2/9] Add tests, docs, example --- addons/cssresources/src/register.tsx | 3 +- addons/notes/src/register.tsx | 3 +- docs/src/pages/addons/using-addons/index.md | 23 +++ docs/src/pages/addons/writing-addons/index.md | 29 ++++ lib/addons/src/index.ts | 1 - lib/api/src/modules/addons.ts | 23 +++ lib/api/src/tests/addons.test.js | 147 ++++++++++++++++++ lib/ui/src/containers/panel.js | 19 +-- lib/ui/src/containers/panel.stories.js | 22 +++ 9 files changed, 249 insertions(+), 21 deletions(-) create mode 100644 lib/api/src/tests/addons.test.js create mode 100644 lib/ui/src/containers/panel.stories.js diff --git a/addons/cssresources/src/register.tsx b/addons/cssresources/src/register.tsx index 4c893c5ccc92..4366ea61801a 100644 --- a/addons/cssresources/src/register.tsx +++ b/addons/cssresources/src/register.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { addons, types } from '@storybook/addons'; -import { ADDON_ID, PANEL_ID } from './constants'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './constants'; import { CssResourcePanel } from './css-resource-panel'; addons.register(ADDON_ID, api => { @@ -10,5 +10,6 @@ addons.register(ADDON_ID, api => { type: types.PANEL, title: 'CSS resources', render: ({ active }) => , + paramKey: PARAM_KEY, }); }); diff --git a/addons/notes/src/register.tsx b/addons/notes/src/register.tsx index 17d3c8d4189f..0e56ab83ae1a 100644 --- a/addons/notes/src/register.tsx +++ b/addons/notes/src/register.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import addons, { types } from '@storybook/addons'; -import { ADDON_ID, PANEL_ID } from './shared'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './shared'; // TODO: fix eslint in tslint (igor said he fixed it, should ask him) import Panel from './Panel'; @@ -14,6 +14,7 @@ export default function register(type: types) { route: ({ storyId }) => `/info/${storyId}`, // todo add type match: ({ viewMode }) => viewMode === 'info', // todo add type render: ({ active }) => , + paramKey: PARAM_KEY, }); }); } diff --git a/docs/src/pages/addons/using-addons/index.md b/docs/src/pages/addons/using-addons/index.md index 4fbe3455df2e..501f9f76735c 100644 --- a/docs/src/pages/addons/using-addons/index.md +++ b/docs/src/pages/addons/using-addons/index.md @@ -65,6 +65,29 @@ Then you'll be able to see those notes when you are viewing the story. ![Stories with notes](../static/stories-with-notes.png) +## Disable the addon + +You can disable an addon panel for a story by adding a `disabled` parameter. + +```js +import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; + +import Button from './Button'; + +storiesOf('Button', module).add( + 'with some emoji', + () => ( + + ), + { notes: { disabled: true } } +); +``` + ## Global Configuration Sometimes you might want to configure an addon globally, as in the case of collocating stories with components, or just simply to keep your stories file cleaner. To do that, you can add your decorators to a config file, typically in `.storybook/config.js`. Here's an example of how you might do that. diff --git a/docs/src/pages/addons/writing-addons/index.md b/docs/src/pages/addons/writing-addons/index.md index eaa34bd36626..e634cd224023 100644 --- a/docs/src/pages/addons/writing-addons/index.md +++ b/docs/src/pages/addons/writing-addons/index.md @@ -110,6 +110,7 @@ addons.register(ADDON_ID, api => { type: types.PANEL, title, render, + paramKey: PARAM_KEY, }); }); ``` @@ -259,6 +260,34 @@ storiesOf('Button', module) }); ``` +### Disabling an addon panel + +It's possible to disable an addon panel for a particular story. + +To offer that capability, you need to pass the paramKey when you register the panel +```js +addons.register(ADDON_ID, () => { + addons.add(PANEL_ID, { + type: types.PANEL, + title: 'My Addon', + render: () =>
Addon tab content
, + paramKey: 'myAddon', + }); +}); +``` + +While adding a story, you can then pass a `disabled` parameter. + +```js +storiesOf('Button', module) + .add('with text', () => , { + myAddon: { + disabled: true, + }, + }); +``` + + ## Styling your addon We use [emotion](https://emotion.sh) for styling, AND we provide a theme which can be set by the user! diff --git a/lib/addons/src/index.ts b/lib/addons/src/index.ts index 14f077b686da..4e593d6e8c3e 100644 --- a/lib/addons/src/index.ts +++ b/lib/addons/src/index.ts @@ -24,7 +24,6 @@ export interface Addon { route?: (routeOptions: RouteOptions) => string; match?: (matchOptions: MatchOptions) => boolean; render: (renderOptions: RenderOptions) => ReactElement; - paramKey?: string; } export type Loader = (api: API) => void; diff --git a/lib/api/src/modules/addons.ts b/lib/api/src/modules/addons.ts index d3ef5704a002..67e06a9ce14a 100644 --- a/lib/api/src/modules/addons.ts +++ b/lib/api/src/modules/addons.ts @@ -29,6 +29,7 @@ export interface Addon { route?: (routeOptions: RouteOptions) => string; match?: (matchOptions: MatchOptions) => boolean; render: (renderOptions: RenderOptions) => ReactElement; + paramKey: string; } export interface Collection { [key: string]: Addon; @@ -41,10 +42,15 @@ interface Panels { export interface SubAPI { getElements: (type: Types) => Collection; getPanels: () => Collection; + getPanelsForStory: (storyParameters: StoryParameters) => Collection; getSelectedPanel: () => string; setSelectedPanel: (panelName: string) => void; } +interface StoryParameters { + [key: string]: any; +} + export function ensurePanel(panels: Panels, selectedPanel?: string, currentPanel?: string) { const keys = Object.keys(panels); @@ -62,6 +68,23 @@ export default ({ provider, store }: Module) => { const api: SubAPI = { getElements: type => provider.getElements(type), getPanels: () => api.getElements(types.PANEL), + getPanelsForStory: (storyParameters: StoryParameters) => { + const panels = api.getPanels(); + if (!panels || !storyParameters) { + return panels; + } + + const filteredPanels: Collection = {}; + Object.entries(panels).forEach(([id, panel]) => { + const { paramKey } = panel; + if (paramKey && storyParameters[paramKey] && storyParameters[paramKey].disabled) { + return; + } + filteredPanels[id] = panel; + }); + + return filteredPanels; + }, getSelectedPanel: () => { const { selectedPanel } = store.getState(); return ensurePanel(api.getPanels(), selectedPanel, selectedPanel); diff --git a/lib/api/src/tests/addons.test.js b/lib/api/src/tests/addons.test.js new file mode 100644 index 000000000000..0053f44471f4 --- /dev/null +++ b/lib/api/src/tests/addons.test.js @@ -0,0 +1,147 @@ +import initAddons, { types } from '../modules/addons'; + +const PANELS = { + a11y: { + title: 'Accessibility', + paramKey: 'a11y', + }, + actions: { + title: 'Actions', + paramKey: 'actions', + }, + knobs: { + title: 'Knobs', + paramKey: 'knobs', + }, +}; + +const provider = { + getElements(type) { + if (type === types.PANEL) { + return PANELS; + } + return null; + }, +}; + +const store = { + getState: () => ({ + selectedPanel: '', + }), + setState: jest.fn(), +}; + +describe('Addons API', () => { + describe('#getElements', () => { + it('should return provider elements', () => { + // given + const { api } = initAddons({ provider, store }); + + // when + const panels = api.getElements(types.PANEL); + + // then + expect(panels).toBe(PANELS); + }); + }); + + describe('#getPanels', () => { + it('should return provider panels', () => { + // given + const { api } = initAddons({ provider, store }); + + // when + const panels = api.getPanels(); + + // then + expect(panels).toBe(PANELS); + }); + }); + + describe('#getPanelsForStory', () => { + it('should return all panels by default', () => { + // given + const { api } = initAddons({ provider, store }); + + // when + const filteredPanels = api.getPanelsForStory(); + + // then + expect(filteredPanels).toBe(PANELS); + }); + + it('should filter disabled addons', () => { + // given + const { api } = initAddons({ provider, store }); + const storyParameters = { + a11y: { disabled: true }, + }; + + // when + const filteredPanels = api.getPanelsForStory(storyParameters); + + // then + expect(filteredPanels).toEqual({ + actions: PANELS.actions, + knobs: PANELS.knobs, + }); + }); + }); + + describe('#getSelectedPanel', () => { + it('should return provider panels', () => { + // given + const storeWithSelectedPanel = { + getState: () => ({ + selectedPanel: 'actions', + }), + setState: jest.fn(), + }; + const { api } = initAddons({ provider, store: storeWithSelectedPanel }); + + // when + const selectedPanel = api.getSelectedPanel(); + + // then + expect(selectedPanel).toBe('actions'); + }); + + it('should return first panel when selected is not a panel', () => { + // given + const storeWithSelectedPanel = { + getState: () => ({ + selectedPanel: 'unknown', + }), + setState: jest.fn(), + }; + const { api } = initAddons({ provider, store: storeWithSelectedPanel }); + + // when + const selectedPanel = api.getSelectedPanel(); + + // then + expect(selectedPanel).toBe('a11y'); + }); + }); + + describe('#setSelectedPanel', () => { + it('should set value inn store', () => { + // given + const setState = jest.fn(); + const storeWithSelectedPanel = { + getState: () => ({ + selectedPanel: 'actions', + }), + setState, + }; + const { api } = initAddons({ provider, store: storeWithSelectedPanel }); + expect(setState).not.toHaveBeenCalled(); + + // when + api.setSelectedPanel('knobs'); + + // then + expect(setState).toHaveBeenCalledWith({ selectedPanel: 'knobs' }, { persistence: 'session' }); + }); + }); +}); diff --git a/lib/ui/src/containers/panel.js b/lib/ui/src/containers/panel.js index 2c8e60bfa041..6e6a5ceaafb7 100644 --- a/lib/ui/src/containers/panel.js +++ b/lib/ui/src/containers/panel.js @@ -10,25 +10,8 @@ const createPanelActions = memoize(1)(api => ({ togglePosition: () => api.togglePanelPosition(), })); -const filterPanel = (panels, storyParameters) => { - if (!panels || !storyParameters) { - return panels; - } - - const filteredPanels = {}; - Object.entries(panels).forEach(([id, panel]) => { - const { paramKey } = panel; - const panelParameters = paramKey && storyParameters[paramKey]; - if (!panelParameters || !panelParameters.disabled) { - filteredPanels[id] = panel; - } - }); - - return filteredPanels; -}; - const mapper = ({ state, api }) => ({ - panels: filterPanel(api.getPanels(), api.getParameters(state.storyId)), + panels: api.getPanelsForStory(api.getParameters(state.storyId)), selectedPanel: api.getSelectedPanel(), panelPosition: state.layout.panelPosition, actions: createPanelActions(api), diff --git a/lib/ui/src/containers/panel.stories.js b/lib/ui/src/containers/panel.stories.js new file mode 100644 index 000000000000..f920d6639ffb --- /dev/null +++ b/lib/ui/src/containers/panel.stories.js @@ -0,0 +1,22 @@ +import React from 'react'; +import { storiesOf } from '@storybook/react'; + +storiesOf('UI|Addon Panel', module) + .add('default', () =>
By default all addon panels are rendered
) + .add( + 'disable panel', + () => ( +
+ This story disables Actions and Accessibility panels +
+          {`storiesOf('UI|Addon Panel', module)
+  .add(
+    'my story',
+    ,
+    { a11y: { disable: true }, actions: { disable: true } }
+  );`}
+        
+
+ ), + { a11y: { disabled: true }, actions: { disabled: true } } + ); From da1a64c1c2a98c9413b62c8dc833d8775e87ae58 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Wed, 12 Jun 2019 21:37:18 +0200 Subject: [PATCH 3/9] Make getStoryPanels a full api method --- lib/api/src/modules/addons.ts | 5 +++-- lib/api/src/tests/addons.test.js | 27 ++++++++++++++++++++------- lib/ui/src/containers/panel.js | 2 +- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/api/src/modules/addons.ts b/lib/api/src/modules/addons.ts index 67e06a9ce14a..f8732bb1581f 100644 --- a/lib/api/src/modules/addons.ts +++ b/lib/api/src/modules/addons.ts @@ -42,7 +42,7 @@ interface Panels { export interface SubAPI { getElements: (type: Types) => Collection; getPanels: () => Collection; - getPanelsForStory: (storyParameters: StoryParameters) => Collection; + getStoryPanels: (storyId: string) => Collection; getSelectedPanel: () => string; setSelectedPanel: (panelName: string) => void; } @@ -68,7 +68,8 @@ export default ({ provider, store }: Module) => { const api: SubAPI = { getElements: type => provider.getElements(type), getPanels: () => api.getElements(types.PANEL), - getPanelsForStory: (storyParameters: StoryParameters) => { + getStoryPanels: storyId => { + const storyParameters = provider.getParameters(storyId); const panels = api.getPanels(); if (!panels || !storyParameters) { return panels; diff --git a/lib/api/src/tests/addons.test.js b/lib/api/src/tests/addons.test.js index 0053f44471f4..95a016a71508 100644 --- a/lib/api/src/tests/addons.test.js +++ b/lib/api/src/tests/addons.test.js @@ -58,13 +58,17 @@ describe('Addons API', () => { }); }); - describe('#getPanelsForStory', () => { + describe('#getStoryPanels', () => { it('should return all panels by default', () => { // given - const { api } = initAddons({ provider, store }); + const providerWithStoryParameters = { + ...provider, + getParameters: () => {}, + }; + const { api } = initAddons({ provider: providerWithStoryParameters, store }); // when - const filteredPanels = api.getPanelsForStory(); + const filteredPanels = api.getStoryPanels(); // then expect(filteredPanels).toBe(PANELS); @@ -72,13 +76,22 @@ describe('Addons API', () => { it('should filter disabled addons', () => { // given - const { api } = initAddons({ provider, store }); - const storyParameters = { - a11y: { disabled: true }, + const storyId = 'story 1'; + const providerWithStoryParameters = { + ...provider, + getParameters: id => { + if (id === storyId) { + return { + a11y: { disabled: true }, + }; + } + return null; + }, }; + const { api } = initAddons({ provider: providerWithStoryParameters, store }); // when - const filteredPanels = api.getPanelsForStory(storyParameters); + const filteredPanels = api.getStoryPanels(storyId); // then expect(filteredPanels).toEqual({ diff --git a/lib/ui/src/containers/panel.js b/lib/ui/src/containers/panel.js index 6e6a5ceaafb7..fcf2e7eca281 100644 --- a/lib/ui/src/containers/panel.js +++ b/lib/ui/src/containers/panel.js @@ -11,7 +11,7 @@ const createPanelActions = memoize(1)(api => ({ })); const mapper = ({ state, api }) => ({ - panels: api.getPanelsForStory(api.getParameters(state.storyId)), + panels: api.getStoryPanels(state.storyId), selectedPanel: api.getSelectedPanel(), panelPosition: state.layout.panelPosition, actions: createPanelActions(api), From 78722470216bf193ddb672f40afc150599297e1c Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Wed, 12 Jun 2019 23:05:17 +0200 Subject: [PATCH 4/9] Fix type --- lib/addons/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/addons/src/index.ts b/lib/addons/src/index.ts index 046b59d403cc..c0ccd03ed4de 100644 --- a/lib/addons/src/index.ts +++ b/lib/addons/src/index.ts @@ -24,6 +24,7 @@ export interface Addon { route?: (routeOptions: RouteOptions) => string; match?: (matchOptions: MatchOptions) => boolean; render: (renderOptions: RenderOptions) => ReactElement; + paramKey: string; } export type Loader = (api: API) => void; From ae3484bb97d0b2081da20e108d2a5c6d9a19f4a4 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Fri, 14 Jun 2019 21:43:16 +0200 Subject: [PATCH 5/9] Add param key in graphql addon --- addons/graphql/src/register.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/graphql/src/register.ts b/addons/graphql/src/register.ts index d69b5af63619..68d41a5dd20e 100644 --- a/addons/graphql/src/register.ts +++ b/addons/graphql/src/register.ts @@ -1,7 +1,7 @@ import { addons, types } from '@storybook/addons'; import GQL from './manager'; -import { ADDON_ID } from '.'; +import { ADDON_ID, PARAM_KEY } from '.'; export const register = () => { addons.register(ADDON_ID, () => { @@ -11,6 +11,7 @@ export const register = () => { route: ({ storyId }) => `/graphql/${storyId}`, match: ({ viewMode }) => viewMode === 'graphql', render: GQL, + paramKey: PARAM_KEY, }); }); }; From f04b6e8191287a919774973b8d141e499976e230 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Fri, 14 Jun 2019 22:40:07 +0200 Subject: [PATCH 6/9] Fix type --- addons/design-assets/src/register.tsx | 3 ++- lib/addons/src/index.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/design-assets/src/register.tsx b/addons/design-assets/src/register.tsx index 61fda7a988db..fb903ec514e5 100644 --- a/addons/design-assets/src/register.tsx +++ b/addons/design-assets/src/register.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { addons, types } from '@storybook/addons'; import { AddonPanel } from '@storybook/components'; -import { ADDON_ID, PANEL_ID } from './constants'; +import { ADDON_ID, PANEL_ID, PARAM_KEY } from './constants'; import { Panel } from './panel'; addons.register(ADDON_ID, () => { @@ -14,5 +14,6 @@ addons.register(ADDON_ID, () => { ), + paramKey: PARAM_KEY, }); }); diff --git a/lib/addons/src/index.ts b/lib/addons/src/index.ts index c0ccd03ed4de..5e4843cbaf17 100644 --- a/lib/addons/src/index.ts +++ b/lib/addons/src/index.ts @@ -24,7 +24,7 @@ export interface Addon { route?: (routeOptions: RouteOptions) => string; match?: (matchOptions: MatchOptions) => boolean; render: (renderOptions: RenderOptions) => ReactElement; - paramKey: string; + paramKey?: string; } export type Loader = (api: API) => void; From 4ef875198695de3a7e07e5c21665a18c3537e875 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Fri, 14 Jun 2019 23:25:39 +0200 Subject: [PATCH 7/9] Cleann --- lib/api/src/modules/addons.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/api/src/modules/addons.ts b/lib/api/src/modules/addons.ts index d84525a18996..35db70f04758 100644 --- a/lib/api/src/modules/addons.ts +++ b/lib/api/src/modules/addons.ts @@ -1,6 +1,6 @@ import { ReactElement } from 'react'; -import { Module, State } from '../index'; +import { Module } from '../index'; import { Options } from '../store'; export enum types { @@ -31,7 +31,7 @@ export interface Addon { route?: (routeOptions: RouteOptions) => string; match?: (matchOptions: MatchOptions) => boolean; render: (renderOptions: RenderOptions) => ReactElement; - paramKey: string; + paramKey?: string; } export interface Collection { [key: string]: Addon; @@ -57,10 +57,6 @@ export interface SubAPI { getAddonState(addonId: string): S; } -interface StoryParameters { - [key: string]: any; -} - export function ensurePanel(panels: Panels, selectedPanel?: string, currentPanel?: string) { const keys = Object.keys(panels); From 521b2b0f228d5942db01b139158d519add6289c2 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Sat, 15 Jun 2019 00:00:50 +0200 Subject: [PATCH 8/9] Add snapshots of panel story --- .../__snapshots__/panel.stories.storyshot | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 lib/ui/src/containers/__snapshots__/panel.stories.storyshot diff --git a/lib/ui/src/containers/__snapshots__/panel.stories.storyshot b/lib/ui/src/containers/__snapshots__/panel.stories.storyshot new file mode 100644 index 000000000000..9ec192c6ca77 --- /dev/null +++ b/lib/ui/src/containers/__snapshots__/panel.stories.storyshot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Storyshots UI|Addon Panel default 1`] = ` +
+ By default all addon panels are rendered +
+`; + +exports[`Storyshots UI|Addon Panel disable panel 1`] = ` +
+ This story disables Actions and Accessibility panels +
+    storiesOf('UI|Addon Panel', module)
+  .add(
+    'my story',
+    <MyComponent />,
+    { a11y: { disable: true }, actions: { disable: true } }
+  );
+  
+
+`; From ff0453400bf86f58278475a05c99dd75e8990182 Mon Sep 17 00:00:00 2001 From: Jimmy Somsanith Date: Mon, 17 Jun 2019 23:51:22 +0200 Subject: [PATCH 9/9] Fix addon api --- lib/api/src/modules/addons.ts | 26 +++++++++++++++++-------- lib/api/src/tests/addons.test.js | 33 ++++++++++++++++---------------- lib/ui/src/containers/panel.js | 2 +- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lib/api/src/modules/addons.ts b/lib/api/src/modules/addons.ts index 35db70f04758..ce95b9765bde 100644 --- a/lib/api/src/modules/addons.ts +++ b/lib/api/src/modules/addons.ts @@ -43,10 +43,16 @@ interface Panels { type StateMerger = (input: S) => S; +interface StoryInput { + parameters: { + [parameterName: string]: any; + }; +} + export interface SubAPI { getElements: (type: Types) => Collection; getPanels: () => Collection; - getStoryPanels: (storyId: string) => Collection; + getStoryPanels: () => Collection; getSelectedPanel: () => string; setSelectedPanel: (panelName: string) => void; setAddonState( @@ -74,17 +80,21 @@ export default ({ provider, store }: Module) => { const api: SubAPI = { getElements: type => provider.getElements(type), getPanels: () => api.getElements(types.PANEL), - getStoryPanels: storyId => { - const storyParameters = provider.getParameters(storyId); - const panels = api.getPanels(); - if (!panels || !storyParameters) { - return panels; + getStoryPanels: () => { + const allPanels = api.getPanels(); + const { storyId, storiesHash } = store.getState(); + const storyInput = storyId && (storiesHash[storyId] as StoryInput); + + if (!allPanels || !storyInput) { + return allPanels; } + const { parameters } = storyInput; + const filteredPanels: Collection = {}; - Object.entries(panels).forEach(([id, panel]) => { + Object.entries(allPanels).forEach(([id, panel]) => { const { paramKey } = panel; - if (paramKey && storyParameters[paramKey] && storyParameters[paramKey].disabled) { + if (paramKey && parameters[paramKey] && parameters[paramKey].disabled) { return; } filteredPanels[id] = panel; diff --git a/lib/api/src/tests/addons.test.js b/lib/api/src/tests/addons.test.js index 95a016a71508..c17c485518ec 100644 --- a/lib/api/src/tests/addons.test.js +++ b/lib/api/src/tests/addons.test.js @@ -61,11 +61,7 @@ describe('Addons API', () => { describe('#getStoryPanels', () => { it('should return all panels by default', () => { // given - const providerWithStoryParameters = { - ...provider, - getParameters: () => {}, - }; - const { api } = initAddons({ provider: providerWithStoryParameters, store }); + const { api } = initAddons({ provider, store }); // when const filteredPanels = api.getStoryPanels(); @@ -77,21 +73,24 @@ describe('Addons API', () => { it('should filter disabled addons', () => { // given const storyId = 'story 1'; - const providerWithStoryParameters = { - ...provider, - getParameters: id => { - if (id === storyId) { - return { - a11y: { disabled: true }, - }; - } - return null; - }, + const storeWithStory = { + getState: () => ({ + storyId, + storiesHash: { + [storyId]: { + parameters: { + a11y: { disabled: true }, + }, + }, + }, + }), + setState: jest.fn(), }; - const { api } = initAddons({ provider: providerWithStoryParameters, store }); + + const { api } = initAddons({ provider, store: storeWithStory }); // when - const filteredPanels = api.getStoryPanels(storyId); + const filteredPanels = api.getStoryPanels(); // then expect(filteredPanels).toEqual({ diff --git a/lib/ui/src/containers/panel.js b/lib/ui/src/containers/panel.js index fcf2e7eca281..88821840822d 100644 --- a/lib/ui/src/containers/panel.js +++ b/lib/ui/src/containers/panel.js @@ -11,7 +11,7 @@ const createPanelActions = memoize(1)(api => ({ })); const mapper = ({ state, api }) => ({ - panels: api.getStoryPanels(state.storyId), + panels: api.getStoryPanels(), selectedPanel: api.getSelectedPanel(), panelPosition: state.layout.panelPosition, actions: createPanelActions(api),