Raft 设计系统

基础

颜色

表面、文字、线和角色的颜色,每种颜色的含义,以及它们保证的对比度。

Raft 里的颜色有两层作用。第一层,表面从外到内颜色越来越少:黄色的外框,然后是奶油色的侧边栏,然后是放内容的白色纸面。第二层,每种品牌色都有一个固定的含义,所以屏幕上出现的颜色总在告诉人一件事:他是谁,什么在等他处理,或者某个东西处于什么状态。一种颜色如果什么都不表示,就去掉。

原则

  • 黄色只用在外框上。 外框出现在每个屏幕上,但没人去读它,所以在那里用颜色几乎没有代价。人要读的所有东西(消息、列表、卡片、推入页面的内容)都放在纸面上。外框指桌面端的导航条、网页的顶栏和手机一级页面的顶栏;见页面结构。
  • 每种颜色只有一个含义。 黄色是你,粉色是待办,青色是这一项,橙色是打断,红色是不可撤销。状态颜色也是固定的;见颜色的含义。
  • 一块品牌色就是一张贴纸。 它有 1.5px 的墨色边,上面是墨色文字,两种模式下都一样;见贴纸。
  • 提示是中性色。 轻提示(Toast)和工具提示(Tooltip)用深灰色(layer-hud),不用品牌色,也没有黄色按钮。提示只是附带的信息:黄色的轻提示会和选中状态抢注意力,而黄色只表示「你」(你在哪里、你选了什么、什么在叫你)。

Token

表面

表面的颜色从外框往里一级级递减。在浅色模式下,layer-canvas、layer-card 和 layer-popover 都是白色,靠线来区分;在深色模式下靠明度区分,每一层都比下面那层亮。

Token浅色深色
layer-canvas
#ffffff
#1b1b19
layer-sidebar
#fffaef
#0d0d0b
layer-popover
#ffffff
#292927
layer-backdrop
#000000 / 65%
#000000 / 60%
layer-backdrop-nested
#000000 / 40%
#000000 / 40%
layer-card
#ffffff
#242422
layer-hud
#252429
#292927
layer-frame
#ffd440
#0d0d0b
layer-frame-active
#ffffff
#ffd440
layer-code
#ffffff
#0a0c10
Token用于
layer-frame外框:手机一级页面的顶栏、桌面端导航条、网页顶栏
layer-sidebar桌面端侧边栏
layer-canvas纸面:桌面端主区域、手机的每个屏幕
layer-card凸起的容器:卡片、内嵌分组、输入框、发消息的输入框、标签栏
layer-popover弹出层:菜单、抽屉、底部面板、对话框、个人资料卡
fill-muted下沉填充:轨道、行内代码、骨架屏、中性图块、回应、消息列预览
layer-code代码块和命令行
layer-hud轻提示和工具提示;上面的文字用 foreground-on-hud 和 foreground-on-hud-muted
layer-backdrop居中浮层、模态抽屉、底部面板和图片查看器背后的遮罩
layer-backdrop-nested从一个模态表面里再打开另一个模态表面时,下面那层更浅的遮罩(叠放的浮层)

填充铺在表面里面或上面:下沉填充和悬停叠加层(悬停叠加层)。

Token浅色深色
fill-muted
#f3f3f3
#32322f
fill-strong
#eaeaea
#3a3a37
fill-subtleHover tier subtle (light): hover on large things people read, a row, a message, a readable card, and a row whose menu is open. About 2.5 to 3 OKLab dE in both modes, on paper, the sidebar and cards alike, under every selection tint, so text keeps its contrast.
#141111 / 4%
#fafaf7 / 3%
fill-mediumHover tier medium: hover on small controls (buttons, icon buttons, chips, tabs, segment items) and press on everything, on paper-coloured surfaces. About 5.5 to 6.5 OKLab dE; dark is lighter than light because the same ink alpha shows more on a dark surface.
#141111 / 8%
#fafaf7 / 7%
fill-frame-mediumHover tier medium on the frame (rail items, on-frame buttons, the workspace button): hover and press. Its own alphas because ink shows differently on the yellow and on the near-black frame: 10% on the yellow and 6% on the dark frame land on the medium step, about 6 OKLab dE.
#141111 / 10%
#fafaf7 / 6%

文字和图标

