315 lines
13 KiB
TypeScript
315 lines
13 KiB
TypeScript
import type { ThemeConfig } from "antd";
|
|
import { theme as antdTheme } from "antd";
|
|
|
|
// 主操作、普通选择和开关是不同交互语义,必须各自维护成对的背景/前景色。
|
|
const controlTheme = {
|
|
light: {
|
|
solidBg: "#171717",
|
|
solidHoverBg: "#303030",
|
|
solidActiveBg: "#404040",
|
|
solidFg: "#ffffff",
|
|
checkBg: "#171717",
|
|
checkHoverBg: "#303030",
|
|
checkActiveBg: "#404040",
|
|
checkFg: "#ffffff",
|
|
switchCheckedBg: "#171717",
|
|
switchCheckedHoverBg: "#303030",
|
|
switchCheckedHandle: "#ffffff",
|
|
selectedBg: "rgba(17, 17, 17, 0.09)",
|
|
selectedHoverBg: "rgba(17, 17, 17, 0.13)",
|
|
selectedActiveBg: "rgba(17, 17, 17, 0.16)",
|
|
selectedFg: "#171717",
|
|
controlSurface: "#ffffff",
|
|
controlBorder: "rgba(17, 17, 17, 0.18)",
|
|
controlDisabledBg: "rgba(17, 17, 17, 0.05)",
|
|
controlDisabledFg: "rgba(17, 17, 17, 0.36)",
|
|
controlFocus: "rgba(17, 17, 17, 0.24)",
|
|
switchOffBg: "rgba(17, 17, 17, 0.22)",
|
|
switchOffHoverBg: "rgba(17, 17, 17, 0.3)",
|
|
switchOffHandle: "#ffffff",
|
|
menuBg: "#f5f5f5",
|
|
menuText: "#171717",
|
|
selectActiveBg: "rgba(17, 17, 17, 0.035)",
|
|
selectSelectedBg: "rgba(17, 17, 17, 0.065)",
|
|
selectText: "#171717",
|
|
tableSelectedBg: "rgba(17, 17, 17, 0.05)",
|
|
tableSelectedHoverBg: "rgba(17, 17, 17, 0.08)",
|
|
},
|
|
dark: {
|
|
solidBg: "#f5f5f5",
|
|
solidHoverBg: "#ffffff",
|
|
solidActiveBg: "#e5e5e5",
|
|
solidFg: "#171717",
|
|
checkBg: "#f5f5f5",
|
|
checkHoverBg: "#ffffff",
|
|
checkActiveBg: "#e5e5e5",
|
|
checkFg: "#131313",
|
|
switchCheckedBg: "#f5f5f5",
|
|
switchCheckedHoverBg: "#ffffff",
|
|
switchCheckedHandle: "#131313",
|
|
selectedBg: "rgba(255, 255, 255, 0.12)",
|
|
selectedHoverBg: "rgba(255, 255, 255, 0.16)",
|
|
selectedActiveBg: "rgba(255, 255, 255, 0.2)",
|
|
selectedFg: "#f5f5f5",
|
|
controlSurface: "rgba(255, 255, 255, 0.035)",
|
|
controlBorder: "rgba(255, 255, 255, 0.24)",
|
|
controlDisabledBg: "rgba(255, 255, 255, 0.06)",
|
|
controlDisabledFg: "rgba(255, 255, 255, 0.38)",
|
|
controlFocus: "rgba(255, 255, 255, 0.24)",
|
|
switchOffBg: "rgba(255, 255, 255, 0.22)",
|
|
switchOffHoverBg: "rgba(255, 255, 255, 0.3)",
|
|
switchOffHandle: "#f5f5f5",
|
|
menuBg: "#262626",
|
|
menuText: "#fafafa",
|
|
selectActiveBg: "rgba(255, 255, 255, 0.055)",
|
|
selectSelectedBg: "rgba(255, 255, 255, 0.09)",
|
|
selectText: "#fafafa",
|
|
tableSelectedBg: "rgba(255, 255, 255, 0.08)",
|
|
tableSelectedHoverBg: "rgba(255, 255, 255, 0.12)",
|
|
},
|
|
};
|
|
|
|
export function getAntThemeConfig(dark: boolean): ThemeConfig {
|
|
const color = dark ? controlTheme.dark : controlTheme.light;
|
|
const elevatedBackground = dark ? "rgba(31, 31, 32, 0.96)" : "rgba(255, 255, 255, 0.96)";
|
|
const subtleBackground = dark ? "rgba(255, 255, 255, 0.055)" : "rgba(17, 17, 17, 0.035)";
|
|
const interactiveBorder = dark ? "rgba(255, 255, 255, 0.18)" : "rgba(17, 17, 17, 0.18)";
|
|
// 黑白主题使用边框表达焦点,避免输入控件周围出现蓝紫色光圈。
|
|
const focusShadow = "none";
|
|
|
|
return {
|
|
algorithm: dark ? antdTheme.darkAlgorithm : antdTheme.defaultAlgorithm,
|
|
cssVar: { key: dark ? "infinite-canvas-dark" : "infinite-canvas-light" },
|
|
token: {
|
|
colorPrimary: color.solidBg,
|
|
colorPrimaryHover: color.solidHoverBg,
|
|
colorPrimaryActive: color.solidActiveBg,
|
|
colorPrimaryBg: color.selectedBg,
|
|
colorPrimaryBgHover: color.selectedHoverBg,
|
|
colorInfo: color.solidBg,
|
|
colorLink: color.solidBg,
|
|
colorLinkHover: color.solidHoverBg,
|
|
colorLinkActive: color.solidActiveBg,
|
|
colorTextLightSolid: color.solidFg,
|
|
colorBgElevated: elevatedBackground,
|
|
colorBorderSecondary: dark ? "rgba(255, 255, 255, 0.1)" : "rgba(17, 17, 17, 0.09)",
|
|
boxShadowSecondary: dark ? "0 24px 72px rgba(0, 0, 0, 0.48)" : "0 22px 64px rgba(15, 23, 42, 0.14)",
|
|
borderRadius: 6,
|
|
borderRadiusLG: 8,
|
|
borderRadiusSM: 5,
|
|
controlHeight: 36,
|
|
controlHeightLG: 42,
|
|
controlHeightSM: 30,
|
|
fontSize: 13,
|
|
fontSizeSM: 12,
|
|
motionDurationFast: "0.12s",
|
|
motionDurationMid: "0.18s",
|
|
motionDurationSlow: "0.24s",
|
|
},
|
|
components: {
|
|
Button: {
|
|
primaryShadow: "none",
|
|
fontWeight: 500,
|
|
paddingInline: 14,
|
|
paddingInlineLG: 16,
|
|
paddingInlineSM: 10,
|
|
colorPrimary: color.solidBg,
|
|
colorPrimaryHover: color.solidHoverBg,
|
|
colorPrimaryActive: color.solidActiveBg,
|
|
primaryColor: color.solidFg,
|
|
defaultBg: "transparent",
|
|
defaultColor: color.selectedFg,
|
|
defaultBorderColor: color.controlBorder,
|
|
defaultHoverBg: color.selectedBg,
|
|
defaultHoverColor: color.selectedFg,
|
|
defaultHoverBorderColor: color.controlBorder,
|
|
defaultActiveBg: color.selectedHoverBg,
|
|
defaultActiveColor: color.selectedFg,
|
|
defaultActiveBorderColor: color.controlBorder,
|
|
},
|
|
Input: {
|
|
paddingInline: 11,
|
|
activeBg: elevatedBackground,
|
|
hoverBg: elevatedBackground,
|
|
activeBorderColor: interactiveBorder,
|
|
hoverBorderColor: interactiveBorder,
|
|
activeShadow: focusShadow,
|
|
},
|
|
InputNumber: {
|
|
activeBg: elevatedBackground,
|
|
hoverBg: elevatedBackground,
|
|
activeBorderColor: interactiveBorder,
|
|
hoverBorderColor: interactiveBorder,
|
|
activeShadow: focusShadow,
|
|
},
|
|
Switch: {
|
|
handleBg: color.switchOffHandle,
|
|
handleShadow: dark ? "0 1px 4px rgba(0, 0, 0, 0.42)" : "0 1px 2px rgba(0, 0, 0, 0.2)",
|
|
colorPrimary: color.switchCheckedBg,
|
|
colorPrimaryActive: color.switchCheckedBg,
|
|
colorPrimaryHover: color.switchCheckedHoverBg,
|
|
colorTextQuaternary: color.switchOffBg,
|
|
colorTextTertiary: color.switchOffHoverBg,
|
|
controlOutline: color.controlFocus,
|
|
},
|
|
Checkbox: {
|
|
colorBgContainer: color.controlSurface,
|
|
colorBgContainerDisabled: color.controlDisabledBg,
|
|
colorBorder: color.controlBorder,
|
|
colorPrimary: color.checkBg,
|
|
colorPrimaryActive: color.checkActiveBg,
|
|
colorPrimaryHover: color.checkHoverBg,
|
|
controlOutline: color.controlFocus,
|
|
},
|
|
Radio: {
|
|
radioSize: 16,
|
|
dotSize: 6,
|
|
buttonBg: color.controlSurface,
|
|
buttonCheckedBg: color.selectedBg,
|
|
buttonCheckedBgDisabled: color.controlDisabledBg,
|
|
buttonCheckedColorDisabled: color.controlDisabledFg,
|
|
buttonSolidCheckedColor: color.checkFg,
|
|
buttonSolidCheckedActiveBg: color.checkActiveBg,
|
|
buttonSolidCheckedBg: color.checkBg,
|
|
buttonSolidCheckedHoverBg: color.checkHoverBg,
|
|
colorBgContainer: color.controlSurface,
|
|
colorBgContainerDisabled: color.controlDisabledBg,
|
|
colorBorder: color.controlBorder,
|
|
colorPrimary: color.checkBg,
|
|
colorPrimaryActive: color.checkActiveBg,
|
|
colorPrimaryHover: color.checkHoverBg,
|
|
controlOutline: color.controlFocus,
|
|
},
|
|
Menu: {
|
|
itemActiveBg: color.menuBg,
|
|
itemHoverBg: color.menuBg,
|
|
itemSelectedBg: color.menuBg,
|
|
itemSelectedColor: color.menuText,
|
|
darkItemHoverBg: controlTheme.dark.menuBg,
|
|
darkItemSelectedBg: controlTheme.dark.menuBg,
|
|
darkItemSelectedColor: controlTheme.dark.menuText,
|
|
},
|
|
Select: {
|
|
selectorBg: elevatedBackground,
|
|
optionHeight: 36,
|
|
optionPadding: "8px 10px",
|
|
multipleItemHeight: 24,
|
|
activeBorderColor: interactiveBorder,
|
|
hoverBorderColor: interactiveBorder,
|
|
activeOutlineColor: "transparent",
|
|
optionActiveBg: color.selectActiveBg,
|
|
optionSelectedBg: color.selectSelectedBg,
|
|
optionSelectedColor: color.selectText,
|
|
},
|
|
Table: {
|
|
headerBg: subtleBackground,
|
|
headerColor: dark ? "rgba(250, 250, 250, 0.62)" : "rgba(23, 23, 23, 0.58)",
|
|
headerBorderRadius: 0,
|
|
rowHoverBg: dark ? "rgba(255, 255, 255, 0.035)" : "rgba(17, 17, 17, 0.025)",
|
|
borderColor: dark ? "rgba(255, 255, 255, 0.08)" : "rgba(17, 17, 17, 0.075)",
|
|
cellPaddingBlockMD: 13,
|
|
cellPaddingInlineMD: 14,
|
|
rowSelectedBg: color.tableSelectedBg,
|
|
rowSelectedHoverBg: color.tableSelectedHoverBg,
|
|
},
|
|
Pagination: {
|
|
itemBg: "transparent",
|
|
itemLinkBg: "transparent",
|
|
itemActiveBg: color.solidBg,
|
|
itemActiveColor: color.solidFg,
|
|
itemActiveColorHover: color.solidFg,
|
|
},
|
|
Segmented: {
|
|
trackBg: subtleBackground,
|
|
trackPadding: 3,
|
|
itemColor: color.controlDisabledFg,
|
|
itemHoverColor: color.selectedFg,
|
|
itemHoverBg: color.selectedBg,
|
|
itemActiveBg: color.selectedActiveBg,
|
|
itemSelectedBg: color.selectedBg,
|
|
itemSelectedColor: color.selectedFg,
|
|
},
|
|
Modal: {
|
|
headerBg: "transparent",
|
|
contentBg: elevatedBackground,
|
|
footerBg: "transparent",
|
|
titleFontSize: 16,
|
|
},
|
|
Form: {
|
|
itemMarginBottom: 18,
|
|
labelFontSize: 12,
|
|
verticalLabelPadding: "0 0 6px",
|
|
},
|
|
Dropdown: {
|
|
paddingBlock: 6,
|
|
},
|
|
Skeleton: {
|
|
gradientFromColor: dark ? "rgba(255, 255, 255, 0.055)" : "rgba(15, 23, 42, 0.055)",
|
|
gradientToColor: dark ? "rgba(255, 255, 255, 0.11)" : "rgba(15, 23, 42, 0.1)",
|
|
},
|
|
Card: {
|
|
headerBg: "transparent",
|
|
headerFontSize: 15,
|
|
bodyPadding: 18,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 管理后台使用更高密度的控件节奏;只在 AdminShell 内挂载,避免改变创作端的视觉契约。
|
|
*/
|
|
export function getAdminAntThemeConfig(dark: boolean): ThemeConfig {
|
|
const base = getAntThemeConfig(dark);
|
|
const mutedForeground = dark ? "rgba(250, 250, 250, 0.58)" : "rgba(23, 23, 23, 0.58)";
|
|
|
|
return {
|
|
...base,
|
|
token: {
|
|
...base.token,
|
|
borderRadius: 6,
|
|
borderRadiusLG: 8,
|
|
colorBgContainer: "var(--color-surface)",
|
|
colorBorder: "var(--color-border)",
|
|
fontFamily: "var(--font-sans)",
|
|
padding: 12,
|
|
paddingSM: 8,
|
|
fontSize: 13,
|
|
},
|
|
components: {
|
|
...base.components,
|
|
Card: {
|
|
...base.components?.Card,
|
|
boxShadow: "none",
|
|
boxShadowTertiary: "none",
|
|
},
|
|
Drawer: {
|
|
...base.components?.Drawer,
|
|
colorBgElevated: "var(--color-surface)",
|
|
},
|
|
Form: {
|
|
...base.components?.Form,
|
|
itemMarginBottom: 16,
|
|
},
|
|
Menu: {
|
|
...base.components?.Menu,
|
|
itemHeight: 34,
|
|
itemSelectedBg: "transparent",
|
|
},
|
|
Table: {
|
|
...base.components?.Table,
|
|
cellPaddingBlock: 8,
|
|
cellPaddingBlockMD: 8,
|
|
cellPaddingBlockSM: 6,
|
|
cellPaddingInline: 12,
|
|
cellPaddingInlineMD: 12,
|
|
cellPaddingInlineSM: 8,
|
|
headerBg: "transparent",
|
|
headerColor: mutedForeground,
|
|
headerSplitColor: "transparent",
|
|
borderColor: "var(--color-border)",
|
|
},
|
|
},
|
|
};
|
|
}
|