admin 管理员组

文章数量: 1184232

tldraw主题系统:深色模式与自定义主题支持

概述

tldraw作为一款现代化的无限画布白板工具,提供了强大的主题系统支持,包括深色模式、浅色模式和系统跟随模式。其主题系统基于CSS自定义属性(CSS Custom Properties)构建,支持灵活的自定义和扩展。

核心主题架构

CSS变量系统

tldraw使用一套精心设计的CSS变量系统来管理主题颜色和样式:

/* 文本颜色变量 */
--tl-color-text-1: #000000;      /* 主要文本颜色 */
--tl-color-text-3: #666666;      /* 次要文本颜色 */
/* 背景和面板颜色 */
--tl-color-background: #ffffff;   /* 画布背景 */
--tl-color-panel: #f8f9fa;       /* 面板背景 */
--tl-color-low: #f0f0f0;         /* 低强调背景 */
/* 交互状态颜色 */
--tl-color-muted-1: #e0e0e0;     /* 静默状态1 */
--tl-color-muted-2: #d0d0d0;     /* 静默状态2 */
--tl-color-selected: #007bff;     /* 选中状态 */
--tl-color-selected-contrast: #ffffff; /* 选中对比色 */
/* 功能颜色 */
--tl-color-primary: #007bff;      /* 主要颜色 */
--tl-color-danger: #dc3545;       /* 危险颜色 */
--tl-color-focus: #007bff;        /* 焦点边框 */
--tl-color-hint: #e6f3ff;         /* 提示背景 */

主题切换机制

tldraw通过 ColorSchemeMenu 组件实现主题切换功能:

const COLOR_SCHEMES = [
  { colorScheme: 'light' as const, label: 'theme.light' },
  { colorScheme: 'dark' as const, label: 'theme.dark' },
  { colorScheme: 'system' as const, label: 'theme.system' },
]

深色模式实现

深色主题变量

在深色模式下,所有颜色变量都会相应调整:

/* 深色模式下的颜色变量 */
[data-color-scheme="dark"] {
  --tl-color-text-1: #ffffff;
  --tl-color-text-3: #aaaaaa;
  --tl-color-background: #1a1a1a;
  --tl-color-panel: #2d2d2d;
  --tl-color-low: #333333;
  --tl-color-muted-1: #444444;
  --tl-color-muted-2: #555555;
}

自动检测机制

tldraw能够自动检测系统主题偏好:

const currentColorScheme = useValue(
  'colorScheme',
  () => editor.user.getUserPreferences().colorScheme ??
        (editor.user.getIsDarkMode() ? 'dark' : 'light'),
  [editor]
)

自定义主题配置

基础自定义方法

开发者可以通过覆盖CSS变量来自定义主题:

.tl-container {
  /* 覆盖主要品牌颜色 */
  --tl-color-primary: #ff6b35;
  --tl-color-selected: #ff6b35;
  
  /* 自定义背景颜色 */
  --tl-color-background: #f5f5f7;
  --tl-color-panel: #ffffff;
  
  /* 调整圆角半径 */
  --tl-radius-2: 8px;
  --tl-radius-3: 12px;
  --tl-radius-4: 16px;
}

高级主题配置

对于更复杂的自定义需求,可以通过组件属性配置:

import { Tldraw } from 'tldraw'
function App() {
  return (
    <Tldraw
      overrides={{
        components: {
          // 自定义主题组件
          ThemeProvider: CustomThemeProvider,
        },
        // 主题配置
        theme: {
          colors: {
            primary: '#ff6b35',
            background: '#f5f5f7',
            text: {
              primary: '#333333',
              secondary: '#666666'
            }
          }
        }
      }}
    />
  )
}

响应式主题系统

断点系统

tldraw的主题系统支持响应式设计,包含多个断点:

const breakpoints = {
  mobile: 600,
  tablet: 900,
  desktop: 1200
}

移动端优化

在移动设备上,主题系统会自动调整:

@media (max-width: 600px) {
  .tlui-button {
    height: 48px;
    min-width: 48px;
  }
  
  .tlui-icon {
    width: 20px;
    height: 20px;
  }
}

主题状态管理

用户偏好持久化

tldraw会自动保存用户的主题偏好:

// 更新用户主题偏好
editor.user.updateUserPreferences({ colorScheme: 'dark' })
// 获取当前主题
const currentTheme = editor.user.getUserPreferences().colorScheme

主题事件追踪

系统会追踪主题切换事件:

trackEvent('color-scheme', { 
  source: 'menu', 
  value: colorScheme 
})

自定义主题实践指南

1. 基础颜色定制

/* 自定义品牌主题 */
:root {
  --tl-color-primary: #4a90e2;
  --tl-color-primary-dark: #357abd;
  --tl-color-primary-light: #6ba5e7;
  
  --tl-color-secondary: #ff6b35;
  --tl-color-accent: #00c853;
}
.tl-container {
  --tl-color-selected: var(--tl-color-primary);
  --tl-color-focus: var(--tl-color-primary);
}

2. 完整主题方案

// 创建完整的自定义主题
const customTheme = {
  colors: {
    primary: {
      main: '#4a90e2',
      dark: '#357abd',
      light: '#6ba5e7'
    },
    background: {
      main: '#f8f9fa',
      panel: '#ffffff',
      low: '#f0f0f0'
    },
    text: {
      primary: '#333333',
      secondary: '#666666',
      disabled: '#999999'
    }
  },
  spacing: {
    base: 4,
    sm: 8,
    md: 16,
    lg: 24,
    xl: 32
  },
  borderRadius: {
    sm: 4,
    md: 8,
    lg: 12,
    xl: 16
  }
}

3. 动态主题切换

// 动态主题切换示例
function useDynamicTheme() {
  const [theme, setTheme] = useState('light')
  
  useEffect(() => {
    const root = document.documentElement
    root.setAttribute('data-theme', theme)
    
    // 应用主题变量
    const themeConfig = themes[theme]
    Object.entries(themeConfig.colors).forEach(([key, value]) => {
      root.style.setProperty(`--tl-color-${key}`, value)
    })
  }, [theme])
  
  return { theme, setTheme }
}

主题系统最佳实践

1. 一致性设计

2. 可访问性考虑

确保主题满足WCAG 2.1可访问性标准:

元素类型 对比度要求 测试工具
正常文本 4.5:1 Contrast Checker
大文本 3:1 Accessibility Insights
用户界面组件 3:1 Color Safe

3. 性能优化

// 主题切换性能优化
const ThemeContext = createContext()
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState(() => {
    // 从localStorage或系统偏好获取初始主题
    return localStorage.getItem('theme') || 'system'
  })
  
  // 使用useMemo避免不必要的重渲染
  const value = useMemo(() => ({ theme, setTheme }), [theme])
  
  return (
    <ThemeContext.Provider value={value}>
      <div data-theme={theme}>
        {children}
      </div>
    </ThemeContext.Provider>
  )
}

故障排除与调试

常见问题解决

  1. 主题不生效

    /* 确保CSS特异性足够 */
    .tl-container.custom-theme {
      --tl-color-primary: #your-color !important;
    }
    
  2. 颜色对比度问题

    // 使用颜色对比度检查工具
    function checkContrast(color1, color2) {
      // 实现对比度计算逻辑
      return contrastRatio >= 4.5
    }
    
  3. 移动端主题异常

    /* 添加移动端特定的主题覆盖 */
    @media (max-width: 600px) {
      .tl-container {
        --tl-color-panel: #ffffff;
      }
    }
    

总结

tldraw的主题系统提供了强大而灵活的定制能力,支持:

  • ✅ 深色/浅色模式切换
  • ✅ 系统主题跟随
  • ✅ 完整的CSS变量体系
  • ✅ 响应式设计支持
  • ✅ 用户偏好持久化
  • ✅ 可访问性优化
  • ✅ 高性能主题切换

通过合理的主题配置,开发者可以轻松创建符合品牌调性的自定义白板体验,同时确保良好的用户体验和可访问性。

本文标签: 变量 深色模式 编程