Token浅色深色
foreground
#141111
#e5e5e2
foreground-muted
#141111 / 68%
#c4c4c1
foreground-hint
#141111 / 62%
#9e9e9b
foreground-disabled
#141111 / 30%
#636360
foreground-inverse
#ffffff
#1b1b19
foreground-on-hud
#f3f3f5
#e5e5e2
foreground-on-hud-mutedSecondary text on the HUD: the shortcut in a tooltip, the detail line of a toast.
#f3f3f5 / 70%
#c4c4c1foreground-muted
foreground-on-frame
#141111sticker-ink
#e5e5e2
foreground-on-frame-muted
#564919
#9e9e9b
foreground-on-frame-active
#141111sticker-ink
#141111sticker-ink
foreground-link
#1447e6
#8ec5ff
foreground-active
#141111foreground
#e5e5e2foreground
foreground-hover
#141111foreground
#e5e5e2foreground
Token用于
foreground墨色:正文、标题、控件边框
foreground-muted次要文字:预览、描述、标签
foreground-hint第三级文字:时间、ID、分组标题、占位文字
foreground-disabled禁用的文字和图标
foreground-link正文中的链接
danger-strong错误文字:无效输入框的边框和帮助文字、上传失败

线

线有三种,每种都有含义。线宽见形状。

Token浅色深色
line-strong
#141111
#e5e5e2
line-seam
#141111 / 45%
#fafaf7 / 26%
line-hairline
#141111 / 15%
#fafaf7 / 10%
line-frame-active
#141111sticker-ink
#141111sticker-ink
line-fieldThe frame of a field and the composer: the ink and width of line-strong, drawn 1.5px.
#141111line-strong
#e5e5e2line-strong
line-field-hover
#141111line-strong
#e5e5e2line-strong
Token含义用于
line-hairline在内容里面列表分隔线、卡片轮廓
line-seam在区域之间导航条和侧边栏之间、标题栏和它的内容之间、菜单、抽屉或对话框的边缘
line-strong这是一个控件控件 1.5px 的墨色边框,以及贴纸的边
line-field这是一个字段字段和输入框 1.5px 的墨色外框,墨色和宽度与 line-strong 相同

线、次要文字和叠加层都由一组半透明的墨色阶梯生成。使用上面的角色 token;这些阶梯列在这里仅供参考。

Token浅色深色
ink-2
#141111 / 2%
#fafaf7 / 2%
ink-4
#141111 / 4%
#fafaf7 / 4%
ink-6
#141111 / 6%
#fafaf7 / 6%
ink-8
#141111 / 8%
#fafaf7 / 8%
ink-10
#141111 / 10%
#fafaf7 / 10%
ink-16
#141111 / 16%
#fafaf7 / 16%
ink-20
#141111 / 20%
#fafaf7 / 20%
ink-30
#141111 / 30%
#fafaf7 / 30%
ink-40
#141111 / 40%
#fafaf7 / 40%
ink
#141111
#fafaf7

颜色角色

