Skip to content

Commit ca3ff3f

Browse files
committed
docs(ui): add ButtonGroup stories to storybook
1 parent 51ecbc7 commit ca3ff3f

11 files changed

Lines changed: 264 additions & 121 deletions

File tree

.storybook/main.ts

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import type { StorybookConfig } from '@storybook-vue/nuxt'
22

33
const config = {
44
stories: ['../app/**/*.stories.@(js|ts)'],
5-
addons: ['@storybook/addon-a11y', '@storybook/addon-docs', '@storybook/addon-themes'],
5+
addons: [
6+
'@storybook/addon-a11y',
7+
'@storybook/addon-docs',
8+
'@storybook/addon-themes',
9+
'storybook-i18n',
10+
],
611
framework: '@storybook-vue/nuxt',
712
staticDirs: ['./.public'],
813
features: {
@@ -19,34 +24,6 @@ const config = {
1924
}
2025
},
2126
})
22-
// Replace the built-in vue-docgen plugin with a fault-tolerant version.
23-
// vue-docgen-api can crash on components that import types from other
24-
// .vue files (it tries to parse the SFC with @babel/parser as plain TS).
25-
// This wrapper catches those errors so the build doesn't fail.
26-
const docgenPlugin = config.plugins?.find(
27-
(p): p is Extract<typeof p, { name: string }> =>
28-
!!p && typeof p === 'object' && 'name' in p && p.name === 'storybook:vue-docgen-plugin',
29-
)
30-
31-
if (docgenPlugin && 'transform' in docgenPlugin) {
32-
const hook = docgenPlugin.transform
33-
// Vite plugin hooks can be a function or an object with a `handler` property
34-
const originalFn = typeof hook === 'function' ? hook : hook?.handler
35-
if (originalFn) {
36-
const wrapped = async function (this: unknown, ...args: unknown[]) {
37-
try {
38-
return await originalFn.apply(this, args)
39-
} catch {
40-
return undefined
41-
}
42-
}
43-
if (typeof hook === 'function') {
44-
docgenPlugin.transform = wrapped as typeof hook
45-
} else if (hook) {
46-
hook.handler = wrapped as typeof hook.handler
47-
}
48-
}
49-
}
5027

5128
return config
5229
},

.storybook/manager.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { addons } from 'storybook/manager-api'
2-
import { create } from 'storybook/theming'
3-
4-
const npmxTheme = create({
5-
brandTitle: 'npmx Storybook',
6-
brandImage: '/npmx-storybook.svg',
7-
})
2+
import npmxDark from './theme'
83

94
addons.setConfig({
10-
theme: npmxTheme,
5+
theme: npmxDark,
116
})

.storybook/preview-head.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<style>
2+
/* Override docs story canvas background to match npmx theme */
3+
.docs-story {
4+
background-color: var(--bg, oklch(0.171 0 0)) !important;
5+
}
6+
</style>

.storybook/preview.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import type { Preview } from '@storybook-vue/nuxt'
22
import { withThemeByDataAttribute } from '@storybook/addon-themes'
3+
import { addons } from 'storybook/preview-api'
34
import { currentLocales } from '../config/i18n'
45
import { fn } from 'storybook/test'
56
import { ACCENT_COLORS } from '../shared/utils/constants'
7+
import npmxDark from './theme'
68

79
// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
810
// Stub Nuxt specific globals
@@ -25,25 +27,22 @@ const preview: Preview = {
2527
date: /Date$/i,
2628
},
2729
},
30+
docs: {
31+
theme: npmxDark,
32+
},
33+
},
34+
initialGlobals: {
35+
locale: 'en-US',
36+
locales: currentLocales.reduce(
37+
(acc, locale) => {
38+
acc[locale.code] = locale.name
39+
return acc
40+
},
41+
{} as Record<string, string>,
42+
),
2843
},
2944
// Provides toolbars to switch things like theming and language
3045
globalTypes: {
31-
locale: {
32-
name: 'Locale',
33-
description: 'UI language',
34-
defaultValue: 'en-US',
35-
toolbar: {
36-
icon: 'globe',
37-
dynamicTitle: true,
38-
items: [
39-
// English is at the top so it's easier to reset to it
40-
{ value: 'en-US', title: 'English (US)' },
41-
...currentLocales
42-
.filter(locale => locale.code !== 'en-US')
43-
.map(locale => ({ value: locale.code, title: locale.name })),
44-
],
45-
},
46-
},
4746
accentColor: {
4847
name: 'Accent Color',
4948
description: 'Accent color',
@@ -70,9 +69,9 @@ const preview: Preview = {
7069
attributeName: 'data-theme',
7170
}),
7271
(story, context) => {
73-
const { locale, accentColor } = context.globals as {
74-
locale: string
72+
const { accentColor, locale } = context.globals as {
7573
accentColor?: string
74+
locale?: string
7675
}
7776

7877
// Set accent color from globals
@@ -82,16 +81,24 @@ const preview: Preview = {
8281
document.documentElement.style.removeProperty('--accent-color')
8382
}
8483

84+
// Store reference to i18n instance for locale changes
85+
let i18nInstance: any = null
86+
87+
// Subscribe to locale changes from storybook-i18n addon
88+
addons.getChannel().on('LOCALE_CHANGED', (newLocale: string) => {
89+
if (i18nInstance) {
90+
i18nInstance.setLocale(newLocale)
91+
}
92+
})
93+
8594
return {
8695
template: '<story />',
87-
// Set locale from globals
8896
created() {
89-
if (this.$i18n) {
90-
this.$i18n.setLocale(locale)
91-
}
92-
},
93-
updated() {
94-
if (this.$i18n) {
97+
// Store i18n instance for LOCALE_CHANGED events
98+
i18nInstance = this.$i18n
99+
100+
// Set initial locale when component is created
101+
if (locale && this.$i18n) {
95102
this.$i18n.setLocale(locale)
96103
}
97104
},

.storybook/theme.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { create } from 'storybook/theming/create'
2+
3+
export const npmxDark = create({
4+
base: 'dark',
5+
6+
brandTitle: 'npmx Storybook',
7+
brandImage: '/npmx-storybook.svg',
8+
9+
// UI
10+
appContentBg: '#101010', // oklch(0.171 0 0)
11+
})
12+
13+
export default npmxDark

app/components/Button/Base.stories.ts

Lines changed: 0 additions & 60 deletions
This file was deleted.

app/components/Button/Base.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
<script setup lang="ts">
22
import type { IconClass } from '~/types'
33
4+
/**
5+
* A base button component that supports multiple variants, sizes, and states as well as icons and keyboard shortcuts.
6+
*/
7+
defineOptions({
8+
name: 'ButtonBase',
9+
})
10+
411
const props = withDefaults(
512
defineProps<{
613
disabled?: boolean

0 commit comments

Comments
 (0)