style: 全站使用背景分层替代装饰边框并统一直角

This commit is contained in:
GouJ
2026-09-01 21:39:05 +08:00
parent 799f16d336
commit 03bf87ca9a
25 changed files with 292 additions and 116 deletions
+8 -3
View File
@@ -89,7 +89,7 @@ describe('微信风格明暗主题', () => {
it.each([false, true])('明暗模式 %s 的组件表面、语义色与业务 CSS 一致,主要文字保持可读', dark => {
const state = setup(dark)
const { common, Menu, Button, Layout } = state.overrides.value
const { common, Menu, Button, Layout, Input, Select } = state.overrides.value
const css = readFileSync('src/admin.css', 'utf8')
const lightTokens = css.match(/:root\s*\{([^}]+)\}/)![1]!
const darkTokens = css.match(/:root\[data-theme='dark'\]\s*\{([^}]+)\}/)![1]!
@@ -119,8 +119,13 @@ describe('微信风格明暗主题', () => {
itemColorActiveCollapsed: tokens.selected,
itemTextColorActive: tokens['accent-text']
})
// 圆角调整只用于导航,表单、普通按钮和弹窗仍保留原有主题
expect(common?.borderRadius).toBe('6px')
// 全站直角;输入区域与普通按钮共享底色,保持明暗模式一致
expect(common?.borderRadius).toBe('0px')
expect(common?.borderRadiusSmall).toBe('0px')
expect(Input?.color).toBe(tokens.control)
expect(Button?.color).toBe(tokens.control)
expect(Button?.colorHover).toBe(tokens['control-hover'])
expect(Select?.peers?.InternalSelection?.color).toBe(tokens.control)
expect(Button?.textColorPrimary).toBe(tokens['on-accent'])
for (const background of [common!.primaryColor!, common!.primaryColorHover!, common!.primaryColorPressed!]) {
expect(contrast(String(Button!.textColorPrimary), background)).toBeGreaterThanOrEqual(4.5)
+88 -4
View File
@@ -39,6 +39,18 @@ export function useTheme() {
const info = dark ? '#91a8d2' : '#576b95'
const danger = dark ? '#fa7373' : '#a93232'
const warning = dark ? '#e8b66a' : '#916019'
const control = dark ? '#2b2b2b' : '#f0f0f0'
const controlHover = dark ? '#353535' : '#e5e5e5'
// 静态边界交给底色;聚焦与错误边框仍由控件的状态主题负责。
const focusBorder = `1px solid ${accentText}`
const selection = {
color: control,
colorActive: control,
border: 'none',
borderHover: 'none',
borderFocus: focusBorder,
borderActive: focusBorder
}
return {
common: {
primaryColor: primary,
@@ -61,7 +73,8 @@ export function useTheme() {
warningColorHover: warning,
warningColorPressed: warning,
warningColorSuppl: warning,
borderRadius: '6px',
borderRadius: '0px',
borderRadiusSmall: '0px',
bodyColor: body,
cardColor: surface,
modalColor: surface,
@@ -80,6 +93,15 @@ export function useTheme() {
"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif"
},
Button: {
color: control,
colorHover: controlHover,
colorPressed: controlHover,
colorFocus: controlHover,
border: 'none',
borderHover: 'none',
borderPressed: 'none',
borderDisabled: 'none',
borderFocus: focusBorder,
textColorPrimary: onPrimary,
textColorHoverPrimary: onPrimary,
textColorPressedPrimary: onPrimary,
@@ -88,6 +110,55 @@ export function useTheme() {
textColorTextPrimary: accentText,
textColorGhostPrimary: accentText
},
Input: {
color: control,
colorHover: controlHover,
colorFocus: control,
border: 'none',
borderHover: 'none',
borderDisabled: 'none',
borderFocus: focusBorder,
groupLabelBorder: 'none'
},
Select: { peers: { InternalSelection: selection } },
Card: { borderColor: 'transparent' },
Drawer: { headerBorderBottom: 'none', footerBorderTop: 'none' },
Alert: {
border: 'none',
borderInfo: 'none',
borderSuccess: 'none',
borderWarning: 'none',
borderError: 'none'
},
Collapse: { dividerColor: 'transparent' },
Table: {
borderColor: 'transparent',
borderColorModal: 'transparent',
borderColorPopover: 'transparent',
thColor: control,
thColorModal: control,
thColorPopover: control,
tdColorStriped: subtle,
tdColorStripedModal: subtle,
tdColorStripedPopover: subtle
},
DataTable: {
borderColor: 'transparent',
borderColorModal: 'transparent',
borderColorPopover: 'transparent',
thColor: control,
tdColorStriped: subtle,
tdColorHover: selected
},
Radio: {
buttonBorderColor: 'transparent',
buttonBorderColorActive: 'transparent',
buttonBorderColorHover: 'transparent',
buttonColor: control,
buttonColorActive: selected,
buttonTextColorActive: accentText,
buttonBoxShadowFocus: `inset 0 0 0 1px ${accentText}`
},
Layout: {
color: body,
headerColor: surface,
@@ -104,12 +175,25 @@ export function useTheme() {
itemIconColorActive: accentText,
itemIconColorActiveHover: accentText
},
Tabs: { tabTextColorActiveLine: accentText, tabTextColorHoverLine: accentText, barColor: primary },
Tag: { textColorPrimary: accentText },
Tabs: {
tabTextColorActiveLine: accentText,
tabTextColorHoverLine: accentText,
barColor: primary,
tabBorderColor: 'transparent'
},
Tag: {
textColorPrimary: accentText,
border: 'none',
borderPrimary: 'none',
borderInfo: 'none',
borderSuccess: 'none',
borderWarning: 'none',
borderError: 'none'
},
Checkbox: { checkMarkColor: onPrimary },
Switch: { railColorActive: primary },
Progress: { fillColor: primary }
}
} satisfies GlobalThemeOverrides
})
/** 系统切换只更新 system 模式下的实际显示。 */
function syncSystem(event: MediaQueryListEvent) {