Token浅色深色
brand-50
#fff9edpalette-yellow-50
#fff9edpalette-yellow-50
brand-100
#fff6e3palette-yellow-100
#fff6e3palette-yellow-100
brand-200
#ffe9b9palette-yellow-200
#ffe9b9palette-yellow-200
brand-300
#ffdf91palette-yellow-300
#ffdf91palette-yellow-300
brand-400
#ffd440
#ffd440
brand-500
#d3ad03palette-yellow-500
#d3ad03palette-yellow-500
brand-600
#a78802palette-yellow-600
#a78802palette-yellow-600
brand-700
#7a6300palette-yellow-700
#7a6300palette-yellow-700
brand-800
#534300palette-yellow-800
#534300palette-yellow-800
brand-900
#2d2300palette-yellow-900
#2d2300palette-yellow-900
brand-950
#1c1500palette-yellow-950
#1c1500palette-yellow-950
brand-strong
#564919
#ffd440
brand-soft
#fff0bd
#876f1f / 20%
brand-edge
#141111sticker-ink
#141111sticker-ink
brand-glow
#ffd440
#ffd440
brand-hoverHovering or pressing a sticker lays sticker-medium (10% ink) over its colour.
color-mix(in srgb, var(--brand-400) 90%, var(--sticker-ink))
color-mix(in srgb, var(--brand-400) 90%, var(--sticker-ink))
brand-active
color-mix(in srgb, var(--brand-400) 90%, var(--sticker-ink))brand-hover
color-mix(in srgb, var(--brand-400) 90%, var(--sticker-ink))brand-hover
Token浅色深色
attention-50
#fff0f4palette-pink-50
#fff0f4palette-pink-50
attention-100
#ffe1e8palette-pink-100
#ffe1e8palette-pink-100
attention-200
#fec1d2palette-pink-200
#fec1d2palette-pink-200
attention-300
#fea0bcpalette-pink-300
#fea0bcpalette-pink-300
attention-400
#ff99c3
#ff99c3
attention-500
#fe7da8palette-pink-400
#fe7da8palette-pink-400
attention-600
#d4086fpalette-pink-600
#d4086fpalette-pink-600
attention-700
#9f0551palette-pink-700
#9f0551palette-pink-700
attention-800
#700238palette-pink-800
#700238palette-pink-800
attention-900
#42011epalette-pink-900
#42011epalette-pink-900
attention-950
#2f0014palette-pink-950
#2f0014palette-pink-950
attention-strong
#c00064
#ffacc7
attention-soft
#ffd6e2
#d0457c / 16%
attention-hover
color-mix(in srgb, var(--attention-400) 90%, var(--sticker-ink))
color-mix(in srgb, var(--attention-400) 90%, var(--sticker-ink))
attention-active
color-mix(in srgb, var(--attention-400) 90%, var(--sticker-ink))attention-hover
color-mix(in srgb, var(--attention-400) 90%, var(--sticker-ink))attention-hover
Token浅色深色
infoEvery solid is a sticker: ink type on the colour in both modes.
#27ccf3
#27ccf3
info-strong
#06414fpalette-cyan-800
#6ccdea
info-muted
#a9e6fepalette-cyan-200
#007592 / 28%
info-soft
#d7f2fe
#005f7a / 18%
info-hover
color-mix(in srgb, var(--info) 90%, var(--sticker-ink))
color-mix(in srgb, var(--info) 90%, var(--sticker-ink))
info-active
color-mix(in srgb, var(--info) 90%, var(--sticker-ink))info-hover
color-mix(in srgb, var(--info) 90%, var(--sticker-ink))info-hover
Token浅色深色
success
#a9d877
#a9d877
success-foreground
#141111sticker-ink
#141111sticker-ink
success-strong
#344522palette-lime-800
#b7e18c
success-muted
#c0f588palette-lime-200
#0c7d43 / 28%
success-soft
#dcfac1
#167641 / 18%
Token浅色深色
warning
#f8a16f
#f8a16f
warning-foreground
#141111sticker-ink
#141111sticker-ink
warning-strong
#5b310fpalette-orange-800
#ffaf76
warning-muted
#fbd1c0palette-orange-200
#ac571d / 28%
warning-soft
#fde6de
#9e511e / 18%
warning-hover
color-mix(in srgb, var(--warning) 90%, var(--sticker-ink))
color-mix(in srgb, var(--warning) 90%, var(--sticker-ink))
warning-active
color-mix(in srgb, var(--warning) 90%, var(--sticker-ink))warning-hover
color-mix(in srgb, var(--warning) 90%, var(--sticker-ink))warning-hover
Token浅色深色
dangerdanger = the destructive sticker (red fill, ink type); danger-strong is the error ink for invalid fields and destructive menu items.
#f97264
#f97264
danger-foreground
#141111sticker-ink
#141111sticker-ink
danger-strong
#b5321a
#f8a49d
danger-muted
#fbbdb9palette-red-200
#d33c30 / 30%
danger-soft
#fddedd
#c93126 / 18%
danger-hover
color-mix(in srgb, var(--danger) 90%, var(--sticker-ink))
color-mix(in srgb, var(--danger) 90%, var(--sticker-ink))
danger-active
color-mix(in srgb, var(--danger) 90%, var(--sticker-ink))danger-hover
color-mix(in srgb, var(--danger) 90%, var(--sticker-ink))danger-hover
Token浅色深色
inactive
#c0b9b1
#c0b9b1
inactive-foreground
#141111sticker-ink
#141111sticker-ink
inactive-soft
#e0dcd7
#32322f

