Skip to content

Instantly share code, notes, and snippets.

@Stupidism
Last active June 19, 2017 21:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stupidism/4f40f3a9688cb09b3a7cb995831d3be9 to your computer and use it in GitHub Desktop.
Save Stupidism/4f40f3a9688cb09b3a7cb995831d3be9 to your computer and use it in GitHub Desktop.
express-like decorators

My Proposal

We can imitate how express handle middlewares. Extend current api:

middleware-style params

addDecorator((getStory[, next, context]) => {...})

globally

const inspectDecorator = (getStory) => {
  const component = getStory();
  inspectProps(component); // e.g. addon-info can use this to inspect source code
  return component;
};
// same as
const inspectDecorator1 = (getStory, next) => {
  const overridedGetStory = () => {
    const component = getStory();
    inspectProps(component);
    return component;
  };
  return next(overridedGetStory);
};

// e.g. context can be used to inject descript and options addon-info needs
const themeDecorator = (getStory, next, context) => {
  // this will not affect any other decorator who wants the real story component, like addon-info
  return (
    <ThemeContainer theme={context.theme}>
      {next()}
    </ThemeContainer>
  );
};

addDecorator(inspectDecorator);
addDecorator(themeDecorator);

storiesOf

const descriptionDecorator = (getStory, next) => {
  // this will not affect any other decorator who wants the real story component, like addon-info
  const currentComponent = getStory();
  return (
    <div>
      <span>title: {currentComponent.props._title}</span>
      {next()}
    </div>
  );
};

const defaultPropsDecorator = (getStory) => {
  const element = getStory();
  return React.cloneElement(element, {
    _title: 'default title',
    ...element.props,
  });
}

const overrideThemeDecorator = (getStory, next, context) {
  context.theme = {
    ...context.theme,
    /*...*/
  };
  return getStory();
}

let stories = storiesOf('Component')
  .addDecorator(descriptionDecorator)
  .addDecorator(defaultPropsDecorator)
  .addDecorator(overrideThemeDecorator)

per-story

stories
  .addDecorator(story1Decorator)
  .add('story 1', () => <Component />);

const context = {
  theme: {/*...*/}
};
stories
  .addDecorator(story2Decorator)
  .add('story 2', () => <Component />, context);

tree-style return value

(stories | storiesWithNDecorators).addDecorator(decorator) returns (storiesWith1Decorator | storiesWithNplus1Decorators)

const stories = storiesOf('Component')
  .addDecorator(decoratorForAllStories);

const oddStories = stories.addDecorator(decoratorForOddStories)
const evenStories = stories.addDecorator(decoratorForEvenStories)

stories.add('story 0.1', () => <Component />)
oddStories.add('story 1', () => <Component />);
evenStories.add('story 2', () => <Component />);
oddStories.add('story 3', () => <Component />);
evenStories.add('story 4', () => <Component />);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment