Skip to content

Commit bece123

Browse files
committed
Merge pull request #2 from sacrosanctic/improved-storybook-setup
Improve Storybook setup
1 parent f2fa20f commit bece123

19 files changed

Lines changed: 572 additions & 7 deletions
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2+
import AppFooter from './AppFooter.vue'
3+
4+
const meta = {
5+
component: AppFooter,
6+
parameters: {
7+
layout: 'fullscreen',
8+
},
9+
globals: {
10+
viewport: { value: undefined },
11+
},
12+
} satisfies Meta<typeof AppFooter>
13+
14+
export default meta
15+
type Story = StoryObj<typeof meta>
16+
17+
export const Default: Story = {}
18+
19+
export const InContext: Story = {
20+
render: () => ({
21+
components: { AppFooter },
22+
template: `
23+
<div style="display: flex; flex-direction: column; min-height: 100vh;">
24+
<div style="flex: 1; padding: 2rem;">
25+
<h1>Some page content</h1>
26+
<span>See footer at the bottom</span>
27+
</div>
28+
<AppFooter />
29+
</div>
30+
`,
31+
}),
32+
}
33+
34+
export const InLongPage: Story = {
35+
render: () => ({
36+
components: { AppFooter },
37+
template: `
38+
<div style="display: flex; flex-direction: column; min-height: 100vh;">
39+
<div style="flex: 1; padding: 2rem;">
40+
<h1>Footer is all the way at the bottom!</h1> <br />
41+
${Array.from({ length: 50 }, (_, i) => `<p key="${i}">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>`).join('')}
42+
</div>
43+
<AppFooter />
44+
</div>
45+
`,
46+
}),
47+
}
48+
49+
export const MobileView: Story = {
50+
...InContext,
51+
globals: {
52+
viewport: { value: 'mobile1' },
53+
},
54+
}
55+
56+
export const TabletView: Story = {
57+
...InContext,
58+
globals: {
59+
viewport: { value: 'tablet' },
60+
},
61+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2+
import AppHeader from './AppHeader.vue'
3+
4+
const meta = {
5+
component: AppHeader,
6+
parameters: {
7+
layout: 'fullscreen',
8+
},
9+
globals: {
10+
viewport: { value: undefined },
11+
},
12+
} satisfies Meta<typeof AppHeader>
13+
14+
export default meta
15+
16+
export const Default: StoryObj<typeof AppHeader> = {}
17+
18+
export const Mobile: StoryObj<typeof AppHeader> = {
19+
globals: {
20+
viewport: { value: 'mobile1' },
21+
},
22+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2+
import ButtonBase from './Base.vue'
3+
4+
const meta = {
5+
component: ButtonBase,
6+
tags: ['autodocs'],
7+
} satisfies Meta<typeof ButtonBase>
8+
9+
export default meta
10+
type Story = StoryObj<typeof meta>
11+
12+
export const Primary: Story = {
13+
args: {
14+
variant: 'primary',
15+
size: 'medium',
16+
},
17+
render: args => ({
18+
components: { ButtonBase },
19+
setup() {
20+
return { args }
21+
},
22+
template: '<ButtonBase v-bind="args">Primary Button</ButtonBase>',
23+
}),
24+
}
25+
26+
export const Secondary: Story = {
27+
args: {
28+
variant: 'secondary',
29+
size: 'medium',
30+
},
31+
render: args => ({
32+
components: { ButtonBase },
33+
setup() {
34+
return { args }
35+
},
36+
template: '<ButtonBase v-bind="args">Secondary Button</ButtonBase>',
37+
}),
38+
}
39+
40+
export const Small: Story = {
41+
args: {
42+
variant: 'secondary',
43+
size: 'small',
44+
},
45+
render: args => ({
46+
components: { ButtonBase },
47+
setup() {
48+
return { args }
49+
},
50+
template: '<ButtonBase v-bind="args">Small Button</ButtonBase>',
51+
}),
52+
}
53+
54+
export const Disabled: Story = {
55+
args: {
56+
variant: 'primary',
57+
size: 'medium',
58+
disabled: true,
59+
},
60+
render: args => ({
61+
components: { ButtonBase },
62+
setup() {
63+
return { args }
64+
},
65+
template: '<ButtonBase v-bind="args">Disabled Button</ButtonBase>',
66+
}),
67+
}
68+
69+
export const WithIcon: Story = {
70+
args: {
71+
variant: 'secondary',
72+
size: 'medium',
73+
classicon: 'i-carbon:search',
74+
},
75+
render: args => ({
76+
components: { ButtonBase },
77+
setup() {
78+
return { args }
79+
},
80+
template: '<ButtonBase v-bind="args">Search</ButtonBase>',
81+
}),
82+
}
83+
84+
export const WithKeyboardShortcut: Story = {
85+
args: {
86+
variant: 'secondary',
87+
size: 'medium',
88+
ariaKeyshortcuts: '/',
89+
},
90+
render: args => ({
91+
components: { ButtonBase },
92+
setup() {
93+
return { args }
94+
},
95+
template: '<ButtonBase v-bind="args">Search</ButtonBase>',
96+
}),
97+
}
98+
99+
export const Block: Story = {
100+
args: {
101+
variant: 'primary',
102+
size: 'medium',
103+
block: true,
104+
},
105+
render: args => ({
106+
components: { ButtonBase },
107+
setup() {
108+
return { args }
109+
},
110+
template: '<ButtonBase v-bind="args">Full Width Button</ButtonBase>',
111+
}),
112+
}

app/components/Button/Base.vue

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,36 @@
11
<script setup lang="ts">
22
const props = withDefaults(
33
defineProps<{
4+
/**
5+
* Whether the button is disabled
6+
*/
47
disabled?: boolean
8+
/**
9+
* HTML button type attribute
10+
* @default "button"
11+
*/
512
type?: 'button' | 'submit'
13+
/**
14+
* Button visual style variant
15+
* @default "secondary"
16+
*/
617
variant?: 'primary' | 'secondary'
18+
/**
19+
* Button size
20+
* @default "medium"
21+
*/
722
size?: 'small' | 'medium'
23+
/**
24+
* Keyboard shortcut hint
25+
*/
826
ariaKeyshortcuts?: string
27+
/**
28+
* Whether the button should take full width
29+
*/
930
block?: boolean
10-
31+
/**
32+
* Icon class (e.g., i-carbon-add)
33+
*/
1134
classicon?: string
1235
}>(),
1336
{
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2+
import FileTree from './FileTree.vue'
3+
4+
export default {
5+
component: FileTree,
6+
} satisfies Meta<typeof FileTree>
7+
8+
export const Default: StoryObj<typeof FileTree> = {
9+
args: {
10+
tree: [
11+
{
12+
name: 'assets',
13+
path: 'assets',
14+
type: 'directory',
15+
children: [
16+
{
17+
name: 'favicon.svg',
18+
path: 'assets/browser/favicon.svg',
19+
type: 'file',
20+
size: 2163,
21+
},
22+
],
23+
},
24+
{
25+
name: 'dist',
26+
path: 'dist',
27+
type: 'directory',
28+
children: [
29+
{
30+
name: 'bin',
31+
path: 'dist/bin',
32+
type: 'directory',
33+
children: [
34+
{
35+
name: 'core.js',
36+
path: 'dist/bin/core.js',
37+
type: 'file',
38+
size: 126956,
39+
},
40+
{
41+
name: 'dispatcher.js',
42+
path: 'dist/bin/dispatcher.js',
43+
type: 'file',
44+
size: 2788,
45+
},
46+
{
47+
name: 'loader.js',
48+
path: 'dist/bin/loader.js',
49+
type: 'file',
50+
size: 3600,
51+
},
52+
],
53+
},
54+
{
55+
name: 'types',
56+
path: 'dist/types',
57+
type: 'directory',
58+
children: [
59+
{
60+
name: 'index.d.ts',
61+
path: 'dist/types/index.d.ts',
62+
type: 'file',
63+
size: 127300,
64+
},
65+
{
66+
name: 'index.js',
67+
path: 'dist/types/index.js',
68+
type: 'file',
69+
size: 3381,
70+
},
71+
],
72+
},
73+
],
74+
},
75+
{
76+
name: 'package.json',
77+
path: 'package.json',
78+
type: 'file',
79+
size: 11104,
80+
},
81+
{
82+
name: 'README.md',
83+
path: 'README.md',
84+
type: 'file',
85+
size: 1606,
86+
},
87+
],
88+
currentPath: '',
89+
baseUrl: '/package-code/foo/v/10.2.8',
90+
basePath: ['foo', 'v', '10.2.8'],
91+
},
92+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2+
import PackageSelector from './PackageSelector.vue'
3+
4+
const meta = {
5+
component: PackageSelector,
6+
} satisfies Meta<typeof PackageSelector>
7+
8+
export default meta
9+
type Story = StoryObj<typeof meta>
10+
11+
export const Default: Story = {}

app/components/Input/Base.stories.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2-
import { expect, fn, userEvent, within } from '@storybook/test'
2+
import { expect, fn, userEvent, within } from 'storybook/test'
33
import Component from './Base.vue'
44

55
const meta = {
@@ -76,8 +76,7 @@ export const NoCorrect: Story = {
7676
args: {
7777
noCorrect: true,
7878
},
79-
play: async ({ canvasElement }) => {
80-
const canvas = within(canvasElement)
79+
play: async ({ canvas }) => {
8180
const input = canvas.getByRole('textbox')
8281

8382
await expect(input).toHaveAttribute('autocapitalize', 'off')

app/components/LicenseDisplay.stories.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import Component from './LicenseDisplay.vue'
33

44
const meta = {
55
component: Component,
6-
tags: ['autodocs'],
76
argTypes: {
87
license: {
98
control: { type: 'text' },
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { Meta, StoryObj } from '@nuxtjs/storybook'
2+
import LoadingSpinner from './LoadingSpinner.vue'
3+
4+
const meta = {
5+
component: LoadingSpinner,
6+
} satisfies Meta<typeof LoadingSpinner>
7+
8+
export default meta
9+
type Story = StoryObj<typeof meta>
10+
11+
export const Default: Story = {}
12+
13+
export const WithCustomText: Story = {
14+
args: {
15+
text: 'Loading packages...',
16+
},
17+
}

0 commit comments

Comments
 (0)