storybook: Bug: Type support for Vue component slots in stories
Is your feature request related to a problem? Please describe
Storybook 7 introduces many improvements for type support when using Vue. Still, we’re seeing errors when trying to pass arguments to component slots.
Below, I’m making stories for my button component. Instead of passing text (content) to a label prop, I want my button component to behave like a native HTML element. The button component has a single, unnamed slot (default) where the content goes. The correct way to set up the default slot is with args/argTypes:
// Button.stories.ts
import { Meta, StoryObj } from '@storybook/vue3'
import Button from './Button.vue'
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
render: (args) => ({
components: {
Button,
},
setup() {
return { args }
},
template: `
<Button v-bind="args">{{ args.default }}</Button>
`,
}),
argTypes: {
default: {
control: 'text',
},
size: {
control: 'select',
options: ['small', 'medium', 'large'],
},
},
args: {
default: 'Click me',
size: 'medium',
},
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {}
export const LongText: Story = {
args: {
default: 'I am a button with faaaar toooo much text',
},
}
The code runs correctly and the story controls allows me to change the button text, but TypeScript is not happy.
Describe the solution you’d like
Add type support for Vue component slots, both default slot and named.
The BaseAnnotations
type, which is extended by the ComponentAnnotations
interface, holds the type definitions for args
(Partial<TArgs>
) and argTypes
(Partial<ArgTypes<TArgs>>
). From what I’ve been able to find, this seems like the right place to do the implementation.
TArgs
is a mapped type by default, but is likely assigned only the component props. Then the implementation might be deeper than I’ve been able to look at this point.
Describe alternatives you’ve considered
The alternative is using @ts-ignore
, but that is never a permanent solution.
Are you able to assist to bring the feature to reality?
yes, I can
Additional context
I’ve tried to solve this myself, but I’m not familiar enough to see where the actual changes needs to be made. I am however a TypeScript developer so if anyone could point me to the right file, I’d be happy to work out a solution.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 51 (32 by maintainers)
Okay, I got something working on typelevel, will finalize tomorrow, and check if it also works on runtime:
@chakAs3 Maybe we can pair up on this?
@CasperSocio As a workaround you can do:
I’m not 100% sure how slots in Vue work, and what makes sense here. Those slots args are only used if there is a custom render function right? Does it make sense to show autocompletion for the slots, even when they are not referenced in the render function?
And what if a user wants to do something differently, then use the named slots:
What would really make this rock is to not have to write a render function in order to get this to work (similar to the auto-render functions provided for React). 😁
Sorry for missing this issue, I noticed that PR now uses vue-tsc to generate component types, volar v1.3 adds a new vue-component-type-helpers package, which is used behind vue-component-meta and can be used to extract The component type generated by vue-tsc, this may also apply to storybook.
Please note that v1.3 is a pre-release version of v1.4, there are still some unresolved edge cases, you can also wait for v1.4.
I really apriciate the work put into this bug guys! TS is happy again in
7.0.0-rc.0
and only throws these while building SB:Using vite v4.1.4 and vite-plugin-dts 2.1.0, which is throwing the errors, but it doesn’t prevent the build from completing. Nor does it impact the SB instance I’m hosting om Firebase. Just thought you should know that there’s probably missing type exports 😅
Again: Thanks guys, stories are going to be a lot easier to write now
@kasperpeulen i guess there is some bugs but no worries i’m already reworking the renderer render in reactive way i’m will be checking this and fix the bug i will add you to review the PR if you don’t mind
@chakAs3 I think we want to only close tickets when we do a new release cc @shilman
Nice! So we can get the type def like this:
In my example at the top, you’ll find the
*.stories.ts
file that yields the slot section of the controls. The code will work as intended, but TS still throws a type errorObject literal may only specify known properties, and 'default' does not exist in type 'Partial<Readonly<ExtractPropTypes...
.meta.args
andmeta.argTypes
must be able to contain the component slots as props. If the component has an unnamed slot, we also need to havemeta.argTypes.default
. And if the component has asectionAside
slot, we also needmeta.argTypes.sectionAside
.When this is done, we should also improve the documentation for how to use slots in stories.
Write stories / Args / Args can modify any aspect of your component
contains information on how to use slots with Vue and TS, but the example can definitely be improved once we have proper type support.