Files
ttstd-infinite-canvas/web/src/lib/app-theme.ts

240 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ThemeConfig } from "antd";
import { theme as antdTheme } from "antd";
const neutral = {
light: {
primary: "#171717",
primaryHover: "#000000",
primaryText: "#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: {
primary: "#fafafa",
primaryHover: "#ffffff",
primaryText: "#171717",
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 ? neutral.dark : neutral.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";
// 暗色界面的黑白主按钮与选择控件分色,避免开关轨道、勾选符号和滑块融成一片。
const selectionControl = dark
? {
active: "#ffffff",
border: "rgba(255, 255, 255, 0.3)",
disabledBackground: "rgba(255, 255, 255, 0.06)",
focus: "transparent",
hover: "#e5e5e5",
primary: "#f5f5f5",
surface: "rgba(255, 255, 255, 0.035)",
}
: null;
return {
algorithm: dark ? antdTheme.darkAlgorithm : antdTheme.defaultAlgorithm,
cssVar: { key: dark ? "infinite-canvas-dark" : "infinite-canvas-light" },
token: {
colorPrimary: color.primary,
colorInfo: color.primary,
colorLink: color.primary,
colorLinkHover: color.primaryHover,
colorLinkActive: color.primary,
colorTextLightSolid: color.primaryText,
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,
...(dark
? {
colorPrimary: "#f5f5f4",
colorPrimaryHover: "#ffffff",
colorPrimaryActive: "#e7e5e4",
primaryColor: "#171717",
defaultBg: "#262626",
defaultColor: "#f5f5f4",
defaultBorderColor: "#404040",
defaultHoverBg: "#303030",
defaultHoverColor: "#ffffff",
defaultHoverBorderColor: "#525252",
defaultActiveBg: "#1f1f1f",
defaultActiveColor: "#ffffff",
defaultActiveBorderColor: "#525252",
}
: {
/* 浅色模式:primary 近黑(#171717),antd 默认 hover 加暗到 #000000 几乎不可见。
改为提亮 hover/active,让交互反馈可感知(审计 #121)*/
colorPrimaryHover: "#404040",
colorPrimaryActive: "#525252",
}),
},
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: dark ? "#fafafa" : "#ffffff",
handleShadow: dark ? "0 1px 4px rgba(0, 0, 0, 0.42)" : "0 1px 2px rgba(0, 0, 0, 0.2)",
...(selectionControl
? {
colorPrimary: selectionControl.primary,
colorPrimaryActive: selectionControl.active,
colorPrimaryHover: selectionControl.hover,
colorTextQuaternary: "rgba(255, 255, 255, 0.16)",
colorTextTertiary: "rgba(255, 255, 255, 0.24)",
controlOutline: selectionControl.focus,
}
: {}),
},
Checkbox: {
...(selectionControl
? {
colorBgContainer: selectionControl.surface,
colorBgContainerDisabled: selectionControl.disabledBackground,
colorBorder: selectionControl.border,
colorPrimary: selectionControl.primary,
colorPrimaryActive: selectionControl.active,
colorPrimaryHover: selectionControl.hover,
controlOutline: selectionControl.focus,
}
: {}),
},
Radio: {
radioSize: 16,
dotSize: 6,
...(selectionControl
? {
buttonBg: selectionControl.surface,
buttonCheckedBg: "rgba(91, 110, 225, 0.12)",
buttonSolidCheckedActiveBg: selectionControl.active,
buttonSolidCheckedBg: selectionControl.primary,
buttonSolidCheckedHoverBg: selectionControl.hover,
colorBgContainer: selectionControl.surface,
colorBgContainerDisabled: selectionControl.disabledBackground,
colorBorder: selectionControl.border,
colorPrimary: selectionControl.primary,
colorPrimaryActive: selectionControl.active,
colorPrimaryHover: selectionControl.hover,
controlOutline: selectionControl.focus,
}
: {}),
},
Menu: {
itemActiveBg: color.menuBg,
itemHoverBg: color.menuBg,
itemSelectedBg: color.menuBg,
itemSelectedColor: color.menuText,
darkItemHoverBg: neutral.dark.menuBg,
darkItemSelectedBg: neutral.dark.menuBg,
darkItemSelectedColor: neutral.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: dark ? "#fafafa" : "#171717",
itemActiveColor: dark ? "#171717" : "#ffffff",
itemActiveColorHover: dark ? "#171717" : "#ffffff",
},
Segmented: {
trackBg: subtleBackground,
trackPadding: 3,
itemSelectedBg: elevatedBackground,
itemSelectedColor: dark ? "#fafafa" : "#171717",
itemHoverBg: dark ? "rgba(255, 255, 255, 0.07)" : "rgba(17, 17, 17, 0.055)",
},
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,
},
},
};
}