Reputation: 63
I'm using Vue 3 and have a component which needs to show a variety of different sub-components, depending on context. Using a slot here is the correct answer in Vue3 to achieve this. I'm using Storybook 8 to demonstrate how this would look to stakeholders, but I haven't found a way to get this to work within my ecosystem.
My config and syntax seemed to be OK in Storybook 7, but following an upgrade to Storybook 8 with it's 'First-class Vue support', it no longer works as it did. clearly I need some help in the migration, I'm just not clear how I need to change my practices to get this to work.
I should say that I am a newcomer to both Vue and Storybook, so I expect that I am just missing something fundamental.
If anyone can point me to a Storybook example which shows how to get dynamic sub-components into a component slot, that would be very helpful.
Here is my Vue component (this all works, apart from the slots, so my props, setup and general Storybook config are all ok, I think.)
<template>
<div class="alert" :id="props.identifier" :class="[alertStyleClass, alertWidthClass, alertLayoutClass]">
<Icon v-if="props.icon" class="alert__icon" :name="props.icon" />
<div class="alert__main" v-if="slots.main && !props.message">
<slot name="main"> </slot>
</div>
<div class="alert__main" v-else v-html="props.message"></div>
<div class="alert__actions" v-if="slots.actions">
<slot name="actions"> </slot>
</div>
</div>
</template>
And here is an example story using this component (again, general direct props are all working, the subcomponent 'CheckboxComponent' seems to be ok in it's own) and this syntax seemed to be ok in Storybook 7, so I'm just not sure what has changed, or how I need to adapt my practice to get this to work in Storybook 8.
export const CheckboxNotification: Story = {
args: {
identifier: '',
style: AlertStyle.Information
},
parameters: {
slots: {
main: {
description: 'Main slot',
components: { CheckboxComponent },
template: `<CheckboxComponent label="Label" identifier="AlertCheckbox" value="true" name="AlertCB" />`
}
}
}
}
I tried this approach, but the main slot is then just populated with a literal string. I didn't expect this to do anything, but at least the content appears in the right place, but it isn't compiled into the required subcomponent.
export const CheckboxNotification: Story = {
args: {
identifier: '',
style: AlertStyle.Information,
main: `<CheckboxComponent label="Label" identifier="AlertCheckbox" value="true" name="AlertCB" />`
}
}
There are obviously a lot of bits missing from this - props definitions, full setup code etc. so if I have omitted anything crucial to aid in diagnosing this issue, please let me know. All I know is I'm frustrated and I can't find any assistance with this - it feels like a fundamental issue, so I also feel pretty dumb not being able to work it out - but I just can't find the answer.
I don't want to change my Vue component to support Storybook - I feel that all of this should be possible within the story code.
Upvotes: 2
Views: 2024
Reputation: 63
I changed my Story export as follows, using the render function within Storybook to interpolate the subcompponent. I am also importing the component and sub component in a slightly different way.
export const CheckboxNotification: Story = {
args: {
identifier: '',
style: AlertStyle.Information
},
render: (args) => ({
components: { AlertComponent, CheckboxComponent },
setup() {
return { args }
},
template: `
<AlertComponent v-bind="args">
<template #main>
<CheckboxComponent label="Label" identifier="AlertCheckbox" value="true" name="AlertCB" />
</template>
</AlertComponent>
`
})
}
Upvotes: 1