zeplin/cli-connect-storybook-plugin

How do I correctly link to my storybook?

jurrianlammerts opened this issue ยท 6 comments

I'm having a hard time figuring out how to link components to Storybook.

This is my connected-components config:

Below is my Button story

import React from 'react';
import { action } from '@storybook/addon-actions';
import { withA11y } from '@storybook/addon-a11y';

import Button from '../components/Button.js';

export default {
  title: 'Button',
  component: Button,
  decorators: [withA11y],
};

export const DefaultButton = () => (
  <Button onClick={action('clicked', { depth: 1 })}>Hello Button</Button>
);

DefaultButton.story = {
  name: 'default',
  parameters: {
    options: { selectedPanel: 'storybook/actions/panel' },
  },
};

The 'Open in Storybook' link opens the following URL:
http://localhost:9009/?path=/story/button--default

But the right URL for this story is:
http://localhost:9009/?path=/story/button--default-button

What is the correct way to link to my story?

Bump.

Looks like the button "Open in Storybook" defaults to the first story.
Though if array of stories is provided, menu icon to the right of the button appears with the stories list.

Screen Shot 2020-02-26 at 21 36 21

PS: Meant to post this from my @n3tn0de account ๐Ÿ˜…

yuqu commented

Hi Jurrian,

There are a couple of question I'd like to ask about your setup.

Button story you shared has only one story.

export default {
  title: 'Button', // -----> Story kind
  component: Button,
  decorators: [withA11y],
};
...
...
DefaultButton.story = {
  name: 'default', // ------------> Story name
  parameters: {
    options: { selectedPanel: 'storybook/actions/panel' },
  },
};

Checkout my comments on the code sample. Kind parameter is OK but you override story name as default, so the storyId of that story is actually button--default. It would be button--default-button if not the name was not overriden (SB converts variable name to kebab-case by default). Do you manipulate that story name in any other place on your repository (maybe in .storybook/config.js)? Even if you manipulate it the link is was automatically generated based on Storybook output, so Storybook tells our plugin that there is a storyId as button--default. Considering the your sample story, looks like we have the correct URL.

Another thing, I see that you also have manually defined some story names in the configuration file. Those values manually generate links without connecting to Storybook itself, just by using their URL format. Do those stories exist on a separate file? Can you see any of the links in Zeplin like Alexey has shown above? If you see them, are they correct?

Hi Yuqu,

Thanks for the fast response! I actually didn't know that by defining the story name it overwrites storyId. It is in no way my goal to manipulate the story's name.

I've made some small changes in the meantime and it seems that Zeplin redirects to the right URL, but Storybook gives me this weird error. When I reload the page it doesn't... I'm so confused.

image

I've made a copy of the repo and made it public, so if you like you can see for yourself. ๐Ÿ˜…

https://github.com/jurrianlammerts/connected-zeplin-components

yuqu commented

What do you see on the address bar when you have a problem on refresh?

I gave it a try but could not reproduce it. Reloading the page is working for me but I could say after you open your story successfully, the URL we generated has no effect on Storybook.

I remember I was experiencing something like that during the development of the plugin. Opening same link in a fresh browser was always working when that happens, so I was thinking the problem had been related to something on local storage/cookie etc. on Storybook side.

I have the same issue as @jurrianlammerts , but I can also expand on my scenario a bit more since its not identical:

In my components.json I have specified the config as such (trailing slash intentional, even tried adding it twice.. more on that later):

"plugins": [
    {
      "name": "@zeplin/cli-connect-storybook-plugin",
      "config": {
        "url": "https://dev-next.trr.se/component-library/"
      }
    },

The plugin seems to do a decent job at picking up available stories. There are a couple of stories, first two look like this (and the plugin seems to always default to the first one):

storiesOf('Components/Button', module)
  .addDecorator(withInfo)
  .addParameters({ info: 'Button component - Primary' })
  .add('Primary - Default', () => (
    <Button onClick={action('clicked')} primary testSelector="primaryselector">
      Primary
    </Button>
  ))
  .add('Primary - Large', () => (
    <Button
      primary
      large
      onClick={action('clicked')}
      testSelector="primaryselector"
    >
      Primary
    </Button>
  ))

Now to the part where things act up..

  1. The link that the plugin produces looks like this:
    https://dev-next.trr.se/component-library?selectedKind=Components%2FButton&selectedStory=Primary%20-%20Default
    However, when I manually navigate there (no Zeplin interaction), I end up on this link: https://dev-next.trr.se/component-library/?path=/story/components-button--primary-default
    This is mostly fine and just two different ways leading to the same result, BUT the link produced by the plugin doesn't resolve correctly!
    After a closer look on the source code, I assume this is the (correct) work of the url-join library and that the issue is that my URL has a trailing slash where there shouldn't be any in order to follow standards

If I however append a trailing slash to the configured url (this is where the trailing slash config comes in), the browser (i.e. Storybook) translates [note the trailing slash] https://dev-next.trr.se/component-library/?selectedKind=Components%2FButton&selectedStory=Primary%20-%20Default to https://dev-next.trr.se/component-library/?path=/story/components-button--primary-default

...and at this point I am in the same situation as @jurrianlammerts - on the first load this image is presented:
image
However, a refresh solves the issue, and any subsequent visits to any component do not share the same problem. I'll move on to browse the Storybook repo for any such issues too.

UPDATE:
I found this in the sources tab, possibly related?
On the first load, Storybook is working with an undefined id
image

On the second/reload, we are looking at the correct source:
image

UPDATE2:
Possibly relevant Storybook issues (closed with fix/merge though): storybookjs/storybook#5925 (comment)
storybookjs/storybook#6075

YET ANOTHER UPDATE:
Given Update2, possibly this could be resolved by adopting the new Storybook URL format?

So for selectedKind we'd have to skip the urlEncoding and instead apply lowercase:

private createLink(kind: string, name?: string): Link {
        const urlEncodedKind = encodeURIComponent(kind);

        let preparedUrl;
        if (name) {
            const urlEncodedName = encodeURIComponent(name);
            preparedUrl = urljoin(this.targetUrl, `?selectedKind=${urlEncodedKind}&selectedStory=${urlEncodedName}`);
        } else {
            preparedUrl = urljoin(this.targetUrl, `?selectedKind=${urlEncodedKind}`);
        }

        return { type: LinkType.storybook, url: preparedUrl };
    }

to replace selectedKind=Components%2FButton with path=/story/components-button

& would be replaced by --

and then selectedStory=Primary%20-%20Default would be changed to primary-default again by replacing encoding with lowercase.

If this is the direction you would like to go, I'd be happy to submit a PR.

yuqu commented

Hey @jurrianlammerts,

We've got many reports of "No Preview" for the links generated by the plugin. We were using old format hyperlinks for compability between Storybook versions. The plugin now generates new format hyperlinks if the storybook instance is v5+.

I've tried it out with your sample repository, it works fine. You don't even need to type in all kind and stories, it will automatically find Button stories. Using the following setup,

  "components": [
    {
      "path": "src/components/Button.js",
      "zeplinNames": [
        "button/default/primary",
        "button/default/secondary",
        "button/default/success",
        "button/default/outline",
        "button/default/disabled"
      ]
    }
  ]

generated these links on Zeplin: