Skip to content

Commit 27b0461

Browse files
authored
Merge branch 'main' into optimize-searching-page-ux
2 parents 5e80824 + 5658f1a commit 27b0461

File tree

180 files changed

+7187
-1711
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+7187
-1711
lines changed

.github/workflows/chromatic.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
run: pnpm install
3838

3939
- name: 🧪 Run Chromatic Visual and Accessibility Tests
40-
uses: chromaui/action@0794e6939fe40ce46a88963f818092afc427da5b # v15.3.0
40+
uses: chromaui/action@f191a0224b10e1a38b2091cefb7b7a2337009116 # v16.0.0
4141
env:
4242
CHROMATIC_BRANCH: ${{ github.event.pull_request.head.ref || github.ref_name }}
4343
CHROMATIC_SHA: ${{ github.event.pull_request.head.sha || github.sha }}

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,14 @@ jobs:
111111
run: pnpm vp test --project nuxt --coverage --reporter=default --reporter=junit --outputFile=test-report.junit.xml
112112

113113
- name: ⬆︎ Upload coverage reports to Codecov
114-
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5
114+
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
115115
with:
116116
report_type: test_results
117117
env:
118118
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
119119

120120
- name: ⬆︎ Upload coverage reports to Codecov
121-
uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5
121+
uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
122122
env:
123123
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
124124

.storybook/main.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import type { StorybookConfig } from '@storybook-vue/nuxt'
22