颜色的含义

颜色角色含义用于
黄色brand你外框、导航中的选中项、打开的开关、你所在位置的位置图块、提及你的地方、搜索命中、你打开的评论所对应的段落;你的服务器(工作空间图块,墨色底上的黄色)
粉色attention待办每个屏幕最多一个主按钮;未读计数和提醒圆点
青色info这一项、信息进行中、运行时、外部 agent、进度条;info-soft 用于内容中被单独标出的项、生效中的筛选、信息横幅
橙色warning打断停止、离开或重置的按钮;警告;「待办」状态;错误状态灯
红色danger不可撤销删除按钮
青柠色success完成完成、在线、成功横幅
薰衣草紫palette-lavender-*—待确认,以及没有照片的人
石灰色inactive已关闭已关闭、离线
  • 出了问题时用橙色:红色只用于无法撤销的后果。
  • 蓝色(foreground-link)只用于正文中的链接。
  • 青柠色、薰衣草紫和石灰色只用来标记状态,不要用在别处。

状态

任务和在线状态各有五种颜色,含义永远不变。任务状态的英文写法是 Todo、In Progress、In Review、Done 和 Closed(中文界面为待办、进行中、待确认、完成、已关闭)。

Token浅色深色
task-status-todo
#f8a16f
#ff6900
task-status-todo-soft
#fde6de
#9e511e / 18%
task-status-todo-strong
#5b310fpalette-orange-800
#ffaf76
task-status-in-progress
#27ccf3
#27ccf3
task-status-in-progress-soft
#d7f2fe
#005f7a / 18%
task-status-in-progress-strong
#06414fpalette-cyan-800
#6ccdea
task-status-in-review
#bbafe6
#9d8ada
task-status-in-review-soft
#efecf9
#6853a0 / 24%
task-status-in-review-strong
#442b7cpalette-lavender-800
#ccc4ecpalette-lavender-300
task-status-done
#a9d877
#20c16b
task-status-done-soft
#dcfac1
#167641 / 18%
task-status-done-strong
#344522palette-lime-800
#6ed892
task-status-closed
#c0b9b1
#8f8f8d
task-status-closed-soft
#e0dcd7
#32322f
task-status-closed-strong
#3e3b38palette-stone-800
#9e9e9b
任务状态Token在线状态灯Token
待办(橙色)task-status-todo在线(青柠色)presence-online
进行中(青色)task-status-in-progress忙碌(黄色)presence-busy
待确认(薰衣草紫)task-status-in-review错误(橙色)presence-error
完成(青柠色)task-status-done离线(石灰色)presence-offline
已关闭(石灰色)task-status-closed外部 agent(青色)presence-external
Token浅色深色
presence-online
#a9d877
#a9d877
presence-busy
#ffd440
#ffd440
presence-error
#f8a16f
#f8a16f
presence-offline
#c0b9b1
#c0b9b1
presence-external
#27ccf3
#27ccf3
  • 状态标签片放在对应的 task-status-*-soft 色调上。
  • presence-busy 有自己的值,而不是指向 brand,这样品牌色变了,忙碌的样子也不会跟着变。
  • presence-offline 是色板里的石灰色,不是默认的灰色:raft-ui 不使用 Tailwind 的默认色板,所以每个在线状态灯都来自同一个色板。
  • 在线状态灯从不闪烁;见动效。

柔和色调

柔和色调(*-soft)是高亮,永远不是贴纸:它没有边框。

  • 状态标签片和运行时标签片画成柔和色调,用一个方形像素点或一个图标承载饱和色,而不是画成带墨色边框的饱和色块。一个屏幕上可能有十几个这样的标签片,饱和色只占一个像素点那么大时,屏幕才能保持安静。
色调用于
brand-soft菜单高亮、忙碌标签片、文本选区
info-soft内容中的选中项、筛选、信息横幅、运行时标签片、消息列引用、通知里的消息
attention-soft频道引用、你添加的回应
success-soft成功横幅、完成标签片
warning-soft警告横幅、待办标签片、通知里的错误和警告
danger-soft危险横幅
task-status-in-review-soft待确认标签片
task-status-closed-soft已关闭标签片
  • 用量计量条用完时,轨道用 warning-muted 加 1px 的 warning 边,不用 warning-soft:在深色画布上 warning-soft 只有 1.16:1,比空轨道还淡,而柔和色调不能加边(Meter)。

