Skip to content

Commit a8b22f9

Browse files
committed
feat: improve stories
1 parent b187bc0 commit a8b22f9

File tree

6 files changed

+81
-45
lines changed

6 files changed

+81
-45
lines changed

.storybook/locales/langs/en-US.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
const enUS = {
2+
'storybook.stories.Backgrounds.light': 'Light Mode',
3+
'storybook.stories.Backgrounds.dark': 'Dark Mode',
24
'storybook.stories.BreakLines.args.value': 'First line\nSecond line\nThird line',
35
'storybook.stories.ColumnSetting.columns.name': 'Name',
46
'storybook.stories.ColumnSetting.columns.id': 'ID',

.storybook/locales/langs/zh-CN.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
const zhCN = {
2+
'storybook.stories.Backgrounds.light': '浅色模式',
3+
'storybook.stories.Backgrounds.dark': '深色模式',
24
'storybook.stories.BreakLines.args.value': '第一行\n第二行\n第三行',
35
'storybook.stories.ColumnSetting.columns.name': '姓名',
46
'storybook.stories.ColumnSetting.columns.id': 'ID',

.storybook/manager.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { addons } from 'storybook/manager-api';
2-
import { create } from 'storybook/theming';
2+
import { create, type ThemeVars } from 'storybook/theming';
3+
import { getGlobalValueFromUrl } from './utils/global';
34

45
// import './manager.css';
56

7+
const globalValue = getGlobalValueFromUrl('backgrounds.value');
68
const isPreferDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
79
addons.setConfig({
810
theme: create({
9-
base: isPreferDark ? 'dark' : 'light',
11+
base: (globalValue as ThemeVars['base']) ?? (isPreferDark ? 'dark' : 'light'),
1012
brandTitle: '@tiny-codes/react-easy',
1113
}),
1214
// navSize: 300,

.storybook/preview.tsx

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { type ComponentType, type PropsWithChildren, useMemo } from 'react';
1+
import { type ComponentType, type PropsWithChildren, useMemo, useState } from 'react';
22
import { type Control, DocsContainer, type DocsContainerProps } from '@storybook/addon-docs/blocks';
33
import type { Preview, ReactRenderer } from '@storybook/react-vite';
4-
import { App as AntdApp, ConfigProvider as AntdConfigProvider, theme } from 'antd';
4+
import { App as AntdApp, ConfigProvider as AntdConfigProvider, theme as antThemes } from 'antd';
55
import enUS from 'antd/es/locale/en_US';
66
import zhCN from 'antd/es/locale/zh_CN';
77
import { FORCE_RE_RENDER } from 'storybook/internal/core-events';
@@ -10,14 +10,37 @@ import { addons, useStoryContext } from 'storybook/preview-api';
1010
import { themes } from 'storybook/theming';
1111
import ConfigProvider from '../src/components/ConfigProvider';
1212
import { useRefValue } from '../src/hooks';
13-
import storyI18n from './locales';
13+
import type { Langs } from '../src/locales';
14+
import storyI18n, { storyT } from './locales';
15+
import { getGlobalValueFromUrl } from './utils/global';
1416
import { inferControlFromDocgenType, standardizeJsDocDefaultValue } from './utils/jsdoc';
1517

1618
// import './preview.css';
1719

20+
const themeFromUrl = getGlobalValueFromUrl('backgrounds.value');
21+
const langFromUrl = getGlobalValueFromUrl('lang');
1822
const isPreferDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
1923

2024
const preview: Preview = {
25+
initialGlobals: {
26+
lang: 'en-US',
27+
backgrounds: {
28+
value: themeFromUrl ?? (isPreferDark ? 'dark' : 'light'),
29+
grid: false,
30+
},
31+
},
32+
globalTypes: {
33+
lang: {
34+
description: 'Internationalization locale',
35+
toolbar: {
36+
icon: 'globe',
37+
items: [
38+
{ value: 'en-US', right: '🇺🇸', title: 'English' },
39+
{ value: 'zh-CN', right: '🇨🇳', title: '中文' },
40+
],
41+
},
42+
},
43+
},
2144
parameters: {
2245
controls: {
2346
expanded: true,
@@ -28,14 +51,15 @@ const preview: Preview = {
2851
},
2952
backgrounds: {
3053
options: {
31-
light: { name: 'Light', value: '#ffffff' },
32-
dark: { name: 'Dark', value: '#2c2c2c' },
54+
light: { value: '#ffffff', name: storyT('storybook.stories.Backgrounds.light') },
55+
dark: { value: '#2c2c2c', name: storyT('storybook.stories.Backgrounds.dark') },
3356
},
3457
},
3558
docs: {
3659
container: (props: PropsWithChildren<DocsContainerProps>) => {
37-
const bgValue = (props.context as unknown as StoryContext<ReactRenderer>)?.globals?.backgrounds?.value;
38-
const isDark = bgValue ? bgValue === 'dark' : isPreferDark;
60+
const globalValue = (props.context as unknown as StoryContext<ReactRenderer>)?.globals?.backgrounds?.value;
61+
const theme = globalValue ?? themeFromUrl;
62+
const isDark = theme ? theme === 'dark' : isPreferDark;
3963
return <DocsContainer {...props} theme={isDark ? themes.dark : themes.light} />;
4064
},
4165
extractComponentDescription: (
@@ -48,31 +72,27 @@ const preview: Preview = {
4872
},
4973
},
5074
},
51-
globalTypes: {
52-
lang: {
53-
description: 'Internationalization locale',
54-
toolbar: {
55-
icon: 'globe',
56-
items: [
57-
{ value: 'en-US', right: '🇺🇸', title: 'English' },
58-
{ value: 'zh-CN', right: '🇨🇳', title: '中文' },
59-
],
60-
},
61-
},
62-
},
63-
initialGlobals: {
64-
lang: 'en-US',
65-
backgrounds: { value: isPreferDark ? 'dark' : 'light' },
66-
},
6775
tags: ['autodocs'],
6876
decorators: [
6977
(Story, context) => {
70-
const bgValue = context.globals?.backgrounds?.value;
71-
const lang = context.globals.lang ?? 'en-US';
78+
const themeFromGlobal = context.globals?.backgrounds?.value;
79+
const theme: string | undefined = themeFromGlobal ?? themeFromUrl;
80+
const lang: Langs | undefined = context.globals.lang ?? langFromUrl ?? 'en-US';
7281
const antdLocale = lang === 'zh-CN' ? zhCN : enUS;
7382
const { viewMode } = useStoryContext();
7483
const viewModeRef = useRefValue(viewMode);
84+
const [prevTheme, setPrevTheme] = useState(themeFromGlobal);
85+
const isDark = theme === 'dark' || (!theme && isPreferDark);
86+
87+
// Reload the page if the theme changes.
88+
useMemo(() => {
89+
if (themeFromGlobal !== prevTheme) {
90+
setPrevTheme(themeFromGlobal);
91+
(window.top ?? window.parent ?? window).location.reload();
92+
}
93+
}, [themeFromGlobal, prevTheme]);
7594

95+
// Reload the page if the language changes.
7696
useMemo(() => {
7797
if (storyI18n.language !== lang) {
7898
storyI18n.changeLanguage(lang).then(() => {
@@ -88,7 +108,7 @@ const preview: Preview = {
88108
return (
89109
<AntdConfigProvider
90110
locale={antdLocale}
91-
theme={{ algorithm: bgValue === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm }}
111+
theme={{ algorithm: isDark ? antThemes.darkAlgorithm : antThemes.defaultAlgorithm }}
92112
>
93113
<AntdApp>
94114
<ConfigProvider lang={lang}>

.storybook/stories/ColumnSetting.stories.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,6 @@ import ColumnSetting from '../../src/components/ColumnSetting';
66
import type { ColumnSettingItem, ColumnSettingProps } from '../../src/components/ColumnSetting';
77
import { storyT, useStoryT } from '../locales';
88

9-
interface User {
10-
id: number;
11-
name: string;
12-
age: number;
13-
city: string;
14-
role: string;
15-
}
16-
type ColumnSettingStoryArgs = ColumnSettingProps;
17-
18-
const buildBaseColumns = (t: ReturnType<typeof useStoryT>): ColumnSettingItem<User>[] => [
19-
{ title: t('storybook.stories.ColumnSetting.columns.id'), dataIndex: 'id', key: 'id', width: 80, disabled: true },
20-
{ title: t('storybook.stories.ColumnSetting.columns.name'), dataIndex: 'name', key: 'name' },
21-
{ title: t('storybook.stories.ColumnSetting.columns.age'), dataIndex: 'age', key: 'age' },
22-
{ title: t('storybook.stories.ColumnSetting.columns.city'), dataIndex: 'city', key: 'city' },
23-
{ title: t('storybook.stories.ColumnSetting.columns.role'), dataIndex: 'role', key: 'role' },
24-
];
25-
269
const meta: Meta<ColumnSettingStoryArgs> = {
2710
title: 'Components/ColumnSetting',
2811
component: ColumnSetting,
@@ -93,3 +76,22 @@ export const Playground: Story = {
9376
);
9477
},
9578
};
79+
80+
interface User {
81+
id: number;
82+
name: string;
83+
age: number;
84+
city: string;
85+
role: string;
86+
}
87+
type ColumnSettingStoryArgs = ColumnSettingProps;
88+
89+
function buildBaseColumns(t: ReturnType<typeof useStoryT>): ColumnSettingItem<User>[] {
90+
return [
91+
{ title: t('storybook.stories.ColumnSetting.columns.id'), dataIndex: 'id', key: 'id', width: 80, disabled: true },
92+
{ title: t('storybook.stories.ColumnSetting.columns.name'), dataIndex: 'name', key: 'name' },
93+
{ title: t('storybook.stories.ColumnSetting.columns.age'), dataIndex: 'age', key: 'age' },
94+
{ title: t('storybook.stories.ColumnSetting.columns.city'), dataIndex: 'city', key: 'city' },
95+
{ title: t('storybook.stories.ColumnSetting.columns.role'), dataIndex: 'role', key: 'role' },
96+
];
97+
}

.storybook/utils/global.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function getGlobalValueFromUrl(key: string): string | undefined {
2+
const urlParams = new URLSearchParams(window.location.search);
3+
const globals = urlParams.get('globals');
4+
if (!globals) return undefined;
5+
6+
const value = globals.split(';').find((item) => item.startsWith(`${key}:`));
7+
return value ? value.split(':')[1] : undefined;
8+
}

0 commit comments

Comments
 (0)