33
const config = {
4-
stories: ['../app/**/*.stories.@(js|ts)'],
5-
addons: ['@storybook/addon-a11y', '@storybook/addon-docs', '@storybook/addon-themes'],
4+
stories: ['../.storybook/*.mdx', '../app/**/*.stories.@(js|ts)'],
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: {
@@ -11,6 +16,33 @@ const config = {
1116
async viteFinal(newConfig) {
1217
newConfig.plugins ??= []
1318

19+
// Bridge compatibility between Storybook v10 core and v9 @storybook-vue/nuxt
20+
// v10 expects module federation globals that v9 doesn't provide
21+
newConfig.plugins.push({
22+
name: 'storybook-v10-compat',
23+
transformIndexHtml: {
24+
order: 'pre',
25+
handler(html) {
26+
const script = `
27+
<script>
28+
// Minimal shims for Storybook v10 module federation system
29+
// These will be replaced when Storybook runtime loads
30+
window.__STORYBOOK_MODULE_GLOBAL__ = { global: window };
31+
window.__STORYBOOK_MODULE_CLIENT_LOGGER__ = {
32+
deprecate: console.warn.bind(console, '[deprecated]'),
33+
once: console.log.bind(console),
34+
logger: console
35+
};
36+
window.__STORYBOOK_MODULE_CHANNELS__ = {
37+
Channel: class { on() {} off() {} emit() {} once() {} },
38+
createBrowserChannel: () => new window.__STORYBOOK_MODULE_CHANNELS__.Channel()
39+
};
40+
</script>`
41+
return html.replace(/<script>/, script + '<script>')
42+
},
43+
},
44+
})
45+
1446
newConfig.plugins.push({
1547
name: 'ignore-internals',
1648
transform(_, id) {

.storybook/manager.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import { addons } from 'storybook/manager-api'
2-
import { create } from 'storybook/theming'
32

4-
const npmxTheme = create({
5-
brandTitle: 'npmx Storybook',
6-
brandImage: '/npmx-storybook.svg',
7-
})
3+
import npmxDark from './theme'
84

95
addons.setConfig({
10-
theme: npmxTheme,
6+
theme: npmxDark,
7+
layoutCustomisations: {
8+
showToolbar: (state, defaultValue) => {
9+
if (state.viewMode === 'docs' && state.storyId) {
10+
const story = state.index?.[state.storyId]
11+
const tags = story?.tags || []
12+
if (tags.includes('hide-toolbar')) {
13+
return false
14+
}
15+
}
16+
return defaultValue
17+
},
18+
},
1119
})

.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: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
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'
67

8+
import npmxDark from './theme'
9+
710
// related: https://github.com/npmx-dev/npmx.dev/blob/1431d24be555bca5e1ae6264434d49ca15173c43/test/nuxt/setup.ts#L12-L26
811
// Stub Nuxt specific globals
912
// @ts-expect-error - dynamic global name
@@ -17,6 +20,12 @@ globalThis['__NUXT_COLOR_MODE__'] ??= {
1720
// @ts-expect-error - dynamic global name
1821
globalThis.defineOgImageComponent = fn()
1922

23+
// Subscribe to locale changes from storybook-i18n addon (once, outside decorator)
24+
let currentI18nInstance: any = null
25+
addons.getChannel().on('LOCALE_CHANGED', (newLocale: string) => {
26+
currentI18nInstance?.setLocale(newLocale)
27+
})
28+
2029
const preview: Preview = {
2130
parameters: {
2231
controls: {
@@ -25,25 +34,22 @@ const preview: Preview = {
2534
date: /Date$/i,
2635
},
2736
},
37+
docs: {
38+
theme: npmxDark,
39+
},
40+
},
41+
initialGlobals: {
42+
locale: 'en-US',
43+
locales: currentLocales.reduce(
44+
(acc, locale) => {
45+
acc[locale.code] = locale.name
46+
return acc
47+
},
48+
{} as Record<string, string>,
49+
),
2850
},
2951
// Provides toolbars to switch things like theming and language
3052
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-
},
4753
accentColor: {
4854
name: 'Accent Color',
4955
description: 'Accent color',
@@ -70,9 +76,9 @@ const preview: Preview = {
7076
attributeName: 'data-theme',
7177
}),
7278
(story, context) => {
73-
const { locale, accentColor } = context.globals as {
74-
locale: string
79+
const { accentColor, locale } = context.globals as {
7580
accentColor?: string
81+
locale?: string
7682
}
7783

7884
// Set accent color from globals
@@ -84,14 +90,12 @@ const preview: Preview = {
8490

8591
return {
8692
template: '<story />',
87-
// Set locale from globals
8893
created() {
89-
if (this.$i18n) {
90-
this.$i18n.setLocale(locale)
91-
}
92-
},
93-
updated() {
94-
if (this.$i18n) {
94+
// Store i18n instance for LOCALE_CHANGED events
95+
currentI18nInstance = this.$i18n
96+
97+
// Set initial locale when component is created
98+
if (locale && this.$i18n) {
9599
this.$i18n.setLocale(locale)
96100
}
97101
},

.storybook/storybook-welcome.mdx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Meta } from '@storybook/addon-docs/blocks';
2+
3+
<Meta title="Welcome" tags={['hide-toolbar']}/>
4+
5+
# Welcome
6+
7+
Welcome to the npmx Storybook.

.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'
2+
3+
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

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"editor.formatOnSave": true,
44
"i18n-ally.keystyle": "nested",
55
"i18n-ally.localesPaths": ["./i18n/locales"],
6-
"typescript.tsdk": "node_modules/typescript/lib",
6+
"js/ts.tsdk.path": "node_modules/typescript/lib",
77
"explorer.fileNesting.enabled": true,
88
"explorer.fileNesting.patterns": {
99
"*.vue": "${capture}.stories.ts"

CONTRIBUTING.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,23 @@ pnpm test:browser:ui # Run with Playwright UI
752752

753753
Make sure to read about [Playwright best practices](https://playwright.dev/docs/best-practices) and don't rely on classes/IDs but try to follow user-replicable behaviour (like selecting an element based on text content instead).
754754

755+
#### Updating snapshots
756+
757+
Some tests use image snapshots that must match the CI environment (Linux). If you need to update them, and aren't running Linux, you can use Docker to run in the same environment:
758+
759+
```bash
760+
docker run --rm \
761+
-e CI=true \
762+
-e NODE_OPTIONS="--max-old-space-size=4096" \
763+
-v $(pwd):/work \
764+
-w /work \
765+
mcr.microsoft.com/playwright:v1.58.2-noble \
766+
sh -c "npm install -g pnpm && pnpm install && pnpm vp run build:test && pnpm vp run test:browser:prebuilt --update-snapshots"
767+
```
768+
769+
> [!NOTE]
770+
> If the build runs out of memory, increase `--max-old-space-size` to `8192`.
771+
755772
### Test fixtures (mocking external APIs)
756773

757774
E2E tests use a fixture system to mock external API requests, ensuring tests are deterministic and don't hit real APIs. This is handled at two levels:

0 commit comments

Comments
 (0)