storybook code preview doesn't show the usage of slots in VueJS

Viewed 4468

I am using Storybook to create a documentation about the components I'm using in my project. One of the componentes makes the usage of the feature called Slots in VueJS. In the snippet below, you can see an Story using the slots.

export const IconText = (args, { argTypes }) => ({
  props: Object.keys(argTypes),
  components: { Button, IconAdd },
  template: `
  <Button>
    <template v-slot:text>
      Text
    </template>

    <template v-slot:icon>
      <IconAdd />
    </template>
  </Button>
  `
})

The problem is, if I touch to see the code preview of this Story in Storybook, I just see the snippet below, I'd like to see the usage of the slots, do you know how can I achieve that?

<template><Button /></template>
4 Answers

I solved this by removing the slot from the $props variable and simply passing it into the template with args.default (default is the slot name)

export default {
    title: 'Button',
    component: ECBtn,
    parameters,
    argTypes: {
        default: {
            description: "The default Vue slot",
            control: {
                type: 'text',
            },
            table: {
                category: 'Slots',
                type: {
                    summary: 'html',
                },
            }
        }
    }

};

const Template = (args, { argTypes }) => ({
  props: Object.keys(argTypes),
  components: { 
    'ec-btn': ECBtn,
  },
  template:`
    <ec-btn v-bind="propsWithoutSlot">
      ${args.default}
    </ec-btn>
  `,
  computed: {
    propsWithoutSlot() {
        const all = this.$props;
        delete all.default
        return all;
    }
}
});

This is what the source code looks like. Would be nice to get rid of the <template> tags, but at least the slot shows up right!

enter image description here

EDIT: I found a way to remove the <template> tags as well. In the preview.js file, you need can use transformSource() to remove the template tags and whatever else you want to change in the source snippet. I'm using beautify-js to format the html indentation after removing the template tags.

// preview.js


var beautify_html = require('js-beautify').html;

export const parameters = {
  docs: {
    transformSource: (src) => {
      const string1 = src.substr(0, src.length - 12).substr(10)

      return beautify_html(string1)
    }
  }
}

I had the same problem and here is what I did to make it works.

I know this is not the prettiest way to do it but that's the only way I found.

So you have to tell in your story's parameters what code to display manually as below :

yourStory.parameters = {
  docs: {
    source: {
      code: 'Write code you want to be displayed here',
    },
  },
};

For more informations, check this : https://storybook.js.org/docs/react/writing-docs/doc-blocks#docspage-1

an easy way to do it

import Alert from './Alert.vue'

export default {
  title: 'Molecules/Alert',
  component: Alert,
}

const Template = (args, { argTypes }) => ({
  components: { Alert },
  props: Object.keys(argTypes),
  template: `
    <Alert v-bind="$props">
        <template v-if="${'default' in args}" v-slot>${args.default}</template>
    </Alert>
  `,
})

export const Simple = Template.bind({})
Simple.storyName = 'Default'
Simple.args = {
  icon: 'info',
  linkLabel: 'More information',
  linkUrl: '/products',
  isExternalLink: false,
  default:
    '<p class="uk-inline-block uk-margin-remove">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.</p>',
}

if you're using named slots would be

import Alert from './Alert.vue'

export default {
  title: 'Molecules/Alert',
  component: Alert,
}

const Template = (args, { argTypes }) => ({
  components: { Alert },
  props: Object.keys(argTypes),
  template: `
    <Alert v-bind="$props">
        <template v-if="${'namedSlot' in args}" v-slot>${args.namedSlot}</template>
    </Alert>
  `,
})

export const Simple = Template.bind({})
Simple.storyName = 'Default'
Simple.args = {
  icon: 'info',
  linkLabel: 'More information',
  linkUrl: '/products',
  isExternalLink: false,
  namedSlot:
    '<p class="uk-inline-block uk-margin-remove">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt.</p>',
}

this is what I get in the story preview

(args, { argTypes }) => ({
2  components: { Alert },
3  props: Object.keys(argTypes),
4  template: `
5    <Alert v-bind="$props">
6        <template v-if="${'default' in args}" v-slot>${args.default}</template>
7    </Alert>
8  `,
9})

cheers

Related