storybookjs/vue-cli-plugin-storybook

Support addon-docs

Opened this issue · 24 comments

I guess this is somewhat similar to #33. Storybook 5.2 was released with the docs page in the addon-docs.

Unfortunately I was not able to get it to work in my vue-cli project. The docs suggest using a preset, but I guess that does overwrites the webpack config that vue-cli-plugin-storybook is generating.

Using the manual setup guide would require loading the @storybook/source-loader. Afaics there is no possibility to modify the webpack config generated by vue-cli-plugin-storybook, is there?

Emobe commented

You can still add webpack.config.js to storybook config. Also the preset doesn't go in the webpack config, it goes into presets.js in the storybook config folder.

One problem I've come across is storybook not recognising a vue project, this plugin works with a blank vue project though so might be specific to the app I was trying.

Yes, I have created the presets.js besides addons.js and config.js.

I guess I could create a webpack.config.js, but the whole point of vue-cli-plugin-storybook is that I don’t have to do that.

Yeah, addon-docs is a little bit complicated. It would definitely be a feature request for this plugin to automagic it too.

Emobe commented

Just tried it myself again and can confirm it isn't working. I have a feeling it will need to be loaded manually within the cli rather than using the provided preset

It works fine for me with the DocsPage preset on both Vue CLI 3 and 4. With the manual setup I came across an issue which required me to disable JSX parsing in the Vue Babel preset though (see storybookjs/storybook#8096).

Now that it has been a few months, does anybody have Storybook Docs working with Vue-cli-plugin-storybook?

It works fine for me with the DocsPage preset on both Vue CLI 3 and 4. With the manual setup I came across an issue which required me to disable JSX parsing in the Vue Babel preset though (see storybookjs/storybook#8096).

@LeBenLeBen are you able to share a repo with us so we can see how you got vue-cli-plugin-storybook working with addon-docs?

Storybook 5.3 has just been released. There are a lot of changes. These should probably be adapted in this plugin:
https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-52x-to-53x

So, My next TODO in this project is to support Docs, Storysource & Typescript. I think the issues everyone are facing is because of Typescript interfering.

Hey all, I'm a contributor to storybook that helps with some of the vue maintenance things. Created this a while back (on 5.2), in case it helps. It's a working example with both vue-cli, this plugin, typescript, and docs.

https://github.com/Aaron-Pool/Vue-Cli-Storybook-Docs

Thanks @Aaron-Pool for giving me the start, but I fixed the issue in your repo where JSX is not allowed. Will be releasing as 1.2.0 in a few minutes once I make sure tests pass.

Thanks @Aaron-Pool for giving me the start, but I fixed the issue in your repo where JSX is not allowed. Will be releasing as 1.2.0 in a few minutes once I make sure tests pass.

Right. I've actually found a work around for that issue myself since I created that issue. I should probably update it at some point.

I assume the solution you found is the same as mine, sending babelOptions to addon-docs.

@pksunkara Actually, no, the problem was simply the order and rule regex for the vue preset. So I had to remove where the preset currently was and re-add it under just a js/jsx rule and at the very end.

Check here https://github.com/Aaron-Pool/storybook-mdx-vue-example/blob/master/.storybook/main.js

So, I released 1.2.0 with the babelOptions fix. But it still doesn't support the following format in MDX:

<Preview>
  <Story name="basic">
    <HelloWorld msg="HelloWorld Docs" />
  </Story>
</Preview>

I am still looking at @Aaron-Pool's fix above and trying to understand what the issue is.

@pksunkara to use inline Jsx two conditions need to be met, and they're oddly contradictory.

  1. the internal element needs to be a React.Element, because that's what MDX supports natively. It doesn't understand the vue version of jsx.
  2. the only permitted contents of the <Story> block when addon-docs is used with @storybook/vue is a vue component.

The first condition can be solved pretty easily, actually. There's a relatively simple library vue-to-react that uses a simple effect hook to render a vue component as a react component. So, you can essentially do:

import toReact from '@egoist/vue-to-react';
import VueComponent from './VueComponent.vue`;
const RVueComponent = toReact(VueComponent);

# This is a mdx header
## I can use a vue component
<RVueComponent/>

Without any issues. However, you can't use it in a story block, because the <Story> block expects it's content to be either { () => VueComponent } or {{ ...VueComponentOptions }}. So if you're really attached to the idea of stories you're kind of out of luck. However, I've found the people that are writing long form, custom docs with MDX rather than just using the automatically generated docs page that addon-docs gives you for free don't normally actually care if each example shows up as a story in the sidebar, in which case you can use just the <Preview> block without using a <Story> block inside and you get all the functionality you would want from and example, you just don't get it exported as a "story".

import toReact from '@egoist/vue-to-react';
import VueComponent from './VueComponent.vue`;
const RVueComponent = toReact(VueComponent);

# this works just fine
<Preview>
    <RVueComponent/>
</Preview

I'm hoping to contribute to the upcoming Storybook 6.0 release to make this all a much smoother and first-class process, but it was really hard in 5.x release because a lot of the vue infrastructure is pretty outdated since the storybook team has never had a vue-specific maintainer before and almost everything I wanted to change could be seen as a breaking change.

@Aaron-Pool Thanks for the explanation. That clears a few things up.

The babelOptions fix allows the following to work:

<Preview>
  <RHelloWorld msg="HelloWorld Docs" />
</Preview>

Looks like I don't even need to write the toReact part. RHelloWorld already exists 😄

Why doesn't the following work though?

<Preview>
  <Story name="With JSX">
    {{
      render() {
        return <HelloWorld msg="HelloWorld Docs" />;
      }
    }}
  </Story>
</Preview>

Fails with the following in the browser console.

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.

I guess the MDX loader converts the JSX inside render() to react.

@pksunkara that's correct. Using Vue jsx and react jsx on the same page would require some sort of Babel plugin that scoped the Vue jsx transpilation just to a <Story/> block. I'm pretty confident that's actually possible, but it wasn't something I've had the opportunity to do so far.

Awesome to see progress on this guys!! 😍

@Aaron-Pool Re: Your suggestion that people use Vue JSX OUTSIDE of stories, I'd almost certainly reject that idea as a final solution for 6.0. Stories are not just things that show up in the sidebar: they are the foundation for the entire storybook ecosystem of of addons/integrations, and I wouldn't want to undermine that in any way. That said, I'm happy to make breaking changes in addon-docs / core / @storybook/vue--or whatever it takes--to get this improved syntax working. Also, FYI, ship window for 6.0 is realistically end of Feb for this kind of change.

Is it possible to work around the JSX parsing conflict by importing a story from a separate module? Something like passing the story to the <Story> component:

import { basic } from './MyComponent.stories.js'

<Preview>
  <Story story="{basic}" />
</Preview>

Is it possible to work around the JSX parsing conflict by importing a story from a separate module? Something like passing the story to the <Story> component:

import { basic } from './MyComponent.stories.js'

<Preview>
  <Story story="{basic}" />
</Preview>

Yes! But you're gonna just want to reference it by id. Syntax is something like <Story id="category--storyName">.

The good news: MDX-2 is in rc now and will be used in Storybook-7 afaik. It will support using Vue JSX directly in MDX files.

Currently however, there is the following in the example mdx file:

<Canvas>
  <RMyButton onClick={linkTo('Button', 'With Some Emoji')}>With JSX</RMyButton>
</Canvas>

This does not work and we shouldn‘t promote it, even if it was possible.
What do you say @pksunkara, can we remove it?

I did test the generated stuff when I wrote it and it was working. Did anything change to not make it work? Did you make sure to hasBabel while generating?

Until we actually have MDX-2 available, I think we still need to keep this.

I don’t see how it could work like that. RButton is not defined anywhere. @pksunkara