storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
83.59k stars 9.16k forks source link

(Vue) Cannot get array prop values from validator or JSDoc #13644

Open afontcu opened 3 years ago

afontcu commented 3 years ago

Describe the bug Storybook does not extract values for an array prop (Vue).

To Reproduce

    /**
     * My prop description
     */
    category: {
      type: String,
      default: 'primary',
      validator: (v) => ['primary', 'secondary', 'white'].includes(v),
    },

(for the record, I also tried the @values small, normal, large JSDoc comment with no luck).

I haven't been able to make it work, and storybook keeps rendering a text input control with no information about the available types.

I checked, and looks like vue-docgen-api is properly extracting values from a definition such as the ones above.

Expected behavior I expected control addons to display a Select with several options, one for each value of the prop.

Screenshots This is what I get:

image

Instead, I expect something similar to what documentation shows:

image

Code snippets If applicable, add code samples to help explain your problem.

System

  System:
    OS: macOS 10.15.6
    CPU: (8) x64 Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
  Binaries:
    Node: 14.15.0 - ~/.nvm/versions/node/v14.15.0/bin/node
    Yarn: 1.22.10 - ~/.nvm/versions/node/v14.15.0/bin/yarn
    npm: 6.14.11 - ~/Code/(path-to-my-package)/node_modules/.bin/npm
  Browsers:
    Chrome: 87.0.4280.141
    Firefox: 84.0.2
    Safari: 13.1.2
  npmPackages:
    @storybook/addon-a11y: ^6.1.14 => 6.1.14 
    @storybook/addon-actions: ^6.1.14 => 6.1.14 
    @storybook/addon-essentials: ^6.1.14 => 6.1.14 
    @storybook/addon-knobs: ^6.1.14 => 6.1.14 
    @storybook/addon-links: ^6.1.14 => 6.1.14 
    @storybook/addon-viewport: ^6.1.14 => 6.1.14 
    @storybook/vue: ^6.1.14 => 6.1.14 

Thank you, folks!

drik98 commented 2 years ago

I ran into the same problem. Any news?

laddi-netapp commented 1 year ago

This is still a problem in the v7 beta, fyi. Would love to see some movement here...

craigrileyuk commented 9 months ago

If anyone wants a workaround, export this from a 'utils' folder or something inside your stories folder:

export default function (component, property) {
    const validator = component?.props?.[property]?.validator?.toString();
    if (!component || !property || !validator) {
        console.error(`Unable to obtain validator function for ${property} property.`);
        return [];
    }
    else if(/includes/i.test(validator) === false) {
        console.error(`Validator for ${property} doesn't contain an "includes" statement`);
        return [];
    }

    const arrayMatch = validator.match(/\[([^\]]*)\]/);
    if (arrayMatch) {
        const optionsString = arrayMatch[1];
        return optionsString.split(',').map(option => option.trim().replace(/^["']/, '').replace(/["']$/, ''));
      } else {
        console.error(`No options found for ${property} property`);
      }

      return [];
}

Then inside your story file, you can use it like so:

import Button from 'components/button/Button.vue';
import getOptions from "../_utils/extractOptionsFromValidator";

export default {
    title: 'Button',
    component: Button,
    argTypes: {
        size: {
            control: {
                type: 'select',
            },
            options: getOptions(Button, 'size'),
        },
    },
};

Note that this will only work for component props with a validator method that uses the includes method, e.g.

const props = defineProps({
    size: {
        type: String,
        default: 'medium',
        validator: (v) => ['small', 'medium', 'large', 'x-large'].includes(v),
    }
});