feat(theme): 重构主题系统,新增 glass-pill 按钮样式
- ThemeConfig 接口扩展至 60+ 语义化属性 - 新增深浅主题预设 (glassPill overrides) - button-group 支持 glass-pill 样式变体 - 默认主题改为浅色 - 移除 toolbar 容器硬编码定位 - 统一组件 CSS 变量命名规范 - 暂时隐藏下拉箭头
This commit is contained in:
@@ -93,6 +93,10 @@ export class BimButtonGroup implements IBimComponent {
|
||||
this.container.classList.add(this.options.className);
|
||||
}
|
||||
|
||||
if (this.options.type && this.options.type !== 'default') {
|
||||
this.container.classList.add(`type-${this.options.type}`);
|
||||
}
|
||||
|
||||
this.updatePosition();
|
||||
|
||||
// 添加事件拦截,防止点击穿透到 3D 引擎
|
||||
@@ -217,17 +221,16 @@ export class BimButtonGroup implements IBimComponent {
|
||||
*/
|
||||
public setTheme(theme: ThemeConfig): void {
|
||||
const themeColors: ButtonGroupColors = {
|
||||
backgroundColor: theme.panelBackground,
|
||||
btnBackgroundColor: theme.componentBackground,
|
||||
btnHoverColor: theme.componentHover,
|
||||
btnActiveColor: theme.componentActive,
|
||||
iconColor: theme.icon,
|
||||
backgroundColor: theme.bgElevated,
|
||||
btnBackgroundColor: theme.componentBg,
|
||||
btnHoverColor: theme.componentBgHover,
|
||||
btnActiveColor: theme.componentBgActive,
|
||||
iconColor: theme.iconDefault,
|
||||
iconActiveColor: theme.iconActive,
|
||||
textColor: theme.textSecondary,
|
||||
textActiveColor: theme.textPrimary
|
||||
};
|
||||
|
||||
// 只应用没有被自定义的颜色
|
||||
Object.entries(themeColors).forEach(([key, value]) => {
|
||||
const colorKey = key as keyof ButtonGroupColors;
|
||||
if (!this.customColors.has(colorKey)) {
|
||||
@@ -235,8 +238,90 @@ export class BimButtonGroup implements IBimComponent {
|
||||
}
|
||||
});
|
||||
|
||||
this.container.classList.remove('theme-dark', 'theme-light');
|
||||
this.container.classList.add(`theme-${theme.name}`);
|
||||
|
||||
this.applyStyles();
|
||||
this.setPrimaryColor(theme.primary);
|
||||
this.applyThemeCssVars(theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用主题系统的 CSS 变量到容器
|
||||
* 供 glass-pill 等样式变体使用
|
||||
*/
|
||||
private applyThemeCssVars(theme: ThemeConfig): void {
|
||||
const style = this.container.style;
|
||||
|
||||
style.setProperty('--bim-primary', theme.primary);
|
||||
style.setProperty('--bim-primary-hover', theme.primaryHover);
|
||||
style.setProperty('--bim-primary-active', theme.primaryActive);
|
||||
|
||||
style.setProperty('--bim-bg-glass', theme.bgGlass);
|
||||
style.setProperty('--bim-bg-glass-blur', theme.bgGlassBlur);
|
||||
style.setProperty('--bim-bg-elevated', theme.bgElevated);
|
||||
style.setProperty('--bim-bg-overlay', theme.bgOverlay);
|
||||
style.setProperty('--bim-bg-inset', theme.bgInset);
|
||||
|
||||
style.setProperty('--bim-text-primary', theme.textPrimary);
|
||||
style.setProperty('--bim-text-secondary', theme.textSecondary);
|
||||
style.setProperty('--bim-text-tertiary', theme.textTertiary);
|
||||
style.setProperty('--bim-text-inverse', theme.textInverse);
|
||||
|
||||
style.setProperty('--bim-icon-default', theme.iconDefault);
|
||||
style.setProperty('--bim-icon-hover', theme.iconHover);
|
||||
style.setProperty('--bim-icon-active', theme.iconActive);
|
||||
style.setProperty('--bim-icon-inverse', theme.iconInverse);
|
||||
|
||||
style.setProperty('--bim-border-default', theme.borderDefault);
|
||||
style.setProperty('--bim-border-subtle', theme.borderSubtle);
|
||||
|
||||
style.setProperty('--bim-component-bg-hover', theme.componentBgHover);
|
||||
style.setProperty('--bim-component-bg-active', theme.componentBgActive);
|
||||
|
||||
style.setProperty('--bim-shadow-sm', theme.shadowSm);
|
||||
style.setProperty('--bim-shadow-md', theme.shadowMd);
|
||||
style.setProperty('--bim-shadow-lg', theme.shadowLg);
|
||||
style.setProperty('--bim-shadow-glow', theme.shadowGlow);
|
||||
|
||||
const gp = theme.overrides?.glassPill;
|
||||
if (gp) {
|
||||
if (gp.sectionBg) style.setProperty('--bim-glass-pill-section-bg', gp.sectionBg);
|
||||
if (gp.sectionBorder) style.setProperty('--bim-glass-pill-section-border', gp.sectionBorder);
|
||||
if (gp.sectionShadow) style.setProperty('--bim-glass-pill-section-shadow', gp.sectionShadow);
|
||||
if (gp.btnBg) style.setProperty('--bim-glass-pill-btn-bg', gp.btnBg);
|
||||
if (gp.btnBorder) style.setProperty('--bim-glass-pill-btn-border', gp.btnBorder);
|
||||
if (gp.btnShadow) style.setProperty('--bim-glass-pill-btn-shadow', gp.btnShadow);
|
||||
if (gp.btnBgHover) style.setProperty('--bim-glass-pill-btn-bg-hover', gp.btnBgHover);
|
||||
if (gp.btnShadowHover) style.setProperty('--bim-glass-pill-btn-shadow-hover', gp.btnShadowHover);
|
||||
if (gp.iconColor) style.setProperty('--bim-glass-pill-icon-color', gp.iconColor);
|
||||
if (gp.iconColorHover) style.setProperty('--bim-glass-pill-icon-color-hover', gp.iconColorHover);
|
||||
}
|
||||
|
||||
this.syncDropdownCssVars(theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步 CSS 变量到所有 dropdown 元素
|
||||
* dropdown 被添加到 body,无法继承容器的 CSS 变量
|
||||
*/
|
||||
private syncDropdownCssVars(theme: ThemeConfig): void {
|
||||
const dropdowns = document.querySelectorAll('.opt-btn-dropdown');
|
||||
dropdowns.forEach(dropdown => {
|
||||
const style = (dropdown as HTMLElement).style;
|
||||
|
||||
style.setProperty('--bim-primary', theme.primary);
|
||||
style.setProperty('--bim-bg-overlay', theme.bgOverlay);
|
||||
style.setProperty('--bim-bg-glass-blur', theme.bgGlassBlur);
|
||||
style.setProperty('--bim-border-subtle', theme.borderSubtle);
|
||||
style.setProperty('--bim-text-primary', theme.textPrimary);
|
||||
style.setProperty('--bim-text-inverse', theme.textInverse);
|
||||
style.setProperty('--bim-icon-default', theme.iconDefault);
|
||||
style.setProperty('--bim-icon-inverse', theme.iconInverse);
|
||||
style.setProperty('--bim-component-bg-hover', theme.componentBgHover);
|
||||
style.setProperty('--bim-component-bg-active', theme.componentBgActive);
|
||||
style.setProperty('--bim-shadow-lg', theme.shadowLg);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,12 +480,13 @@ export class BimButtonGroup implements IBimComponent {
|
||||
textWrapper.appendChild(label);
|
||||
}
|
||||
|
||||
if (button.children && button.children.length > 0) {
|
||||
const arrow = document.createElement('span');
|
||||
arrow.className = 'opt-btn-arrow';
|
||||
arrow.textContent = '▼';
|
||||
textWrapper.appendChild(arrow);
|
||||
}
|
||||
// TODO: 暂时隐藏下拉箭头
|
||||
// if (button.children && button.children.length > 0) {
|
||||
// const arrow = document.createElement('span');
|
||||
// arrow.className = 'opt-btn-arrow';
|
||||
// arrow.textContent = '▼';
|
||||
// textWrapper.appendChild(arrow);
|
||||
// }
|
||||
|
||||
// 只有当有内容时才添加 wrapper
|
||||
if (textWrapper.hasChildNodes()) {
|
||||
@@ -543,6 +629,13 @@ export class BimButtonGroup implements IBimComponent {
|
||||
dropdown.style.flexDirection = 'row'; // 纵向按钮组,菜单横向排列
|
||||
}
|
||||
|
||||
if (this.options.type && this.options.type !== 'default') {
|
||||
dropdown.classList.add(`type-${this.options.type}`);
|
||||
}
|
||||
|
||||
const currentTheme = themeManager.getTheme();
|
||||
dropdown.classList.add(`theme-${currentTheme.name}`);
|
||||
|
||||
// 先添加到 DOM 以便计算尺寸
|
||||
document.body.appendChild(dropdown);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user