Skip to content

Commit db7ead5

Browse files
committed
build: storybook
1 parent 077e064 commit db7ead5

6 files changed

Lines changed: 88 additions & 28 deletions

File tree

.storybook/main.ts

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,58 @@ const rootDir = process.cwd()
77
const config: StorybookConfig = {
88
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
99
addons: [
10-
'@storybook/addon-links', // 推荐加上:支持故事间跳转
11-
'@storybook/addon-a11y', // 保持
12-
'@storybook/addon-docs', // 如果你用了 MDX3,可以去掉(essentials 已包含)
10+
'@storybook/addon-links',
11+
// '@storybook/addon-a11y',
12+
'@storybook/addon-docs',
1313
],
1414
docs: {},
1515
framework: {
1616
name: '@storybook/react-vite',
1717
options: {},
1818
},
1919
viteFinal: async (viteConfig) => {
20-
// Storybook 会合并项目的 Vite 配置;如果把应用的 HTML input 带进来,
21-
// 可能导致 storybook-static/index.html 变成主应用模板(从而 manager 资源加载失败)。
20+
// Storybook 会合并项目的 Vite 配置。
21+
// 需要剔除「仅用于主应用 build」的选项/插件,否则可能:
22+
// 1) 覆盖 Storybook 的入口(index.html 变成主应用模板)
23+
// 2) 触发压缩/打包等后置插件,导致 Storybook build 失败(产物不完整,iframe.html/index.json 404)
2224
const cfg: any = viteConfig
23-
if (cfg?.build?.rollupOptions?.input) {
24-
delete cfg.build.rollupOptions.input
25+
26+
// build 相关:只移除「主应用的 index.html input」,保留 Storybook 自己的 iframe 输入。
27+
const inputLooksLikeAppIndex = (input: unknown): boolean => {
28+
const isIndexHtml = (v: unknown) => {
29+
if (typeof v !== 'string') return false
30+
const normalized = v.replace(/\\/g, '/').toLowerCase()
31+
return normalized.endsWith('/index.html') || normalized === 'index.html'
32+
}
33+
if (isIndexHtml(input)) return true
34+
if (Array.isArray(input)) return input.some(isIndexHtml)
35+
if (input && typeof input === 'object') {
36+
return Object.values(input as Record<string, unknown>).some(isIndexHtml)
37+
}
38+
return false
2539
}
26-
if (cfg?.build?.outDir) {
27-
delete cfg.build.outDir
40+
41+
if (cfg?.build?.rollupOptions?.input && inputLooksLikeAppIndex(cfg.build.rollupOptions.input)) {
42+
delete cfg.build.rollupOptions.input
2843
}
44+
if (cfg?.build?.outDir) delete cfg.build.outDir
2945

30-
return mergeConfig(viteConfig, {
46+
// 插件相关:过滤掉主应用专用插件(压缩/zip/sentry/analyze 等)。
47+
const filteredPlugins = Array.isArray(cfg?.plugins)
48+
? cfg.plugins.filter((p: any) => {
49+
const name: string = String(p?.name || '')
50+
if (!name) return true
51+
if (name === 'vite-plugin-compression') return false
52+
if (name === 'zip-after-build') return false
53+
if (name.includes('sentry')) return false
54+
if (name.includes('visualizer')) return false
55+
return true
56+
})
57+
: cfg?.plugins
58+
59+
const merged = mergeConfig(viteConfig, {
60+
// 避免 Vite 默认拾取项目根目录的 index.html(会把 storybook-static/index.html 覆盖成主应用 loader)
61+
root: path.resolve(rootDir, '.storybook'),
3162
resolve: {
3263
alias: {
3364
'@': path.resolve(rootDir, 'src'),
@@ -60,8 +91,17 @@ const config: StorybookConfig = {
6091

6192
build: {
6293
chunkSizeWarningLimit: 2000,
94+
// 强制 preview 产物落在 storybook-static(否则会被主应用 outDir 污染,导致 iframe.html 缺失 -> 404)
95+
outDir: path.resolve(rootDir, 'storybook-static'),
96+
// manager 会负责清理 outputDir;这里避免 vite 误删 manager 文件
97+
emptyOutDir: false,
6398
},
6499
})
100+
101+
// mergeConfig 会合并 plugins 数组,这里强制替换为过滤后的插件列表。
102+
;(merged as any).plugins = filteredPlugins
103+
104+
return merged
65105
},
66106
}
67107

src/components/ResponsiveTable/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ const ResponsiveTable = <T,>(props: ResponsiveTableProps<T> & TableProps<T>) =>
426426
<span>操作</span>
427427
{showColumnSettings && (
428428
<Popover content={popContent} title="列设置">
429-
<Button icon={<SettingOutlined />} size="small" />
429+
<Button icon={<SettingOutlined />} size="small" aria-label="列设置" title="列设置" />
430430
</Popover>
431431
)}
432432
</div>

src/components/stateless/OneTimePasscode/index.module.less

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
--otp-primary-rgb: 22, 119, 255;
44
--otp-bg: #fff;
55
--otp-fg: #0f1720;
6+
--otp-bg-1: rgb(255 255 255 / 92%);
7+
--otp-bg-2: rgb(245 247 250 / 92%);
68
}
79

810
.wrapper {
@@ -18,7 +20,7 @@
1820
height: 3.25rem;
1921
border-radius: 0.75rem;
2022
border: 1px solid rgb(15 23 32 / 6%);
21-
background: linear-gradient(180deg, rgb(255 255 255 / 85%), rgb(250 250 252 / 85%));
23+
background: var(--otp-bg);
2224
color: var(--otp-fg);
2325
font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, monospace;
2426
font-size: 1.125rem;
@@ -42,7 +44,6 @@
4244
border-radius: 0.9rem;
4345
font-size: 1.125rem;
4446
box-shadow: 0 10px 28px rgb(2 6 23 / 8%);
45-
background: linear-gradient(180deg, rgb(255 255 255 / 92%), rgb(245 247 250 / 92%));
4647
}
4748

4849
/* explicit variant classes to ensure CSS module exports these keys */
@@ -67,7 +68,7 @@
6768
height: 3rem;
6869
border-radius: 0.35rem;
6970
border: 1px solid rgb(15 23 32 / 12%);
70-
background: linear-gradient(180deg, #fff, #f7fafc);
71+
background: var(--otp-bg);
7172
box-shadow: inset 0 -2px 6px rgb(0 0 0 / 2%);
7273
}
7374

src/components/stateless/OneTimePasscode/index.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,19 @@ export const OneTimePasscode: React.FC<OneTimePasscodeProps> = ({
149149
['--otp-primary-rgb' as any]: hexToRgb(primary),
150150
['--otp-bg' as any]: themeMode === 'dark' ? '#0b1220' : '#fff',
151151
['--otp-fg' as any]: themeMode === 'dark' ? '#e6eef8' : '#0f1720',
152+
['--otp-bg-1' as any]: themeMode === 'dark' ? 'rgba(11, 18, 32, 0.92)' : 'rgba(255, 255, 255, 0.92)',
153+
['--otp-bg-2' as any]: themeMode === 'dark' ? 'rgba(9, 14, 24, 0.92)' : 'rgba(245, 247, 250, 0.92)',
152154
}
153155
} catch (e) {
154156
// if context not available, fall back to defaults
155-
themeStyle = { ['--otp-primary' as any]: '#1677ff', ['--otp-primary-rgb' as any]: '22, 119, 255' }
157+
themeStyle = {
158+
['--otp-primary' as any]: '#1677ff',
159+
['--otp-primary-rgb' as any]: '22, 119, 255',
160+
['--otp-bg' as any]: '#fff',
161+
['--otp-fg' as any]: '#0f1720',
162+
['--otp-bg-1' as any]: 'rgba(255, 255, 255, 0.92)',
163+
['--otp-bg-2' as any]: 'rgba(245, 247, 250, 0.92)',
164+
}
156165
}
157166

158167
const wrapperClass = [css.wrapper, (css as any)[variant] ?? '', className ?? ''].filter(Boolean).join(' ')
@@ -164,8 +173,8 @@ export const OneTimePasscode: React.FC<OneTimePasscodeProps> = ({
164173
width: '3.25rem',
165174
height: '3.25rem',
166175
borderRadius: '0.75rem',
167-
border: '1px solid rgba(15,23,32,0.06)',
168-
background: 'linear-gradient(180deg, rgba(255,255,255,0.85), rgba(250,250,252,0.85))',
176+
border: '1px solid rgba(15,23,32,0.12)',
177+
background: 'var(--otp-bg, #fff)',
169178
color: 'var(--otp-fg, #0f1720)',
170179
fontFamily: "ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, monospace",
171180
fontSize: '1.125rem',

src/components/stateless/SmartVideoPlayer/index.jsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,7 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
14891489
{!isEmbed ? (
14901490
<div
14911491
className={`${styles.settingItem} ${styles.settingItemSplit}`}
1492+
role="group"
14921493
aria-label={t('svp.ariaPlaybackSpeed')}
14931494
>
14941495
<span className={styles.settingLabel}>{t('svp.playbackSpeed')}</span>
@@ -1530,7 +1531,11 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
15301531
) : null}
15311532

15321533
{!isEmbed && captionTracks.length > 0 ? (
1533-
<div className={`${styles.settingItem} ${styles.settingItemSplit}`} aria-label={t('svp.ariaCaptions')}>
1534+
<div
1535+
className={`${styles.settingItem} ${styles.settingItemSplit}`}
1536+
role="group"
1537+
aria-label={t('svp.ariaCaptions')}
1538+
>
15341539
<span className={styles.settingLabel}>{t('svp.captions')}</span>
15351540
<div className={styles.speedDropdown} data-captions-dropdown="true">
15361541
<button
@@ -1591,7 +1596,11 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
15911596
</div>
15921597
) : null}
15931598

1594-
<div className={`${styles.settingItem} ${styles.settingItemSplit}`} aria-label={t('svp.ariaUiLanguage')}>
1599+
<div
1600+
className={`${styles.settingItem} ${styles.settingItemSplit}`}
1601+
role="group"
1602+
aria-label={t('svp.ariaUiLanguage')}
1603+
>
15951604
<span className={styles.settingLabel}>{t('svp.uiLanguage')}</span>
15961605
<div className={styles.speedDropdown} data-ui-lang-dropdown="true">
15971606
<button
@@ -1646,7 +1655,7 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
16461655
</div>
16471656
</div>
16481657

1649-
<div className={styles.settingsScroll} aria-label={t('svp.ariaOtherSettings')}>
1658+
<div className={styles.settingsScroll} role="group" aria-label={t('svp.ariaOtherSettings')}>
16501659
{!isEmbed ? (
16511660
<>
16521661
<SettingToggle
@@ -1780,7 +1789,7 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
17801789
) : null}
17811790

17821791
{isEmbed ? (
1783-
<div className={styles.embedToolbar} aria-label={t('svp.ariaEmbedToolbar')}>
1792+
<div className={styles.embedToolbar} role="toolbar" aria-label={t('svp.ariaEmbedToolbar')}>
17841793
{externalOpenUrl ? (
17851794
<IconButton Icon={ExternalLink} label={t('svp.openInNewWindow')} onClick={handleOpenExternal} />
17861795
) : null}
@@ -1797,7 +1806,7 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
17971806
) : null}
17981807

17991808
{!isEmbed ? (
1800-
<div className={styles.videoControls} aria-label={t('svp.ariaVideoControls')}>
1809+
<div className={styles.videoControls} role="group" aria-label={t('svp.ariaVideoControls')}>
18011810
<div className={styles.controlsTop} role="group" aria-label={t('svp.ariaPlaybackTools')}>
18021811
{!isEmbed && !isMini ? (
18031812
<IconButton
@@ -1899,6 +1908,7 @@ const SmartVideoPlayerInner = React.forwardRef(function SmartVideoPlayerInner(
18991908
<span className={styles.time}>{formatTime(currentTime)}</span>
19001909
<div
19011910
className={styles.progressWrap}
1911+
role="group"
19021912
onPointerMove={handleProgressPointerMove}
19031913
onPointerLeave={handleProgressPointerLeave}
19041914
aria-label={t('svp.ariaProgressBar')}

src/components/stateless/SmartVideoPlayer/index.module.less

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
}
1515

1616
.videoWrap {
17-
background: transparent;
17+
background: rgba(0, 0, 0, 0.92);
1818
position: relative;
1919
overflow: hidden;
2020
}
@@ -102,7 +102,7 @@
102102
.embedFallback {
103103
width: 100%;
104104
aspect-ratio: 16 / 9;
105-
background: transparent;
105+
background: rgba(0, 0, 0, 0.92);
106106
color: rgba(255, 255, 255, 0.85);
107107
display: grid;
108108
place-content: center;
@@ -194,7 +194,7 @@
194194
display: grid;
195195
gap: 8px;
196196
padding: 8px 8px;
197-
background: rgba(0, 0, 0, 0.52);
197+
background: rgba(0, 0, 0, 0.72);
198198
border-top: 1px solid rgba(255, 255, 255, 0.08);
199199
opacity: 0;
200200
transform: translateY(56%);
@@ -243,7 +243,7 @@
243243

244244
.time {
245245
font-size: 12px;
246-
color: rgba(255, 255, 255, 0.78);
246+
color: rgba(255, 255, 255, 0.92);
247247
font-variant-numeric: tabular-nums;
248248
white-space: nowrap;
249249
flex: 0 0 auto;
@@ -660,7 +660,7 @@
660660
.miniPlaceholder {
661661
width: 100%;
662662
aspect-ratio: 16 / 9;
663-
background: transparent;
663+
background: rgba(0, 0, 0, 0.92);
664664
}
665665

666666
.mini {
@@ -770,5 +770,5 @@
770770
height: auto;
771771
aspect-ratio: 16 / 9;
772772
object-fit: contain;
773-
background: transparent;
773+
background: rgba(0, 0, 0, 0.92);
774774
}

0 commit comments

Comments
 (0)