悬停叠加层

悬停和按下时,在控件上叠一层半透明的叠加层,而不是改变它的填充色,分两档;见悬停和按下。

Token档位作用于
fill-subtle轻悬停在行、消息或可阅读的卡片上(评论卡片、附件卡片、任务卡片、回复栏),以及菜单打开着的行
fill-medium中悬停在纸面色的控件上(按钮、图标按钮、标签片、标签页、分段),以及按下任何东西
sticker-medium中悬停和按下彩色贴纸
fill-frame-medium中悬停和按下外框上的任何东西

fill-subtle 比每种选中色调都浅,所以悬停的行永远不会看起来像被选中,文字也保持原有的对比度。这些 token 在分成两档之前的旧名称作为已弃用的别名继续可用,直到 raft-ui 1.0;codemods/token-names.mjs 会把它们改成新名称。

贴纸

贴纸是一块品牌色:头像、选中项、位置图块、主按钮、徽标。

  • 给每块品牌色加上 1.5px 的 line-strong 边:贴纸和纸面之间的对比度只有 1.4:1 到 2.8:1,没有边的话,贴纸撑不住自己的形状。
  • 贴纸上用墨色文字(sticker-ink),两种模式下都不用白色。
  • 深色模式下不要反转贴纸。贴纸颜色在两种模式下的值相同;深色模式改为加上模切边(见深色模式)。
  • 不要给控件加阴影。硬朗的贴纸阴影只用于品牌插画;见层级。
Token浅色深色
sticker-ink
#141111
#141111
sticker-paper
#ffffff
#ffffff
sticker-edge
#141111 / 0%
#fafaf7 / 35%
sticker-mediumHover tier medium on a colour sticker (primary, warning and danger buttons, colour badges, the selected segment on press): hover and press, 10% ink in both modes.
#141111 / 10%
#141111 / 10%

对比度

  • foreground、foreground-muted 和 foreground-hint 在每种表面、每种柔和色调和每种弹出层上,两种模式下,以及在它们之上的悬停行上,对比度都至少是 4.5:1。没有需要记的例外。
  • foreground-hint 在浅色模式下比 60% 墨色稍深,在深色模式下稍浅。60% 墨色是产品采用这些 token 之前用的值,在某些色调和弹出层上达不到 4.5:1。第三级文字承载着人需要读的时间、ID 和计数,所以它和正文享有同样的保证。
  • 错误文字和无效输入框的边框用 danger-strong,这是一种深红色,在纸面上的对比度是 6.1:1。产品之前用的较亮的红色在白色上只有 4.2:1 和 2.8:1,低于文字需要的 4.5:1。删除按钮保留 danger,因为它上面的文字是墨色。
  • 贴纸上的墨色对比度至少是 6.8:1。
  • line-seam 在白色上是 3.0:1,在黄色上是 2.8:1。

色板

角色 token 指向一个小色板。只有在没有合适角色的地方才直接用色板,比如没有照片的人用薰衣草紫。色板 token 的形式是 palette-<color>-<step>,对应的简写工具类是 bg-palette-<color>。

