@storybook/vue3 7.4.0-alpha.0 → 7.4.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-UXHY756F.mjs +6 -0
- package/dist/config.d.ts +2 -2
- package/dist/config.js +2 -2
- package/dist/config.mjs +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +3 -3
- package/dist/{render-32b7dd3f.d.ts → render-ddbe18a8.d.ts} +2 -6
- package/package.json +8 -7
- package/dist/chunk-35B2DQBU.mjs +0 -6
- package/src/typings.d.ts +0 -1
- package/template/components/Button.vue +0 -52
- package/template/components/Form.vue +0 -41
- package/template/components/Html.vue +0 -18
- package/template/components/Pre.vue +0 -34
- package/template/components/button.css +0 -30
- package/template/stories/vue3-mdx.stories.mdx +0 -46
- package/template/stories_vue3-vite-default-ts/BaseLayout.vue +0 -18
- package/template/stories_vue3-vite-default-ts/CustomRenderFunctionalComponent.stories.ts +0 -32
- package/template/stories_vue3-vite-default-ts/CustomRenderOptionsArgsFromData.stories.ts +0 -45
- package/template/stories_vue3-vite-default-ts/GlobalSetup.stories.ts +0 -55
- package/template/stories_vue3-vite-default-ts/GlobalSetup.vue +0 -6
- package/template/stories_vue3-vite-default-ts/GlobalUsage.stories.ts +0 -29
- package/template/stories_vue3-vite-default-ts/GlobalUsage.vue +0 -3
- package/template/stories_vue3-vite-default-ts/MySlotComponent.vue +0 -12
- package/template/stories_vue3-vite-default-ts/OverrideArgs.vue +0 -40
- package/template/stories_vue3-vite-default-ts/ReactiveArgs.stories.ts +0 -137
- package/template/stories_vue3-vite-default-ts/ReactiveArgs.vue +0 -40
- package/template/stories_vue3-vite-default-ts/ReactiveDecorators.stories.ts +0 -88
- package/template/stories_vue3-vite-default-ts/ReactiveSlots.stories.ts +0 -127
- package/template/stories_vue3-vite-default-ts/Reactivity.vue +0 -44
- package/template/stories_vue3-vite-default-ts/ScopedSlots.stories.ts +0 -81
- package/template/stories_vue3-vite-default-ts/SourceDecorator.stories.ts +0 -46
- package/template/stories_vue3-vite-default-ts/decorators.stories.ts +0 -84
- package/template/stories_vue3-vite-default-ts/preview.ts +0 -12
@@ -1,29 +0,0 @@
|
|
1
|
-
import GlobalUsage from './GlobalUsage.vue';
|
2
|
-
|
3
|
-
export default {
|
4
|
-
component: GlobalUsage,
|
5
|
-
argTypes: {},
|
6
|
-
render: (args: any) => ({
|
7
|
-
// Components used in your story `template` are defined in the `components` object
|
8
|
-
components: { GlobalUsage },
|
9
|
-
// The story's `args` need to be mapped into the template through the `setup()` method
|
10
|
-
setup() {
|
11
|
-
return { args };
|
12
|
-
},
|
13
|
-
// And then the `args` are bound to your component with `v-bind="args"`
|
14
|
-
template: '<global-usage v-bind="args" />',
|
15
|
-
}),
|
16
|
-
};
|
17
|
-
|
18
|
-
export const Primary = {
|
19
|
-
args: {
|
20
|
-
primary: true,
|
21
|
-
label: 'Globally Defined',
|
22
|
-
},
|
23
|
-
};
|
24
|
-
|
25
|
-
export const Secondary = {
|
26
|
-
args: {
|
27
|
-
label: 'Globally Defined',
|
28
|
-
},
|
29
|
-
};
|
@@ -1,12 +0,0 @@
|
|
1
|
-
<!-- <MyComponent> template -->
|
2
|
-
<script setup lang="ts">
|
3
|
-
const props = defineProps({
|
4
|
-
label: String,
|
5
|
-
year: Number,
|
6
|
-
});
|
7
|
-
</script>
|
8
|
-
<template>
|
9
|
-
<div data-testid="scoped-slot">
|
10
|
-
<slot :text="`Hello ${props.label} from the slot`" :year="props.year"></slot>
|
11
|
-
</div>
|
12
|
-
</template>
|
@@ -1,40 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<button type="button" :class="classes" :style="style">
|
3
|
-
<!-- You can use <component /> with `:is` when passing a component as a prop -->
|
4
|
-
<component :is="icon" />
|
5
|
-
</button>
|
6
|
-
</template>
|
7
|
-
|
8
|
-
<script lang="ts">
|
9
|
-
import { computed } from 'vue';
|
10
|
-
|
11
|
-
export default {
|
12
|
-
name: 'override-args',
|
13
|
-
|
14
|
-
props: {
|
15
|
-
icon: {
|
16
|
-
type: Object,
|
17
|
-
required: true,
|
18
|
-
},
|
19
|
-
|
20
|
-
backgroundColor: {
|
21
|
-
type: String
|
22
|
-
},
|
23
|
-
},
|
24
|
-
|
25
|
-
|
26
|
-
setup(props, { emit }) {
|
27
|
-
const classes = {
|
28
|
-
'storybook-button': true,
|
29
|
-
'storybook-button--primary': true,
|
30
|
-
'storybook-button--large': true,
|
31
|
-
};
|
32
|
-
const style = computed(() => ({
|
33
|
-
backgroundColor: props.backgroundColor,
|
34
|
-
}));
|
35
|
-
|
36
|
-
// Notice that `icon` prop component is still passed through even though it isn't mapped
|
37
|
-
return { classes, style, }
|
38
|
-
},
|
39
|
-
};
|
40
|
-
</script>
|
@@ -1,137 +0,0 @@
|
|
1
|
-
import { expect } from '@storybook/jest';
|
2
|
-
import { global as globalThis } from '@storybook/global';
|
3
|
-
import type { Meta, StoryObj, StoryFn } from '@storybook/vue3';
|
4
|
-
import { within, userEvent } from '@storybook/testing-library';
|
5
|
-
import { UPDATE_STORY_ARGS, STORY_ARGS_UPDATED, RESET_STORY_ARGS } from '@storybook/core-events';
|
6
|
-
|
7
|
-
import ReactiveArgs from './ReactiveArgs.vue';
|
8
|
-
|
9
|
-
const meta = {
|
10
|
-
component: ReactiveArgs,
|
11
|
-
argTypes: {
|
12
|
-
// To show that other props are passed through
|
13
|
-
backgroundColor: { control: 'color' },
|
14
|
-
},
|
15
|
-
} satisfies Meta<typeof ReactiveArgs>;
|
16
|
-
|
17
|
-
export default meta;
|
18
|
-
|
19
|
-
type Story = StoryObj<typeof meta>;
|
20
|
-
|
21
|
-
export const ReactiveTest: Story = {
|
22
|
-
args: {
|
23
|
-
label: 'Button',
|
24
|
-
},
|
25
|
-
// test that args are updated correctly in rective mode
|
26
|
-
play: async ({ canvasElement, id }) => {
|
27
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
28
|
-
const canvas = within(canvasElement);
|
29
|
-
|
30
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
31
|
-
await new Promise((resolve) => {
|
32
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
33
|
-
});
|
34
|
-
const reactiveButton = await canvas.getByRole('button');
|
35
|
-
await expect(reactiveButton).toHaveTextContent('Button 0');
|
36
|
-
|
37
|
-
await userEvent.click(reactiveButton); // click to update the label to increment the count + 1
|
38
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
39
|
-
storyId: id,
|
40
|
-
updatedArgs: { label: 'updated' },
|
41
|
-
});
|
42
|
-
await new Promise((resolve) => {
|
43
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
44
|
-
});
|
45
|
-
await expect(canvas.getByRole('button')).toHaveTextContent('updated 1');
|
46
|
-
|
47
|
-
await userEvent.click(reactiveButton); // click to update the label to increment the count + 1
|
48
|
-
await expect(reactiveButton).toHaveTextContent('updated 2');
|
49
|
-
},
|
50
|
-
};
|
51
|
-
|
52
|
-
export const ReactiveHtmlWrapper: Story = {
|
53
|
-
args: { label: 'Wrapped Button' },
|
54
|
-
|
55
|
-
decorators: [
|
56
|
-
() => ({
|
57
|
-
template: `
|
58
|
-
<div style="border: 5px solid red;">
|
59
|
-
<story/>
|
60
|
-
</div>
|
61
|
-
`,
|
62
|
-
}),
|
63
|
-
],
|
64
|
-
play: async ({ canvasElement, id }) => {
|
65
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
66
|
-
const canvas = within(canvasElement);
|
67
|
-
|
68
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
69
|
-
await new Promise((resolve) => {
|
70
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
71
|
-
});
|
72
|
-
const reactiveButton = await canvas.getByRole('button');
|
73
|
-
await expect(reactiveButton).toHaveTextContent('Wrapped Button 0');
|
74
|
-
|
75
|
-
await userEvent.click(reactiveButton); // click to update the label to increment the count + 1
|
76
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
77
|
-
storyId: id,
|
78
|
-
updatedArgs: { label: 'updated Wrapped Button' },
|
79
|
-
});
|
80
|
-
await new Promise((resolve) => {
|
81
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
82
|
-
});
|
83
|
-
await expect(canvas.getByRole('button')).toHaveTextContent('updated Wrapped Button 1');
|
84
|
-
|
85
|
-
await userEvent.click(reactiveButton); // click to update the label to increment the count + 1
|
86
|
-
await expect(reactiveButton).toHaveTextContent('updated Wrapped Button 2');
|
87
|
-
},
|
88
|
-
};
|
89
|
-
|
90
|
-
// to test that Simple html Decorators in CSF2 format are applied correctly in reactive mode
|
91
|
-
const ReactiveCSF2WrapperTempl: StoryFn = (args) => ({
|
92
|
-
components: { ReactiveArgs },
|
93
|
-
setup() {
|
94
|
-
return { args };
|
95
|
-
},
|
96
|
-
template: '<ReactiveArgs v-bind="args" />',
|
97
|
-
});
|
98
|
-
|
99
|
-
export const ReactiveCSF2Wrapper = ReactiveCSF2WrapperTempl.bind({});
|
100
|
-
|
101
|
-
ReactiveCSF2Wrapper.args = {
|
102
|
-
label: 'CSF2 Wrapped Button',
|
103
|
-
};
|
104
|
-
ReactiveCSF2Wrapper.decorators = [
|
105
|
-
() => ({
|
106
|
-
template: `
|
107
|
-
<div style="border: 5px solid red;">
|
108
|
-
<story/>
|
109
|
-
</div>
|
110
|
-
`,
|
111
|
-
}),
|
112
|
-
];
|
113
|
-
|
114
|
-
ReactiveCSF2Wrapper.play = async ({ canvasElement, id }) => {
|
115
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
116
|
-
const canvas = within(canvasElement);
|
117
|
-
|
118
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
119
|
-
await new Promise((resolve) => {
|
120
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
121
|
-
});
|
122
|
-
const reactiveButton = await canvas.getByRole('button');
|
123
|
-
await expect(reactiveButton).toHaveTextContent('CSF2 Wrapped Button 0');
|
124
|
-
|
125
|
-
await userEvent.click(reactiveButton); // click to update the label to increment the count + 1
|
126
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
127
|
-
storyId: id,
|
128
|
-
updatedArgs: { label: 'updated CSF2 Wrapped Button' },
|
129
|
-
});
|
130
|
-
await new Promise((resolve) => {
|
131
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
132
|
-
});
|
133
|
-
await expect(canvas.getByRole('button')).toHaveTextContent('updated CSF2 Wrapped Button 1');
|
134
|
-
|
135
|
-
await userEvent.click(reactiveButton); // click to update the label to increment the count + 1
|
136
|
-
await expect(reactiveButton).toHaveTextContent('updated CSF2 Wrapped Button 2');
|
137
|
-
};
|
@@ -1,40 +0,0 @@
|
|
1
|
-
<template>
|
2
|
-
<button type="button" @click="onClick" :class="classes" :style="style">{{ label }} {{ counter }}</button>
|
3
|
-
</template>
|
4
|
-
|
5
|
-
<script>
|
6
|
-
import { computed, ref } from 'vue';
|
7
|
-
|
8
|
-
export default {
|
9
|
-
name: 'reactive-args',
|
10
|
-
|
11
|
-
props: {
|
12
|
-
label: {
|
13
|
-
type: String,
|
14
|
-
},
|
15
|
-
|
16
|
-
backgroundColor: {
|
17
|
-
type: String
|
18
|
-
},
|
19
|
-
},
|
20
|
-
|
21
|
-
setup(props, { emit }) {
|
22
|
-
const classes = {
|
23
|
-
'storybook-button': true,
|
24
|
-
'storybook-button--primary': true,
|
25
|
-
'storybook-button--large': true,
|
26
|
-
};
|
27
|
-
const style = computed(() => ({
|
28
|
-
backgroundColor: props.backgroundColor,
|
29
|
-
}));
|
30
|
-
const counter = ref(0);
|
31
|
-
const onClick = () => {
|
32
|
-
emit('click', 1);
|
33
|
-
counter.value += 1;
|
34
|
-
};
|
35
|
-
|
36
|
-
// Notice that `icon` prop component is still passed through even though it isn't mapped
|
37
|
-
return { classes, style, counter, onClick }
|
38
|
-
},
|
39
|
-
};
|
40
|
-
</script>
|
@@ -1,88 +0,0 @@
|
|
1
|
-
import { global as globalThis } from '@storybook/global';
|
2
|
-
import { userEvent, within } from '@storybook/testing-library';
|
3
|
-
import type { Meta, StoryObj } from '@storybook/vue3';
|
4
|
-
import { h } from 'vue';
|
5
|
-
import { RESET_STORY_ARGS, STORY_ARGS_UPDATED, UPDATE_STORY_ARGS } from '@storybook/core-events';
|
6
|
-
import Reactivity from './Reactivity.vue';
|
7
|
-
|
8
|
-
const meta = {
|
9
|
-
component: Reactivity,
|
10
|
-
argTypes: {
|
11
|
-
header: { control: { type: 'text' } },
|
12
|
-
footer: { control: { type: 'text' } },
|
13
|
-
default: { control: { type: 'text' } },
|
14
|
-
},
|
15
|
-
args: {
|
16
|
-
label: 'If you see this then the label arg was not reactive.',
|
17
|
-
default: 'If you see this then the default slot was not reactive.',
|
18
|
-
header: 'If you see this, the header slot was not reactive.', // this can be useless if you have custom render function that overrides the slot
|
19
|
-
footer: 'If you see this, the footer slot was not reactive.',
|
20
|
-
},
|
21
|
-
play: async ({ canvasElement, id, args }) => {
|
22
|
-
const channel = (globalThis as any).__STORYBOOK_ADDONS_CHANNEL__;
|
23
|
-
|
24
|
-
const canvas = within(canvasElement);
|
25
|
-
|
26
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
27
|
-
await new Promise((resolve) => channel.once(STORY_ARGS_UPDATED, resolve));
|
28
|
-
|
29
|
-
const input = await canvas.findByLabelText<HTMLInputElement>('Some input:');
|
30
|
-
await userEvent.type(input, 'value');
|
31
|
-
|
32
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
33
|
-
storyId: id,
|
34
|
-
updatedArgs: {
|
35
|
-
label: 'updated label',
|
36
|
-
header: 'updated header slot', // this can be useless if you have custom render function that overrides the slot which the case here
|
37
|
-
footer: 'updated footer slot',
|
38
|
-
default: 'updated default slot',
|
39
|
-
},
|
40
|
-
});
|
41
|
-
await new Promise((resolve) => channel.once(STORY_ARGS_UPDATED, resolve));
|
42
|
-
},
|
43
|
-
} satisfies Meta<typeof Reactivity>;
|
44
|
-
|
45
|
-
export default meta;
|
46
|
-
type Story = StoryObj<typeof meta>;
|
47
|
-
|
48
|
-
export const NoDecorators: Story = {};
|
49
|
-
|
50
|
-
export const DecoratorFunctionalComponent: Story = {
|
51
|
-
decorators: [
|
52
|
-
(storyFn, context) => {
|
53
|
-
const story = storyFn();
|
54
|
-
return () => h('div', [h('h2', ['Decorator not using args']), [h(story)]]);
|
55
|
-
},
|
56
|
-
],
|
57
|
-
};
|
58
|
-
|
59
|
-
export const DecoratorFunctionalComponentArgsFromContext: Story = {
|
60
|
-
decorators: [
|
61
|
-
(storyFn, context) => {
|
62
|
-
const story = storyFn();
|
63
|
-
return () =>
|
64
|
-
h('div', [h('h2', ['Decorator using args.label: ', context.args.label]), [h(story)]]);
|
65
|
-
},
|
66
|
-
],
|
67
|
-
};
|
68
|
-
|
69
|
-
export const DecoratorComponentOptions: Story = {
|
70
|
-
decorators: [
|
71
|
-
(storyFn, context) => {
|
72
|
-
return {
|
73
|
-
template: '<div><h2>Decorator not using args</h2><story/></div>',
|
74
|
-
};
|
75
|
-
},
|
76
|
-
],
|
77
|
-
};
|
78
|
-
|
79
|
-
export const DecoratorComponentOptionsArgsFromData: Story = {
|
80
|
-
decorators: [
|
81
|
-
(storyFn, context) => {
|
82
|
-
return {
|
83
|
-
data: () => ({ args: context.args }),
|
84
|
-
template: '<div><h2>Decorator using args.label: {{args.label}}</h2><story/></div>',
|
85
|
-
};
|
86
|
-
},
|
87
|
-
],
|
88
|
-
};
|
@@ -1,127 +0,0 @@
|
|
1
|
-
import { expect } from '@storybook/jest';
|
2
|
-
import { global as globalThis } from '@storybook/global';
|
3
|
-
import { within } from '@storybook/testing-library';
|
4
|
-
import { STORY_ARGS_UPDATED, RESET_STORY_ARGS, UPDATE_STORY_ARGS } from '@storybook/core-events';
|
5
|
-
import { h } from 'vue';
|
6
|
-
import type { Meta, StoryObj } from '@storybook/vue3';
|
7
|
-
import BaseLayout from './BaseLayout.vue';
|
8
|
-
|
9
|
-
const meta = {
|
10
|
-
component: BaseLayout,
|
11
|
-
args: {
|
12
|
-
label: 'Storybook Day',
|
13
|
-
default: () => 'Default Text Slot',
|
14
|
-
footer: h('p', 'Footer VNode Slot'),
|
15
|
-
},
|
16
|
-
tags: ['autodocs'],
|
17
|
-
} satisfies Meta<typeof BaseLayout>;
|
18
|
-
|
19
|
-
export default meta;
|
20
|
-
type Story = StoryObj<typeof meta>;
|
21
|
-
|
22
|
-
export const SimpleSlotTest: Story = {
|
23
|
-
args: {
|
24
|
-
label: 'Storybook Day',
|
25
|
-
header: () => h('h1', 'Header Text Slot'),
|
26
|
-
default: () => 'Default Text Slot',
|
27
|
-
footer: h('p', 'Footer VNode Slot'),
|
28
|
-
},
|
29
|
-
play: async ({ canvasElement, id }) => {
|
30
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
31
|
-
const canvas = within(canvasElement);
|
32
|
-
|
33
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
34
|
-
await new Promise((resolve) => {
|
35
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
36
|
-
});
|
37
|
-
await expect(canvas.getByTestId('footer-slot').innerText).toContain('Footer VNode Slot');
|
38
|
-
await expect(canvas.getByTestId('default-slot').innerText).toContain('Default Text Slot');
|
39
|
-
|
40
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
41
|
-
storyId: id,
|
42
|
-
updatedArgs: {
|
43
|
-
default: () => 'Default Text Slot Updated',
|
44
|
-
footer: h('p', 'Footer VNode Slot Updated'),
|
45
|
-
},
|
46
|
-
});
|
47
|
-
await new Promise((resolve) => {
|
48
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
49
|
-
});
|
50
|
-
await expect(canvas.getByTestId('default-slot').innerText).toContain(
|
51
|
-
'Default Text Slot Updated'
|
52
|
-
);
|
53
|
-
await expect(canvas.getByTestId('footer-slot').innerText).toContain(
|
54
|
-
'Footer VNode Slot Updated'
|
55
|
-
);
|
56
|
-
},
|
57
|
-
};
|
58
|
-
|
59
|
-
export const NamedSlotTest: Story = {
|
60
|
-
args: {
|
61
|
-
label: 'Storybook Day',
|
62
|
-
header: ({ title }: { title: string }) => h('h1', title),
|
63
|
-
default: () => 'Default Text Slot',
|
64
|
-
footer: h('p', 'Footer VNode Slot'),
|
65
|
-
},
|
66
|
-
// test that args are updated correctly in rective mode
|
67
|
-
play: async ({ canvasElement, id }) => {
|
68
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
69
|
-
const canvas = within(canvasElement);
|
70
|
-
|
71
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
72
|
-
await new Promise((resolve) => {
|
73
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
74
|
-
});
|
75
|
-
await expect(canvas.getByTestId('header-slot').innerText).toContain(
|
76
|
-
'Header title from the slot'
|
77
|
-
);
|
78
|
-
await expect(canvas.getByTestId('default-slot').innerText).toContain('Default Text Slot');
|
79
|
-
await expect(canvas.getByTestId('footer-slot').innerText).toContain('Footer VNode Slot');
|
80
|
-
|
81
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
82
|
-
storyId: id,
|
83
|
-
updatedArgs: {
|
84
|
-
default: () => 'Default Text Slot Updated',
|
85
|
-
footer: h('p', 'Footer VNode Slot Updated'),
|
86
|
-
},
|
87
|
-
});
|
88
|
-
await new Promise((resolve) => {
|
89
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
90
|
-
});
|
91
|
-
await expect(canvas.getByTestId('default-slot').innerText).toContain(
|
92
|
-
'Default Text Slot Updated'
|
93
|
-
);
|
94
|
-
await expect(canvas.getByTestId('footer-slot').innerText).toContain(
|
95
|
-
'Footer VNode Slot Updated'
|
96
|
-
);
|
97
|
-
},
|
98
|
-
};
|
99
|
-
|
100
|
-
export const SlotWithRenderFn: Story = {
|
101
|
-
args: {
|
102
|
-
label: 'Storybook Day',
|
103
|
-
header: ({ title }: { title: string }) => `${title}`,
|
104
|
-
default: () => 'Default Text Slot',
|
105
|
-
footer: h('p', 'Footer VNode Slot'),
|
106
|
-
},
|
107
|
-
render: (args) => ({
|
108
|
-
components: { BaseLayout },
|
109
|
-
setup() {
|
110
|
-
return { args };
|
111
|
-
},
|
112
|
-
template: `<BaseLayout :label="args.label" data-testid="layout">
|
113
|
-
{{args.default()}}
|
114
|
-
<template #header="{ title }"><h1>{{args.header({title})}}</h1></template>
|
115
|
-
</BaseLayout>`,
|
116
|
-
}),
|
117
|
-
play: async ({ canvasElement, id }) => {
|
118
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
119
|
-
const canvas = within(canvasElement);
|
120
|
-
|
121
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
122
|
-
await new Promise((resolve) => {
|
123
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
124
|
-
});
|
125
|
-
await expect(canvas.getByTestId('layout').innerText).toContain('Default Text Slot');
|
126
|
-
},
|
127
|
-
};
|
@@ -1,44 +0,0 @@
|
|
1
|
-
<script setup lang="ts">
|
2
|
-
defineProps<{ label: string }>();
|
3
|
-
</script>
|
4
|
-
<template>
|
5
|
-
<div style="padding: 20px;background-color: pink;">
|
6
|
-
<header data-testid="header-slot">
|
7
|
-
<slot name="header" title="Header title from the slot">
|
8
|
-
If you see this, the header slot was not reactive.
|
9
|
-
</slot>
|
10
|
-
</header>
|
11
|
-
<div id="content">
|
12
|
-
<label>
|
13
|
-
Some input:
|
14
|
-
<input style='width: 400px' placeholder='If you see this, an args update caused the input field to loose state' />
|
15
|
-
</label>
|
16
|
-
<hr>
|
17
|
-
<button class="storybook-button storybook-button--primary storybook-button--medium"> {{ label
|
18
|
-
}}</button>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<main data-testid="default-slot">
|
22
|
-
<slot>Default slot placeholder</slot>
|
23
|
-
</main>
|
24
|
-
<footer data-testid="footer-slot">
|
25
|
-
<slot name="footer">
|
26
|
-
Footer slot placeholder
|
27
|
-
</slot>
|
28
|
-
</footer>
|
29
|
-
</div>
|
30
|
-
</template>
|
31
|
-
|
32
|
-
<style>
|
33
|
-
header,
|
34
|
-
footer {
|
35
|
-
background-color: #fff0ff;
|
36
|
-
padding: 20px;
|
37
|
-
}
|
38
|
-
|
39
|
-
main,
|
40
|
-
#content {
|
41
|
-
background-color: #f0f0f0;
|
42
|
-
padding: 20px;
|
43
|
-
}
|
44
|
-
</style>
|
@@ -1,81 +0,0 @@
|
|
1
|
-
import { expect } from '@storybook/jest';
|
2
|
-
import { global as globalThis } from '@storybook/global';
|
3
|
-
import type { Channel } from '@storybook/channels';
|
4
|
-
import { within } from '@storybook/testing-library';
|
5
|
-
import { UPDATE_STORY_ARGS, STORY_ARGS_UPDATED, RESET_STORY_ARGS } from '@storybook/core-events';
|
6
|
-
|
7
|
-
import type { Meta, StoryObj } from '@storybook/vue3';
|
8
|
-
import MySlotComponent from './MySlotComponent.vue';
|
9
|
-
|
10
|
-
declare global {
|
11
|
-
// eslint-disable-next-line no-var,vars-on-top,@typescript-eslint/naming-convention
|
12
|
-
var __STORYBOOK_ADDONS_CHANNEL__: Channel;
|
13
|
-
}
|
14
|
-
|
15
|
-
const meta = {
|
16
|
-
component: MySlotComponent,
|
17
|
-
args: {
|
18
|
-
label: 'Storybook Day',
|
19
|
-
year: 2022,
|
20
|
-
default: ({ text, year }) => `${text}, ${year}`,
|
21
|
-
},
|
22
|
-
tags: ['autodocs'],
|
23
|
-
} satisfies Meta<typeof MySlotComponent>;
|
24
|
-
|
25
|
-
export default meta;
|
26
|
-
type Story = StoryObj<typeof meta>;
|
27
|
-
|
28
|
-
export const Basic: Story = {
|
29
|
-
// test that args are updated correctly in reactive mode
|
30
|
-
play: async ({ canvasElement, id }) => {
|
31
|
-
const channel = globalThis.__STORYBOOK_ADDONS_CHANNEL__;
|
32
|
-
const canvas = within(canvasElement);
|
33
|
-
|
34
|
-
await channel.emit(RESET_STORY_ARGS, { storyId: id });
|
35
|
-
await new Promise((resolve) => channel.once(STORY_ARGS_UPDATED, resolve));
|
36
|
-
await expect(canvas.getByTestId('scoped-slot').innerText).toMatch(
|
37
|
-
'Hello Storybook Day from the slot, 2022'
|
38
|
-
);
|
39
|
-
|
40
|
-
await channel.emit(UPDATE_STORY_ARGS, {
|
41
|
-
storyId: id,
|
42
|
-
updatedArgs: {
|
43
|
-
label: 'Storybook Day updated',
|
44
|
-
year: 2023,
|
45
|
-
},
|
46
|
-
});
|
47
|
-
await new Promise((resolve) => {
|
48
|
-
channel.once(STORY_ARGS_UPDATED, resolve);
|
49
|
-
});
|
50
|
-
|
51
|
-
await expect(canvas.getByTestId('scoped-slot').innerText).toMatch(
|
52
|
-
'Hello Storybook Day updated from the slot, 2023'
|
53
|
-
);
|
54
|
-
},
|
55
|
-
};
|
56
|
-
|
57
|
-
export const CustomRender: Story = {
|
58
|
-
render: (args) => ({
|
59
|
-
components: { MySlotComponent },
|
60
|
-
setup() {
|
61
|
-
return { args };
|
62
|
-
},
|
63
|
-
template: `<MySlotComponent v-bind="args" v-slot="slotProps">
|
64
|
-
{{ slotProps.text }}, {{ slotProps.year }}
|
65
|
-
</MySlotComponent>`,
|
66
|
-
}),
|
67
|
-
play: Basic.play,
|
68
|
-
};
|
69
|
-
|
70
|
-
export const CustomRenderUsingFunctionSlot: Story = {
|
71
|
-
render: (args: any) => ({
|
72
|
-
components: { MySlotComponent },
|
73
|
-
setup() {
|
74
|
-
return { args };
|
75
|
-
},
|
76
|
-
template: `<MySlotComponent v-bind="args" v-slot="slotProps">
|
77
|
-
{{args.default(slotProps)}}
|
78
|
-
</MySlotComponent>`,
|
79
|
-
}),
|
80
|
-
play: Basic.play,
|
81
|
-
};
|
@@ -1,46 +0,0 @@
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/vue3';
|
2
|
-
|
3
|
-
import GlobalUsage from './GlobalUsage.vue';
|
4
|
-
import GlobalSetup from './GlobalSetup.vue';
|
5
|
-
|
6
|
-
const meta: Meta = {
|
7
|
-
component: GlobalUsage,
|
8
|
-
argTypes: {},
|
9
|
-
tags: ['autodocs'],
|
10
|
-
} satisfies Meta<typeof GlobalUsage>;
|
11
|
-
|
12
|
-
export default meta;
|
13
|
-
type Story = StoryObj<typeof meta>;
|
14
|
-
|
15
|
-
export const MultiComponents: Story = {
|
16
|
-
args: {
|
17
|
-
label: 'Button',
|
18
|
-
size: 'large',
|
19
|
-
backgroundColor: '#aa00ff',
|
20
|
-
btn1Args: { label: 'Button 10', size: 'small', backgroundColor: '#aa00ff' },
|
21
|
-
},
|
22
|
-
render(args: any) {
|
23
|
-
return {
|
24
|
-
components: { GlobalUsage, GlobalSetup },
|
25
|
-
setup() {
|
26
|
-
return { args };
|
27
|
-
},
|
28
|
-
template: `<div style="background-color:pink;opacity:0.9;padding:20px" >
|
29
|
-
|
30
|
-
<div style="display:flex;gap:10px">
|
31
|
-
<img src="https://user-images.githubusercontent.com/263385/199832481-bbbf5961-6a26-481d-8224-51258cce9b33.png" width="200" />
|
32
|
-
<GlobalUsage v-bind="args.btn1Args" />
|
33
|
-
</div>
|
34
|
-
<h2>Complex Story Custom template </h2> <br/> <hr/>
|
35
|
-
|
36
|
-
<GlobalSetup :label="args.label" />
|
37
|
-
<div style="margin:8px"><span style="font-size:28px;color:green">Multiple </span>
|
38
|
-
<span style="background-color:magenta;opacity:0.9;padding:8px"><i>Components</i></span></div>
|
39
|
-
<div style="display:flex;gap:10px">
|
40
|
-
<GlobalUsage v-bind="args" />
|
41
|
-
<GlobalUsage label="Static Label Dynamic color" :background-color="args.backgroundColor"/>
|
42
|
-
</div>
|
43
|
-
</div>`,
|
44
|
-
};
|
45
|
-
},
|
46
|
-
};
|