Skip to content

Refactoring of withX wrappers withNotes and withInfo#1538

Merged
shilman merged 4 commits intomasterfrom
1147-addon-info-refactor
Jul 31, 2017
Merged

Refactoring of withX wrappers withNotes and withInfo#1538
shilman merged 4 commits intomasterfrom
1147-addon-info-refactor

Conversation

@shilman
Copy link
Copy Markdown
Member

@shilman shilman commented Jul 28, 2017

Issue: #1452

What I did

  • make withX signatures consistent
  • make string-only variant of withNotes/withInfo
  • simplify withInfo code

I have documented the rationale behind this change here:

https://gist.github.com/shilman/792dc25550daa9c2bf37238f4ef7a398#options-types

Will obviously put this into a more permanent place in the docs if we converge on this convention and migrate things over to it.

How to test

yarn && yarn boostrap
cd examples cra-kitchen-sink
yarn storybook

- make signatures consistent
- make string-only variant of withNotes/withInfo
- simplify withInfo code
Comment thread addons/notes/src/index.js Outdated
export const withNotes = textOrOptions => {
const channel = addons.getChannel();

const text = typeof textOrOptions === 'string' ? textOrOptions : textOrOptions.text;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract into a function

'addons composition',
withInfo('see Notes panel for composition info')(
withNotes({ notes: 'Composition: Info(Notes())' })(context =>
withInfo({ text: 'see Notes panel for composition info' })(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the example we show to users, do you think it makes sense like this?
I think the less verbose syntax:
withInfo('see Notes panel for composition info')
makes more sense tbh.

We should document these options somewhere, but the example should showcase the common use case here, I think.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree

Comment thread addons/info/src/index.js
addWithInfo: deprecate(function addWithInfo(storyName, info, storyFn, _options) {
return this.add(storyName, withInfo(info, _options)(storyFn));
addWithInfo: deprecate(function addWithInfo(storyName, text, storyFn, options) {
if (typeof storyFn !== 'function') {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use a bit of refactoring,
in some cases the const text is actually the storyFn. I find this confusing.

I'd prefer using abstract names or simply an argument array to do detection, and only assign to a const when we are sure what it is.

Comment thread addons/info/src/index.js
const options = {
...defaultOptions,
..._options,
...infoOptions,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also merge in:

if (!options.propTables) {
  options.propTables = null;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would you merge this in? see the comment above in the code.

@ndelangen
Copy link
Copy Markdown
Member

This will be backwards compatible? or not?

@tmeasday
Copy link
Copy Markdown
Member

tmeasday commented Jul 28, 2017

I think both withX functions are new in 3.2 -- It's only incompatible in sense that the old way is deprecated. But @shilman can answer for sure.

Comment thread addons/info/src/index.js Outdated
export const withInfo = (info, _options) =>
addonCompose((storyFn, context) => addInfo(storyFn, context, info, _options));
export const withInfo = textOrOptions => {
if (typeof textOrOptions === 'string') {
Copy link
Copy Markdown
Member

@tmeasday tmeasday Jul 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just:

const options = (typeof textOrOptions === 'string') ?
  { text: textOrOptions } :
  textOrOptions;

@codecov
Copy link
Copy Markdown

codecov bot commented Jul 28, 2017

Codecov Report

Merging #1538 into master will increase coverage by 0.02%.
The diff coverage is 69.23%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1538      +/-   ##
==========================================
+ Coverage   20.52%   20.55%   +0.02%     
==========================================
  Files         241      241              
  Lines        5222     5220       -2     
  Branches      643      657      +14     
==========================================
+ Hits         1072     1073       +1     
+ Misses       3667     3639      -28     
- Partials      483      508      +25
Impacted Files Coverage Δ
addons/notes/src/index.js 0% <0%> (ø) ⬆️
addons/info/src/index.js 90.9% <90%> (-0.4%) ⬇️
lib/ui/src/modules/ui/libs/hierarchy.js 45.45% <0%> (ø) ⬆️
addons/events/src/components/Event.js 0% <0%> (ø) ⬆️
addons/knobs/src/react/WrapStory.js 12% <0%> (ø) ⬆️
app/react/src/client/preview/element_check.js 41.17% <0%> (ø) ⬆️
addons/info/src/components/Props.js 37.2% <0%> (ø) ⬆️
addons/knobs/src/KnobManager.js 35.41% <0%> (ø) ⬆️
lib/ui/src/modules/ui/configs/init_panels.js 25% <0%> (ø) ⬆️
addons/knobs/src/components/types/Color.js 8% <0%> (ø) ⬆️
... and 26 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b02fec0...ee6204e. Read the comment docs.

Copy link
Copy Markdown
Member

@ndelangen ndelangen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

Copy link
Copy Markdown
Member

@usulpro usulpro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Comment thread addons/notes/src/index.js
return getStory => context => {
// send the notes to the channel before the story is rendered
channel.emit('storybook/notes/add_notes', notes);
channel.emit('storybook/notes/add_notes', options.text);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we mean that this addon could have other options in the future (or even if we want to keep it as an addon example) why don't pass all 'options' object here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can emit those options once we handle them on the other end.

There may be "preview-side" options, so I don't think it's necessarily the case that we'd want to emit them all.

Comment thread addons/info/src/index.js
ul: UL,
};

export function addInfo(storyFn, context, info, _options) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to not export this function to users? Maybe our documentation shouldn't encourage people to use it, but there could be some "advanced" use cases when this form is more convenient! Especially it makes sense after #1501

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, we should never export a function to users if we don't need to, because then we are stuck supporting it unless we want to break the API.

Comment thread addons/info/src/index.js

export const withInfo = (info, _options) =>
addonCompose((storyFn, context) => addInfo(storyFn, context, info, _options));
export const withInfo = textOrOptions => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it would be nice to provide here such an option as well:

withInfo('text info', { options })

There are two reasons for that:

1.1. We might want to use different text info with the same other options:

.add('Button', withInfo('Default Button', widgetInfoOptions)(() => <Button />))

1.2. We might want to use multiline template string for `text info` and such syntax would be less verbose

  1. It's relevant to the previous behavior of .addWithInfo when we could pass (or not) text info as a separate argument

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@usulpro the reason @tmeasday wanted to keep it to a single argument is for this API:

https://gist.github.com/shilman/792dc25550daa9c2bf37238f4ef7a398#options-types

The API described in the gist is obviously just a proposal, but we think having a single argument makes stuff like this simple to implement. If we have two arguments it gets complicated fast.

Copy link
Copy Markdown
Member

@tmeasday tmeasday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@shilman shilman merged commit f98a950 into master Jul 31, 2017
@shilman shilman deleted the 1147-addon-info-refactor branch July 31, 2017 00:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants