跳到主要内容

主题与 UI 样式

@ydesign/react-editor 的界面由 内置 shadcn 组件 + 语义 CSS 变量 驱动。接入时引入一份样式,即可用内置主题 API 切换明暗与主色,或覆盖 CSS 变量做品牌定制。

样式栈一览

层级技术选型用途
组件内置 shadcn(Button、Dialog、Select、Tooltip…)编辑器全部表单 / 反馈 UI
主题令牌语义 CSS 变量--primary--background…)颜色、圆角、边框;明暗与预设都写在这些变量上
原子类Tailwind CSS v4(已编译进 style.css布局、间距、dark: 变体
布局容器styled-componentsDesignEditorContainer / SidePanelWrap / WorkspaceWrap
主题 API@ydesign/react-editor/themeuseTheme / setTheme / ThemeSwitcher
画布引擎@ydesign/core无 UI 样式依赖

消费方不必再安装 Tailwind、shadcn 或独立 token 包;一行样式即可:

import '@ydesign/react-editor/style.css';

1. 快速接入:内置主题切换

Demo / 脚手架已提供完整开关,业务 Topbar 可直接挂上:

import '@ydesign/react-editor/style.css';
import { ThemeSwitcher } from '@ydesign/react-editor/theme';

export function Topbar() {
return (
<header>
{/* 明暗三段切换 + 主色预设圆点 */}
<ThemeSwitcher />
</header>
);
}

也可拆开用:

import { ModeToggle, PresetPicker } from '@ydesign/react-editor/theme';

<ModeToggle /> {/* light / dark / system */}
<PresetPicker /> {/* 主色预设 */}

状态是模块级单例,持久化到 localStorage(key:ydl-theme)。ThemeProvider 可选,仅用于挂载时写入默认值:

import { ThemeProvider } from '@ydesign/react-editor/theme';

<ThemeProvider defaultMode="system" defaultPreset="blue">
<App />
</ThemeProvider>

2. 主题如何工作

setTheme({ mode, preset })


document.documentElement
├─ classList.toggle('dark', isDark) ← Tailwind / shadcn 暗色
└─ style.setProperty('--primary', …) ← 当前预设主色
style.setProperty('--primary-foreground', …)
style.setProperty('--sidebar-primary', …)

维度取值效果
mode'light' | 'dark' | 'system'控制 <html> 是否带 .darksystem 跟随 prefers-color-scheme
preset'neutral' | 'blue' | 'orange' | …覆盖 --primary / --sidebar-primary 等(亮暗各有一套色值)
resolvedMode'light' | 'dark'system 解析后的实际明暗,只读

内置预设见 PRESETS(neutral、amber、blue、cyan、emerald、fuchsia、green、indigo、lime、orange、pink、purple、red、rose、sky、teal、violet、yellow 等)。默认:mode: 'light'preset: 'neutral'

底层变量定义在包内 globals.css:root / .dark;Tailwind 通过 @custom-variant dark (&:is(.dark *)) 识别暗色。


3. 编程式控制

3.1 React:useTheme

import { useTheme } from '@ydesign/react-editor/theme';

function BrandBar() {
const { mode, resolvedMode, preset, color, setMode, setPreset, toggleMode } = useTheme();

return (
<div>
<span>当前:{resolvedMode} / {preset}</span>
<button type="button" onClick={() => setMode('dark')}>深色</button>
<button type="button" onClick={() => setPreset('orange')}>橙色品牌</button>
<button type="button" onClick={toggleMode}>轮换 light → dark → system</button>
<span style={{ color }}>主色预览</span>
</div>
);
}

3.2 非 React / 启动时:setTheme

import { setTheme, getTheme, subscribeTheme } from '@ydesign/react-editor/theme';

// 启动时强制品牌色
setTheme({ mode: 'system', preset: 'blue' });

const current = getTheme(); // { mode, preset, resolvedMode }

const unsub = subscribeTheme(state => {
console.log('theme changed', state);
});

4. 品牌定制:覆盖语义变量

预设不够时,直接覆盖 CSS 变量即可;shadcn 组件与编辑器布局都会跟着变。

/* 全局品牌色(在引入 style.css 之后) */
:root {
--primary: oklch(0.55 0.18 40);
--primary-foreground: oklch(0.99 0 0);
--radius: 0.5rem;
--font-sans: 'PingFang SC', 'Helvetica Neue', sans-serif;
}

.dark {
--primary: oklch(0.72 0.14 40);
--primary-foreground: oklch(0.2 0 0);
}

常用变量:

变量用途
--background / --foreground页面底 / 正文
--card / --popover卡片、弹出层
--primary / --primary-foreground主按钮、高亮、选中态
--muted / --muted-foreground次要背景 / 说明文字
--border / --input / --ring边框、输入框、焦点环
--destructive危险操作
--sidebar*侧栏相关
--radius全局圆角基准

在组件里也可以用 Tailwind 语义色:bg-backgroundtext-foregroundbg-primaryborder-bordertext-muted-foreground 等(已映射到上表变量)。

注意: 若同时使用 ThemeSwitcher / setTheme(preset),预设会在运行时再次写入 --primary 等。品牌色若要「锁死」,请固定一个 preset,或在业务里自行 setProperty,不要和用户切换预设冲突。


5. 局部样式覆盖

变量覆盖不了的细节,可用稳定 class / 属性选择器。部分历史类名仍带 polotno- 前缀(兼容遗留),新代码优先用语义变量与 Tailwind。

/* 编辑器最外层 */
.polotno-app-container {
background: var(--background);
color: var(--foreground);
}

/* 侧栏 Tab 选中态跟主色 */
.polotno-side-panel-tab.active {
color: var(--primary);
}

/* 工作区底 */
.polotno-workspace-container {
background: var(--muted);
}

自建壳里也可以直接用语义类:

<div className="flex h-screen bg-background text-foreground">
<aside className="w-64 border-r border-border bg-sidebar text-sidebar-foreground"></aside>
<main className="flex-1"></main>
</div>

6. 字体

范围怎么改
UI 字体覆盖 --font-sans / --font-heading,或在容器上设 font-family
画布文字字体与 UI 无关,走 store.fonts / 字体管理,见 编辑器配置 · 字体
:root {
--font-sans: 'Inter', 'PingFang SC', system-ui, sans-serif;
}

7. 注意事项

  1. 必须引入 import '@ydesign/react-editor/style.css',否则组件几乎无样式。
  2. 消费方不必自装 Tailwind;style.css 已含编译后的 utility。若业务项目自己也用 Tailwind v4,注意不要与包内语义色变量定义冲突。
  3. 暗色模式通过 <html class="dark"> 生效;推荐用 setTheme / ThemeSwitcher,不要手写散落的 class 切换。
  4. SSR:首屏前根据 cookie / UA 设好 class="dark" 与关键变量,避免亮→暗闪烁;useTheme 在服务端有 light/neutral 的 fallback snapshot。
  5. @ydesign/core 画布本身无主题;画布背景色是设计稿数据(workarea fill),不是 UI --background

延伸阅读