Token浅色深色
palette-yellow-50
#fff9ed
#fff9ed
palette-yellow-100
#fff6e3
#fff6e3
palette-yellow-200
#ffe9b9
#ffe9b9
palette-yellow-300
#ffdf91
#ffdf91
palette-yellow-400
#ffd441
#ffd441
palette-yellow-500
#d3ad03
#d3ad03
palette-yellow-600
#a78802
#a78802
palette-yellow-700
#7a6300
#7a6300
palette-yellow-800
#534300
#534300
palette-yellow-900
#2d2300
#2d2300
palette-yellow-950
#1c1500
#1c1500
palette-lavender-50
#f7f6fc
#f7f6fc
palette-lavender-100
#efecf9
#efecf9
palette-lavender-200
#dcd7f2
#dcd7f2
palette-lavender-300
#ccc4ec
#ccc4ec
palette-lavender-400
#bbafe6
#bbafe6
palette-lavender-500
#9d8ada
#9d8ada
palette-lavender-600
#7f62cb
#7f62cb
palette-lavender-700
#6341b0
#6341b0
palette-lavender-800
#442b7c
#442b7c
palette-lavender-900
#251548
#251548
palette-lavender-950
#170c31
#170c31
palette-pink-50
#fff0f4
#fff0f4
palette-pink-100
#ffe1e8
#ffe1e8
palette-pink-200
#fec1d2
#fec1d2
palette-pink-300
#fea0bc
#fea0bc
palette-pink-400
#fe7da8
#fe7da8
palette-pink-500
#fe2f8b
#fe2f8b
palette-pink-600
#d4086f
#d4086f
palette-pink-700
#9f0551
#9f0551
palette-pink-800
#700238
#700238
palette-pink-900
#42011e
#42011e
palette-pink-950
#2f0014
#2f0014
palette-cyan-50
#ecf9ff
#ecf9ff
palette-cyan-100
#d7f2fe
#d7f2fe
palette-cyan-200
#a9e6fe
#a9e6fe
palette-cyan-300
#68dafd
#68dafd
palette-cyan-400
#28ccf3
#28ccf3
palette-cyan-500
#1ea6c6
#1ea6c6
palette-cyan-600
#15849f
#15849f
palette-cyan-700
#0e6276
#0e6276
palette-cyan-800
#06414f
#06414f
palette-cyan-900
#02252f
#02252f
palette-cyan-950
#01161c
#01161c
palette-orange-50
#fef5f1
#fef5f1
palette-orange-100
#fde6de
#fde6de
palette-orange-200
#fbd1c0
#fbd1c0
palette-orange-300
#f9b899
#f9b899
palette-orange-400
#f8a16f
#f8a16f
palette-orange-500
#dd7e34
#dd7e34
palette-orange-600
#ad6127
#ad6127
palette-orange-700
#83481a
#83481a
palette-orange-800
#5b310f
#5b310f
palette-orange-900
#331905
#331905
palette-orange-950
#220e02
#220e02
palette-lime-50
#f1fde9
#f1fde9
palette-lime-100
#dcfac1
#dcfac1
palette-lime-200
#c0f588
#c0f588
palette-lime-300
#b4e67f
#b4e67f
palette-lime-400
#a9d877
#a9d877
palette-lime-500
#8ab261
#8ab261
palette-lime-600
#6b8b4a
#6b8b4a
palette-lime-700
#506836
#506836
palette-lime-800
#344522
#344522
palette-lime-900
#1c2711
#1c2711
palette-lime-950
#101808
#101808
palette-red-50
#fef1f0
#fef1f0
palette-red-100
#fddedd
#fddedd
palette-red-200
#fbbdb9
#fbbdb9
palette-red-300
#fa9991
#fa9991
palette-red-400
#f97264
#f97264
palette-red-500
#eb4423
#eb4423
palette-red-600
#bb3419
#bb3419
palette-red-700
#8e2510
#8e2510
palette-red-800
#621708
#621708
palette-red-900
#3e0b03
#3e0b03
palette-red-950
#280501
#280501
palette-stone-50
#f7f6f5
#f7f6f5
palette-stone-100
#efedeb
#efedeb
palette-stone-200
#e0dcd7
#e0dcd7
palette-stone-300
#d2cbc2
#d2cbc2
palette-stone-400
#c0b9b1
#c0b9b1
palette-stone-500
#9d9891
#9d9891
palette-stone-600
#7b7671
#7b7671
palette-stone-700
#5d5955
#5d5955
palette-stone-800
#3e3b38
#3e3b38
palette-stone-900
#23211f
#23211f
palette-stone-950
#141312
#141312
palette-cream-50
#fffdf9
#fffdf9
palette-cream-100
#fffcf5
#fffcf5
palette-cream-200
#fffaef
#fffaef
palette-cream-300
#f9eccf
#f9eccf
palette-cream-400
#ebd38f
#ebd38f
palette-cream-500
#d2b100
#d2b100
palette-cream-600
#a78c00
#a78c00
palette-cream-700
#7c6800
#7c6800
palette-cream-800
#554500
#554500
palette-cream-900
#312700
#312700
palette-cream-950
#191300
#191300
  • 深色模式:深色模式下什么会变、什么不变。
  • 状态:悬停、选中、未读和错误的颜色。
  • 品牌:每种页面可以用多少品牌色。
  • Button:什么操作用什么颜色的按钮。