Claude Code · Codex · Gemini 供应商切换器

CC Switch 设计系统

桌面端(Tauri + React)的视觉与交互规范。令牌直接取自 src/index.css 与 tailwind.config.cjs: 中性黑白骨架、主题色 #F97316 只落在操作色上, 直连 / 路由 / 聚合三种模式各有一套颜色,13px 正文、6 / 10 / 14 三档圆角,明暗双主题一一对应。

Tauri 2 · React 18 Tailwind 3 · Radix · shadcn/ui lucide 图标 主题色 #F97316
基础 / 01

色彩

骨架是中性灰,彩色只表达「能操作」和「是什么状态」。 主题色只有一个:橙 #F97316,它占的是 --action-* 和 --ring 这组槽位—— 一个视图只有一个实心橙按钮。模式色、语义色各管各的,不和主题色混用。

主题色 · 操作色

--action-bg #F97316
50 · soft#FFF1E6
400 · 深色文字#FB923C
500 · 主题色#F97316
600 · hover#EA620A
700 · 浅色文字#C2410C
已勾选 文字链接

对比度:浅色主题实心按钮白字 2.8:1,按钮文字统一用 600 字重补偿;橙色当文字用时一律换 --action-text(浅 #C2410C 5.2:1 / 深 #FB923C 7.5:1)。深色主题实心按钮压暗为 #EA580C + 白字(3.6:1),焦点描边用更沉的 #D77A3C。

中性面与文字

bg-app
#FFFFFF / #1C1C1E
内容区底
bg-sidebar
#F5F5F7 / #161618
侧栏
bg-subtle
#EFEFF2 / #26262A
hover、分段轨道、通知
bg-selected
#E4E4EA / #313136
侧栏当前项
bg-card · surface
#FFFFFF / #2E2E33
卡片、弹层、输入
border-strong
#CFCFD6 / #4A4A52
描边按钮、hover 卡片
Aa
text-1 · fg-1
#18181B / #F4F4F5
标题、正文
Aa
text-2 · fg-2
#52525B / #D0D0D8
次要文字、图标
Aa
text-3 · fg-3
#65656E / #B5B5BD
占位、辅助说明
Tip
inverse
#18181B / #F4F4F5
HoverTip 胶囊

模式色

直连 direct
fill#0A84FF
text#0063C7
soft#EAF3FF
solid#0066CC
路由 route
fill#0D9488
text#06726B
soft#E7F6F4
solid#0F766E
聚合 stack
fill#7C3AED
text#6D28D9
soft#F2ECFE
solid#6D28D9

模式色只出现在:模式 tab、侧栏模式标签、当前生效的供应商卡片、模式切换的主按钮。其他地方不用。

语义色

正常
success
#16A34A · text #007634
健康、额度充足、已连接
注意
warning
#D97706 · text #A64A00
额度将尽、需重新登录
失败
danger
#DC2626 · text #B91C1C
请求失败、删除
chart-1
#0891B2 / #38BDF8
图表主序列
heat-1…4
chart-1 32% / 62% / 100% · #0E7490
热力图色阶(浅色);深色为 chart-1 30/50/75/100%
chart-2
#DB2777 / #F472B6
图表对比序列

橙 vs 琥珀:主题橙和 warning 琥珀色相接近。警告永远是「soft 底 + 三角图标 + 文字」,从不单独用一块橙/琥珀色表达状态;橙色只出现在能点的东西上。

基础 / 02

字体

系统字体栈(SF Pro / 苹方 / Segoe UI / 微软雅黑),不加载网络字体。正文 13px,桌面工具的密度; 字号只用下面 8 个角色(text-badge … text-metric),数字列用等宽数字。

metric24 / 32 · 600$12.48 · 1,284,302
page18 / 26 · 600Claude Code
title16 / 24 · 600编辑供应商
section15 / 22 · 600路由设置
strong14 / 20 · 500Anthropic 官方
body13 / 20 · 400切换后 Claude Code 下一次请求就走新的供应商,不用重启终端。
caption12 / 18 · 400api.anthropic.com · 上次使用 3 分钟前
badge11 / 16 · 500路由
mono12 · ui-monospacesk-ant-•••• · claude-sonnet-5-5 · 200 OK
基础 / 03

间距 · 圆角

4px 基础刻度。页面左右留白 24px,卡片之间 8px,卡片内 12px。控件高度只有三档:28(卡片、对话框里)、32(页头、输入框)、36(分段控件、页签)。

1 · 4图标与文字
1.5 · 6按钮内图标间距
2 · 8卡片列表间距
3 · 12卡片内边距
4 · 16模式行元素间距
5 · 20对话框内边距
6 · 24页面左右留白
control6px · 按钮 / 输入 / 侧栏行
panel10px · 卡片 / 分段 / 通知
dialog14px · 对话框 / 命令面板
full徽章 / 开关 / HoverTip

嵌套圆角:内圆角 = 外圆角 − 内衬。分段控件轨道 10、内衬 3 → 选中块 7。

基础 / 04

层级 · 阴影

平面靠描边分层,阴影只给「浮起来」的东西。深色主题的 shadow-sm 带一圈 8% 白描边,代替看不见的投影。

shadow-v7-sm分段选中块 · 卡片 hover
shadow-v7-md菜单 · 说明卡 · HoverTip · 拖拽中
shadow-v7-lg对话框 · 抽屉 · 命令面板

z 轴:对话框 40 → 嵌套 50 → 确认 60 → 命令面板 80 → Tooltip 130 → 说明卡 120(与 Tooltip 互斥,不会同时出现)。

基础 / 05

动效

快、短、只改颜色和位置。默认 150ms;菜单 / 弹层 / 提示淡入 + 轻微放大(tailwindcss-animate 的 animate-in fade-in-0 zoom-in-95),关闭时反向;分段选中块、页签下划线 200ms 滑动;打开菜单的触发器按下不缩放;按下按钮缩到 scale .96;系统开了「减少动态效果」时 framer-motion 位移全部跳过; 切换明暗主题期间暂停所有过渡(.theme-switching),避免整页闪一下。

active · scale .96
悬停卡片
描边 + 阴影 150ms
hover · border / shadow
开关 · 150ms
HoverTip · 0 延迟
组件 / 01 · src/components/ui/button.tsx

按钮

一个视图只有一个实心按钮。其余用描边 neutral(卡片上的「切换」「设为默认」)或透明 quiet(页头次要操作)。 模式色实心按钮只用于「切换到这个模式」。

solid · 主题色
neutral
quiet
destructive
neutral · disabled

模式色按钮

尺寸

compact · 28 · 卡片 / 对话框
regular · 32 · 页头 / 模式切换
icon-compact · 28 见方
组件 / 02 · src/components/ui/hover-tip.tsx

图标按钮 · HoverTip

工具栏、卡片操作、模式行右侧一律用纯图标按钮,文字放进 HoverTip:鼠标移上去立即出现深色胶囊,说清楚这一下会做什么。 按钮本身仍要 aria-label。

规格

胶囊圆角 · inverse 底 · 12px / 500 · 内边距 6×12 · 距触发元素 6px · shadow-md · 默认在下方,碰边自动翻转。延迟 0,相邻按钮之间移动不再等待。

写法

<HoverTip content="切换到路由"><button aria-label="路由"…/></HoverTip>。内容写动作(动词开头)或「名字 + 状态」,一句话,不放链接和按钮。

HoverTip 与 HelpTip 分工:HoverTip 只报「这个按钮是什么 / 做什么」;规则和术语解释放 HelpTip 的「?」说明卡(见通知条一节)。

组件 / 03

输入

高 32、圆角 6、border-strong 描边;聚焦时描边和 3px 光晕换主题色。标签在上,说明在下,出错时说明换成红字,不弹 toast。密钥、URL、模型名用等宽。

只在 CC Switch 里显示
保存在本机配置文件里
要以 http:// 或 https:// 开头
组件 / 04 · switch.tsx · checkbox.tsx

开关 · 勾选

开关轨道 30×18(表格里成排用 26×16),开 = 主题色、圆点反色;点击区域用伪元素扩到 38×28。成排、不该抢眼的开关用 tone="neutral"(开 = 深灰)。

default · 开
default · 关
sm · 26×16
tone=neutral
disabled · 45%
同步到 Claude Desktop 写入 settings.json 按队列 按延迟
组件 / 05 · segmented-control.tsx · page-tabs.tsx

分段控件 · 页签

分段控件是按钮组(aria-pressed),用在模式和页内筛选;下划线页签换整块内容。两者不混用。分段选中块是白底 + 小阴影,不用主题色。 切换有动画:选中块和页签下划线都是单独的一块,点哪项就 200ms 滑过去(src/components/ui/sliding-indicator.tsx);页面刚打开时不播,系统开了「减少动态效果」时直接跳。

md · 36
sm · 28
PageTabs · 36 高 · 下划线用 text-1,不用主题色
组件 / 06

徽章

高 20、全圆角、11px / 500。用 soft 底 + text 色,不用实心彩色块。一张卡片上最多两个。

官方 直连 路由 · 第 1 位 聚合 正常 · 312ms 额度 8% 连接失败 新
组件 / 07 · providers/ProviderCard.tsx

供应商卡片

最小高 58、圆角 10。普通卡片白底细描边,hover 描边加深 + 小阴影,拖拽手柄和右侧操作只在 hover / 聚焦时出现。右侧操作全部是图标按钮(主操作 → 排序 → 编辑 → ⋯),名字由 HoverTip 报; 有禁用原因时改挂说明卡报原因,不叠两层提示。状态(使用中 / 路由中)是文字不是按钮,照旧写字。 当前生效的那张用所在模式的 soft 底 + fill 描边。

Anthropic 官方 路由 · 第 1 位
api.anthropic.com · claude-sonnet-5-5
312ms 路由中
OpenRouter
openrouter.ai/api · 上次使用 2 天前
Kimi
⚠ 额度剩 8% · api.moonshot.cn

主操作图标对照(ProviderCardActions.tsx · BUTTON_ICON)

切换 回到直连并使用 路由到此 加入 / 移出队列 添加 / 移除

设为默认 = 星标(OpenClaw 选默认模型)、启用 / 停用 = 电源;没对上的 key 回退为圆点图标,新加按钮时在 BUTTON_ICON 里补一条。

聚合页的「设为默认」不占主操作位:行上只留名单的添加 / 移除,「设为默认」在 ⋯ 菜单最前面(CardPresentation.menuItems),点了之后的后果用警示色写在名字下面,不能点时列出来并写原因。

供应商图标框固定白底深色图标,深色主题里也不反色——单色品牌图标继承浅色文字会看不见。

组件 / 08 · notice.tsx · help-tip.tsx

通知条 · 说明卡

通知条圆角 10、左侧 16px 图标、soft 底,不用左边框强调色。只有一行时图标、文字、按钮整行上下居中;有第二行时图标对齐第一行。应用页顶部的通知槽按严重程度从上到下排。

路由服务没能启动
端口 15721 被占用。请求现在直连默认供应商。
有 1 个账号需要重新登录
Codex · ChatGPT Plus 的令牌已过期
路由生效中 · 按队列
第 1 位不可用时自动换下一位
Claude Code 需要重开终端才能读到新的环境变量

说明卡 HelpTip(「?」)

故障转移 什么是故障转移当前供应商连续失败时,按队列自动换到下一家,恢复后再切回来。 悬停 300ms 打开 · 移开 200ms 关闭 · 点一下固定 · 只放规则和术语,不放按钮
组件 / 09

菜单 · 对话框 · Toast

已回到直连:Codex 现在直接连接官方。重启 Codex 后生效。
保存失败:配置文件被占用

Toast 是白卡片(深色主题为深灰)、底部居中、2 秒消失;状态只看图标颜色——成功绿勾、失败红、警告琥珀、提示灰;带关闭按钮时一律在右上角(RTL 镜像到左上)。对话框圆角 14、遮罩 --overlay、shadow-lg。确认危险操作时,按钮写具体动作(「删除」),不写「确定」。会丢东西、要重启这类后果写在对话框或 toast 里,不进说明卡。

组件 / 10 · usage/

数据展示

今日花费
$12.48
昨天 $9.10
请求数
1,284
失败 6
输入 tokens
3.2M
缓存命中 71%
Codex 额度
62%
时间应用供应商模型状态输入输出耗时花费
14:02:31Claude CodeAnthropic 官方claude-sonnet-5-520018,2041,0324.1s$0.071
14:01:58CodexOpenRoutergpt-5.1-codex2009,8804122.3s$0.018
14:01:12Claude CodeKimikimi-k3429——0.4s—

数字列右对齐、tabular-nums;状态码、模型名、时间用等宽;额度条 >30% 绿、10–30% 琥珀、<10% 红。

CC Switch / 01 · providers/mode/ModeTabs.tsx

连接模式

每个应用有三种连接方式:直连(直接写配置文件)、 路由(本地代理按队列 / 故障转移)、聚合(多家模型合并)。 模式 tab 保留图标 + 文字、不挂提示;同一行右侧的故障转移、路由设置是纯图标 + HoverTip。

三种模式的区别直连:直接写入应用配置。
路由:经本地代理转发,可故障转移。
聚合:把多家的模型合并给一个应用。
路由生效中 · 按队列 · Anthropic 官方

看 ≠ 生效

白底凸起 = 正在看的那段;模式色文字 + 圆点 = 生效中的那段。两者可以不同。

切换要确认

看另一个模式时,底部出现模式色实心按钮「改为路由」,点了才生效。

颜色只在这几处

模式 tab、侧栏模式标签、当前卡片、切换按钮。别处出现模式名用中性文字。

规约 / 01

交互原则

一个主操作

每个视图只有一个实心主题色按钮;卡片上一律描边或图标。

图标 + HoverTip

重复出现的操作(编辑、复制、删除、设置、模式)只放图标,悬停立即显示操作内容,键盘聚焦同样显示。

状态写在原处

额度、延迟、需要登录写在卡片副行;后果(丢失、需重启)写在按钮、确认框或 toast,不藏进说明卡。

明暗一致

所有颜色走 token;浅色 / 深色两套值一一对应,切换时暂停过渡。

键盘可达

焦点环 2px 主题色;⌘K 打开命令面板;Escape 关闭浮层;禁用按钮用 aria-disabled 保留悬停说明原因。

文案

动词开头、说结果(「已切换到 X」),不写「操作成功」;按钮写具体动作,不写「确定」。

规约 / 02

Do / Don't

Do

主题橙只放在能点的东西上:主按钮、开关、勾选、焦点、链接。

Don't

用橙色表达「注意 / 警告」状态,或给分段控件选中块、页签下划线上橙色。

Do

卡片操作、工具栏用纯图标按钮,配 HoverTip + aria-label;模式 tab 这种「选哪一个」的控件保留文字。

Don't

图标按钮只靠 title 属性提示——要等一秒多才出现,样式也和系统不一致。

Do

当前生效的供应商卡片用模式 soft 底 + fill 描边。

Don't

给当前卡片再加主题色描边或实心彩色块,和模式色打架。

Do

数字列右对齐、等宽数字;模型名、状态码、密钥用 mono。

Don't

新增 token 以外的颜色或字号(text-[15px]、#ff8800)。