IvyLabs Design BostonIvy 爬山虎 v0.3.0

风格切换

三种风格

风格 id 一句话 适合
青藤 Clean clean 安静克制,白墙上只在关键处冒出绿意 团队日常协作、长时间盯屏;默认风格
萌虎 Sticker sticker 粗描边、硬阴影、糖果色,完成任务像贴贴纸 个人、学生、小团队
像素 Pixel pixel 等宽字体、像素小虎、快捷键提示常驻,信息密度最高 开发者、运维、键盘党

每种风格都有亮色和暗色,主题 id 写作 <style>-<mode>,一共 6 套:clean-light、clean-dark、sticker-light、sticker-dark、pixel-light、pixel-dark。

什么会变,什么不变

切换风格只换皮,不搬家具。

跟着风格变 所有风格都一样
颜色(53 个语义 token 的取值) 信息架构:概览、即将到期、通知、项目树、过滤器、团队、管理面板
字体与字号阶梯 页面分区:侧栏、列表、详情面板、看板分栏的位置
圆角、描边粗细、阴影 组件清单和组件的属性
密度:行高、控件高度、侧栏宽度 快捷键
图标描边粗细和端点 文案的意思(口吻可以不同)
动效节奏 语义色的含义:红是紧急或逾期,黄是高优先级或今天到期,绿是完成
少数组件写法(勾选框、优先级、标签、指派人、吉祥物、空状态口吻) 无障碍要求

风格专属写法只限于 README「使用规则」表里列出的几处,组件靠 data-theme 前缀或 Flutter BiShape 里的枚举来分支,其余一律走 token。设计稿里出现过的「萌虎详情用弹窗」「像素底部状态栏」这类布局差异不跟风格走:详情面板在三种风格里都是右侧面板(窄屏全屏);快捷键提示条是一个独立开关「显示快捷键提示」,像素风格默认打开,其他风格默认关闭。

设置入口

存储与同步

实现要点

Web(bostonivy-web)

<head>
  <link rel="stylesheet" href="/bostonivy-tokens.css">
  <script>
    // 在首帧之前设置主题,避免闪烁
    try {
      var a = JSON.parse(localStorage.getItem('bostonivy.appearance') || '{}');
      var dark = a.mode === 'dark' || (a.mode !== 'light' && matchMedia('(prefers-color-scheme: dark)').matches);
      document.documentElement.dataset.theme = (a.style || 'clean') + '-' + (dark ? 'dark' : 'light');
    } catch (e) {}
  </script>
</head>

组件只读语义变量和风格别名(var(--accent)、var(--radius-md)、var(--type-task)),不认具体风格。需要按风格换写法的那几处,用 [data-theme^="pixel-"] .x { … } 这样的选择器。

Flutter(bostonivy-macos、bostonivy-android)

MaterialApp(
  theme: bostonIvyTheme(style, Brightness.light),
  darkTheme: bostonIvyTheme(style, Brightness.dark),
  themeMode: mode, // ThemeMode.system / light / dark
);

// 组件里
final c = Theme.of(context).extension<BiColors>()!;
final s = Theme.of(context).extension<BiShape>()!;
if (s.checkbox == BiCheckboxVariant.bracket) { /* 像素风格的 [ ] 勾选 */ }

切换风格时用 AnimatedTheme 过渡,时长取 s.motionDuration;像素风格的过渡时长是 80ms,等于直接切换。

App 图标跟随风格