Notrat UI Control(无源码操控指南)
> 核心能力:不碰 Notrat 源代码,纯靠 MCP 工具实时操控 UI 外观。
一、可用工具一览
| 工具 | 作用 | 典型场景 |
|---|---|---|
slot_set_style |
给任意 CSS 选择器注入样式 | 改颜色、字体大小、背景、边框 |
slot_set_props |
修改 React 组件 props | 改 placeholder、disabled 等 |
slot_set_behavior |
绑定事件处理 | onClick、onChange |
slot_set_content |
替换元素内容 | 改标题文字、插入 HTML |
slot_clear_all |
清除所有覆盖 | 恢复默认样式 |
config_get / config_get_all |
读取配置 | 查看当前主题、字体大小 |
config_set |
写入配置 | 切换主题、改字号 |
config_toggle_theme |
明暗主题切换 | 一键切 dark/light |
component_modify |
热替换组件源码 | 改组件结构/逻辑(需源码) |
ui_get_state |
获取当前 UI 状态 | 查看活动 tab、打开的文件 |
ui_click / ui_type |
模拟用户操作 | 点击按钮、输入文字 |
二、Notrat 主题系统架构(源码逆向)
2.1 CSS 变量体系
Notrat 使用 shadcn/ui 风格 的 CSS 变量 + Tailwind 主题系统。所有颜色都是 HSL 无前缀格式(如 0 0% 10%,不带 hsl())。
2.2 核心变量速查表
全局基础变量
| 变量名 | 作用 | 默认值(light) | 默认值(dark) |
|---|---|---|---|
--background |
编辑器/主背景 | 0 0% 100% |
0 0% 10% |
--foreground |
主文字色 | 0 0% 10% |
0 0% 95% |
--card |
卡片背景 | 0 0% 100% |
0 0% 12% |
--popover |
弹窗背景 | 0 0% 100% |
0 0% 12% |
--muted |
静音区域背景 | 0 0% 94% |
0 0% 16% |
--muted-foreground |
次要文字色 | 0 0% 45% |
0 0% 65% |
--accent |
强调区域背景 | 0 0% 96% |
0 0% 16% |
--border |
边框色 | 0 0% 90% |
0 0% 16% |
--input |
输入框背景 | 0 0% 92% |
0 0% 16% |
--ring |
聚焦环色 | 215 95% 55% |
215 95% 60% |
--radius |
圆角 | 0.625rem |
同 |
--secondary |
次级背景 | 0 0% 96% |
0 0% 16% |
--destructive |
危险/删除色 | 0 72% 51% |
0 62% 50% |
侧边栏专用变量
| 变量名 | 作用 | 默认值(light) | 默认值(dark) |
|---|---|---|---|
--sidebar-background |
侧边栏背景 | 0 0% 97% |
0 0% 8% |
--sidebar-foreground |
侧边栏文字 | 0 0% 15% |
0 0% 90% |
--sidebar-border |
侧边栏边框 | 0 0% 90% |
0 0% 16% |
主色调变量
| 变量名 | 作用 | 默认值 |
|---|---|---|
--primary |
主色调 | 215 95% 55%(蓝) |
--primary-foreground |
主色调上的文字 | 白 |
--accent-color |
强调色(CSS 值,非 HSL) | #3b82f6 |
--accent-hover |
强调色悬停 | #2563eb |
--hue-accent |
色相值 | 215 |
排版变量
| 变量名 | 默认值 | 作用 |
|---|---|---|
--font-size-xs |
12px |
超小字 |
--font-size-sm |
12px |
小字 |
--font-size-base |
14px |
正文字号 |
--font-size-md |
16px |
中号 |
--font-size-lg |
18px |
大号 |
--font-size-xl |
20px |
超大 |
--font-size-2xl |
24px |
二级标题 |
--font-size-3xl |
30px |
三级标题 |
--font-size-4xl |
38px |
四级标题 |
布局变量
| 变量名 | 默认值 | 作用 |
|---|---|---|
--left-panel-width |
260px |
左侧面板宽度 |
2.3 主题选择器优先级
Notrat 的主题通过 :root 上挂 class 实现,选择器优先级从低到高:
:root ← 最基础(fallback 值)
:root.theme-minimalist:not(.dark) ← 极简白(默认 light 主题)
:root.theme-minimalist.dark ← 极简白 dark
:root.theme-oceanic:not(.dark) ← 海洋蓝
:root.theme-oceanic.dark ← 海洋蓝 dark
:root.theme-forest:not(.dark) ← 森林绿
:root.theme-forest.dark ← 森林绿 dark
...(更多主题)
⚠️ 关键陷阱:直接改 :root 不一定生效!主题 class 选择器(如 .theme-minimalist:not(.dark))优先级更高,会覆盖 :root 的值。
正确写法:同时写两个选择器,双保险:
selector: ":root, :root.theme-minimalist:not(.dark)"
2.4 已知主题列表
| 主题名 | CSS class | 风格 |
|---|---|---|
| 极简白 | .theme-minimalist |
默认,纯灰白 |
| 海洋蓝 | .theme-oceanic |
蓝色调 |
| 森林绿 | .theme-forest |
绿色调 |
| 暖阳橙 | .theme-warm |
橙暖色调 |
| 紫罗兰 | .theme-violet |
紫色调 |
| 兰花紫 | .theme-orchid |
深紫调 |
| 深海蓝 | .theme-deepblue |
深蓝色 |
| 玫红 | .theme-rose |
粉红调 |
| 青绿 | .theme-teal |
青色 |
| 日落 | .theme-sunset |
橙红调 |
| 薰衣草 | .theme-lavender |
浅紫调 |
| 品红 | .theme-magenta |
洋红调 |
| 板岩 | .theme-slate |
灰蓝调 |
| 午夜 | .theme-midnight |
深蓝调(dark-only) |
三、完整 CSS Selector 速查表(源码逆向)
> 以下选择器全部从 Notrat 源码 src/styles/index.css、src/styles/tiptap.css 及各组件 TSX 中提取。
3.1 Activity Bar(活动栏 / 最左侧图标栏)
| 选择器 | 用途 |
|---|---|
.activity-bar |
活动栏容器 |
.activity-bar-item |
每个图标按钮 |
.activity-bar-item.active |
当前激活的图标 |
.activity-bar-item:hover |
鼠标悬停状态 |
.activity-bar-item::before |
悬停背景 |
.activity-bar-item.active::before |
激活背景 |
.activity-bar-item.active::after |
激活指示条(左侧竖线) |
.activity-bar-item-badge |
角标/红点 |
.activity-bar-divider |
分割线 |
.activity-bar-spacer |
弹性间距 |
.activity-bar-macos |
macOS 样式变体 |
3.2 Sidebar Panel(侧边栏面板)
| 选择器 | 用途 |
|---|---|
.sidebar-panel |
侧边栏面板容器(文件树、会话列表等的父容器) |
.file-tree-panel |
文件树面板 |
.file-tree |
文件树容器 |
.file-tree-header |
文件树头部 |
.file-tree-toolbar |
文件树工具栏 |
.file-tree-node |
文件树节点 |
.file-tree-node.selected |
选中的文件/文件夹 |
.file-tree-node.focused |
聚焦的节点 |
.file-tree-node:hover |
悬停的节点 |
.file-tree-node.dragging |
正在拖拽的节点 |
.file-tree-node.drag-over |
拖拽悬停目标 |
.file-tree .tree-node |
树节点(react-arborist) |
.file-tree .tree-node-content |
树节点内容 |
3.3 Editor(编辑器区域)
| 选择器 | 用途 |
|---|---|
.editor-container |
编辑器外层容器 |
.editor-content |
编辑器内容区 |
.editor-tabs |
标签栏容器 |
.editor-tabs-container |
标签栏内部容器 |
.editor-tab |
单个标签 |
.editor-tab.active |
当前激活标签 |
.editor-tab.hover |
悬停标签 |
.editor-tab.closing |
正在关闭的标签 |
.editor-tab.drag-over |
拖拽悬停标签 |
.editor-tab.enter |
进入动画标签 |
.editor-tabs-count |
标签计数 |
.editor-tabs-scroll-button |
标签滚动按钮 |
.editor-tabs-scroll-button.left |
左滚动 |
.editor-tabs-scroll-button.right |
右滚动 |
.rich-text-editor |
富文本编辑器 |
.word-editor-content |
Word 编辑器内容 |
.wysiwyg-editor |
所见即所得编辑器 |
3.4 ProseMirror / TipTap(Markdown 编辑器核心)
| 选择器 | 用途 |
|---|---|
.ProseMirror |
ProseMirror 编辑器根元素 |
.ProseMirror-focused |
聚焦状态 |
.ProseMirror p |
段落 |
.ProseMirror h1 ~ .ProseMirror h6 |
标题(h1=2em, h2=1.5em, h3=1.25em, h4=1.125em, h5=1em, h6=0.875em) |
.ProseMirror a |
链接 |
.ProseMirror blockquote |
引用 |
.ProseMirror code |
行内代码 |
.ProseMirror pre |
代码块 |
.ProseMirror pre code |
代码块内代码 |
.ProseMirror ul / .ProseMirror ol |
列表 |
.ProseMirror ul.contains-task-list |
任务列表 |
.ProseMirror img |
图片 |
.ProseMirror table |
表格 |
.ProseMirror table td / .th |
表格单元格 |
.ProseMirror hr |
分割线 |
.ProseMirror mark |
高亮标记 |
.ProseMirror strong |
加粗 |
.ProseMirror em |
斜体 |
.ProseMirror s / .ProseMirror strike |
删除线 |
.ProseMirror ::selection |
文本选区 |
.ProseMirror .drag-handle |
拖拽手柄 |
.ProseMirror .heading-hash-prefix |
标题井号前缀 |
.ProseMirror .md-heading-draft-marker |
标题草稿标记 |
.ProseMirror .md-syntax-hint |
语法提示 |
.ProseMirror .inline-image |
行内图片 |
.ProseMirror .inline-math-edit |
行内数学编辑 |
.ProseMirror .inline-math-edit--selected |
选中的数学编辑 |
.ProseMirror .column-resize-handle |
列调整手柄 |
.ProseMirror .selectedCell:after |
选中的单元格 |
.notrat-editor-root |
编辑器根容器(语义 hook) |
3.5 TipTap 数学 / 公式
| 选择器 | 用途 |
|---|---|
.tiptap-editor |
TipTap 编辑器容器 |
.tiptap-editor .math-delim |
数学分隔符 |
.tiptap-editor .math-katex-render |
KaTeX 渲染 |
.tiptap-editor .math-live-preview |
实时预览 |
.tiptap-editor div[data-type="block-math"] |
块级公式 |
.tiptap-editor span[data-type="inline-math"] |
行内公式 |
.tiptap-mathematics-render |
数学渲染组件 |
.highlight-mark |
高亮标记 |
.inline-math-edit__input |
数学输入框 |
.inline-math-edit__delim |
数学分隔符 |
.katex |
KaTeX 渲染根 |
.markdown-table |
Markdown 表格 |
3.6 代码高亮(highlight.js)
| 选择器 | 用途 |
|---|---|
.hljs |
代码块根 |
.code-block-wrapper |
代码块外包装 |
.code-block-wrapper pre |
代码块 pre 元素 |
.hljs-keyword |
关键字 |
.hljs-string |
字符串 |
.hljs-comment |
注释 |
.hljs-number |
数字 |
.hljs-function |
函数名 |
.hljs-title |
标题 |
.hljs-attr |
属性 |
.hljs-built_in |
内置 |
.hljs-meta |
元信息 |
.hljs-tag |
标签 |
.hljs-name |
名称 |
.hljs-variable |
变量 |
.hljs-type |
类型 |
.hljs-params |
参数 |
3.7 Slash Menu(斜杠菜单)
| 选择器 | 用途 |
|---|---|
.slash-menu-popup |
弹窗容器 |
.slash-menu-popup-inner |
弹窗内部 |
.slash-menu-list |
菜单列表 |
.slash-menu-search |
搜索区域 |
.slash-menu-search-input |
搜索输入框 |
.slash-menu-search-icon |
搜索图标 |
.slash-menu-item |
菜单项 |
.slash-menu-item.selected |
选中的菜单项 |
.slash-menu-item:hover |
悬停菜单项 |
.slash-menu-item-icon |
菜单项图标 |
.slash-menu-item-label |
菜单项标签 |
.slash-menu-item-desc |
菜单项描述 |
.slash-menu-item-text |
菜单项文本 |
.slash-menu-group-label |
分组标签 |
.slash-menu-footer |
底部 |
.slash-menu-empty |
空状态 |
.slash-menu-chevron |
箭头 |
.slash-submenu |
子菜单 |
.slash-table-picker |
表格选择器 |
.slash-table-picker-grid |
表格网格 |
.slash-table-cell |
表格单元格 |
.slash-table-cell.active |
活动单元格 |
3.8 Status Bar(底部状态栏)
| 选择器 | 用途 |
|---|---|
.status-bar |
状态栏容器 |
注意:StatusBar 组件主要使用 Tailwind 内联类,常用模式:
text-[10px] text-muted-foreground/70— 状态栏小字text-[10px] text-muted-foreground/80— 状态栏文字text-[10px] font-mono text-muted-foreground/70— 等宽状态文字text-[10px] text-foreground/70— 强调状态文字text-[11px] font-semibold— Notrat 标题bg-muted/30— 状态栏背景
3.9 Title Bar(顶部标题栏)
| 选择器 | 用途 |
|---|---|
.app-region-drag |
可拖拽区域(标题栏) |
.app-region-no-drag |
不可拖拽区域(按钮) |
.app-region-drag:hover |
拖拽区悬停 |
常用 Tailwind 类:
h-8 bg-background border-b border-border/50— 标题栏容器text-sm font-medium text-foreground— 标题文字w-11 h-8 text-muted-foreground hover:bg-muted hover:text-foreground— 窗口控制按钮
3.10 Chat / Session List(聊天侧边栏)
| 选择器 | 用途 |
|---|---|
.sidebar-panel |
聊天侧边栏容器(同文件树) |
SessionList 常用 Tailwind 类:
text-foreground— 会话标题text-muted-foreground— 预览文本、图标text-muted-foreground/70— 时间戳text-muted-foreground/60— 搜索图标text-accent-color— 当前选中会话bg-muted/50— 搜索框背景
3.11 Chat Input(聊天输入框)
常用 Tailwind 类:
bg-muted/30 rounded-2xl border border-border— 输入区容器bg-background border-0 rounded-xl focus:ring-2 focus:ring-primary/20— textareaplaceholder:text-muted-foreground/50— placeholder 颜色bg-accent-color/10 border border-accent-color/30— 上下文提示条bg-muted rounded-full text-xs— 标签 chiptext-muted-foreground hover:text-foreground hover:bg-muted— 发送按钮
3.12 Immersive AI(沉浸式 AI 界面)
| 选择器 | 用途 |
|---|---|
.immersive-ai-view |
沉浸式 AI 主视图 |
.immersive-ai-main |
主内容区 |
.immersive-ai-canvas |
画布区 |
.immersive-ai-topbar |
顶部栏 |
.immersive-ai-topbar-title-wrap |
标题容器 |
.immersive-ai-topbar-context |
上下文信息 |
.immersive-ai-overlay-scrim |
遮罩层 |
.immersive-ai-composer-surface |
输入区域 |
.immersive-ai-composer-surface:focus-within |
输入区聚焦 |
.immersive-ai-composer-width |
输入区宽度 |
.immersive-ai-user-bubble |
用户消息气泡 |
.immersive-ai-section-card |
分区卡片 |
.immersive-ai-section-item |
分区项 |
.immersive-ai-chip |
芯片/标签 |
.immersive-ai-chip-row |
芯片行 |
.immersive-ai-attachment-chip |
附件芯片 |
.immersive-ai-pill |
药丸按钮 |
.immersive-ai-mode-pill |
模式选择 |
.immersive-ai-state-pill |
状态药丸 |
.immersive-ai-state-pill-active |
活动状态 |
.immersive-ai-state-pill-error |
错误状态 |
.immersive-ai-status-chip |
状态芯片 |
.immersive-ai-status-chip-accent |
强调状态 |
.immersive-ai-status-chip-muted |
静音状态 |
.immersive-ai-count-pill |
计数药丸 |
.immersive-ai-tone-dot |
语气圆点 |
.immersive-ai-tone-dot-active |
活动语气 |
.immersive-ai-tone-dot-error |
错误语气 |
.immersive-ai-toggle |
开关 |
.immersive-ai-toggle-group |
开关组 |
.immersive-ai-title |
标题 |
.immersive-ai-kicker |
标题前缀 |
.immersive-ai-danger-button |
危险按钮 |
.immersive-ai-danger-button:hover |
危险按钮悬停 |
.immersive-ai-inline-notice |
内联通知 |
.immersive-ai-inline-notice-permission |
权限通知 |
.immersive-ai-inline-notice-thinking |
思考通知 |
.immersive-ai-process-timeline |
流程时间线 |
.immersive-ai-process-item |
流程项 |
.immersive-ai-process-node |
流程节点 |
.immersive-ai-process-summary-row |
流程摘要行 |
.immersive-ai-process-summary-dot |
摘要圆点 |
.immersive-ai-process-summary-badge |
摘要徽章 |
.immersive-ai-process-detail |
流程详情 |
.immersive-ai-process-count |
流程计数 |
.immersive-ai-process-error-reason |
错误原因 |
.immersive-ai-execution-drawer |
执行抽屉 |
.immersive-ai-execution-drawer-error |
执行错误 |
.immersive-ai-details-entry |
详情条目 |
.immersive-ai-details-entry-active |
活动条目 |
.immersive-ai-details-entry-attention |
注意条目 |
.immersive-ai-details-entry-error |
错误条目 |
.immersive-ai-details-entry-badge |
条目徽章 |
.immersive-ai-runtime-status-bar |
运行时状态栏 |
.immersive-ai-trace-item |
追踪项 |
.immersive-ai-trace-shell |
追踪外壳 |
.immersive-ai-surface-active |
活动表面 |
.immersive-ai-page-column |
页面列 |
.immersive-ai-document-segment |
文档片段 |
.immersive-document-segment |
文档段落 |
3.13 Mention Dashboard(@提及面板)
| 选择器 | 用途 |
|---|---|
.mention-dashboard-shell |
面板外壳 |
.mention-dashboard-header |
头部 |
.mention-dashboard-subtitle |
副标题 |
.mention-dashboard-search-icon |
搜索图标 |
.mention-dashboard-footer |
底部 |
.mention-dashboard-empty |
空状态 |
.mention-dashboard-section-label |
分区标签 |
.mention-dashboard-item |
条目 |
.mention-dashboard-item-active |
活动条目 |
.mention-dashboard-item:hover |
悬停条目 |
.mention-dashboard-meta |
元信息 |
.mention-dashboard-category-card |
分类卡片 |
.mention-dashboard-category-card-active |
活动分类 |
3.14 Scrollbar(滚动条)
| 选择器 | 用途 |
|---|---|
.custom-scrollbar |
自定义滚动条 |
.custom-scrollbar::-webkit-scrollbar |
滚动条轨道 |
.custom-scrollbar::-webkit-scrollbar-thumb |
滚动条滑块 |
.custom-scrollbar::-webkit-scrollbar-thumb:hover |
滑块悬停 |
.custom-scrollbar::-webkit-scrollbar-track |
滚动条轨道背景 |
.scrollbar-thin |
细滚动条 |
.scrollbar-thin-hover |
悬停显示滚动条 |
.scrollbar-visible |
可见滚动条 |
3.15 Tree / react-arborist(文件树底层)
| 选择器 | 用途 |
|---|---|
.tree-container |
树容器 |
.react-arborist-tree |
arborist 树 |
.react-arborist-row |
树行 |
.react-arborist-row:hover |
树行悬停 |
.react-arborist-row-focused |
聚焦行 |
.react-arborist-row-selected |
选中行 |
.react-arborist-drag-preview |
拖拽预览 |
.react-arborist-line |
拖拽线 |
.react-arborist-row-selected .row-content |
选中行内容 |
3.16 Excel Editor(Excel 编辑器)
| 选择器 | 用途 |
|---|---|
.excel-editor-container |
Excel 编辑器容器 |
.excel-cell |
单元格 |
.excel-cell:focus |
聚焦单元格 |
.excel-header |
表头 |
3.17 Source Code Editor(源码编辑器)
| 选择器 | 用途 |
|---|---|
.CodeMirror |
CodeMirror 根 |
.CodeMirror-scroll |
CodeMirror 滚动区 |
.source-editor-textarea |
源码编辑 textarea |
.source-editor-textarea::placeholder |
placeholder |
3.18 Diagram Preview(图表预览)
| 选择器 | 用途 |
|---|---|
.diagram-preview |
图表预览容器 |
.diagram-preview img |
预览图片 |
.diagram-preview svg |
预览 SVG |
.drag-ghost |
拖拽幽灵 |
.drag-handle |
拖拽手柄 |
.drag-handle:hover |
手柄悬停 |
.drag-handle.dragging |
正在拖拽 |
.drag-insert-line |
拖拽插入线 |
3.19 Icon Colors(图标颜色类)
| 选择器 | 用途 |
|---|---|
.icon-blue |
蓝色图标 |
.icon-cyan |
青色图标 |
.icon-gray |
灰色图标 |
.icon-green |
绿色图标 |
.icon-orange |
橙色图标 |
.icon-pink |
粉色图标 |
.icon-purple |
紫色图标 |
.icon-red |
红色图标 |
.icon-yellow |
黄色图标 |
3.20 Misc / 动画
| 选择器 | 用途 |
|---|---|
.tour-highlight-pulse |
引导高亮脉冲 |
.wc-shell |
写作画布外壳 |
.wc-shell-paint |
写作画布绘制层 |
.wc-fade-left |
向左淡入 |
.wc-fade-up |
向上淡入 |
.wc-fade-rule |
分割线淡入 |
.wc-fade-wash |
冲刷动画 |
.wc-delay-1 ~ .wc-delay-5 |
动画延迟(0.04s ~ 0.28s) |
.changelog-md |
更新日志 Markdown |
.drag-ghost |
拖拽幽灵元素 |
3.21 Tailwind Utility 选择器(高频使用)
以下 Tailwind class 在源码中频繁出现,可通过 CSS 变量统一控制:
| Tailwind class | 对应 CSS 变量 | 出现频率 |
|---|---|---|
.text-foreground |
--foreground |
极高 |
.text-muted-foreground |
--muted-foreground |
极高 |
.text-muted-foreground/70 |
--muted-foreground × 0.7 |
高 |
.text-muted-foreground/60 |
--muted-foreground × 0.6 |
中 |
.text-muted-foreground/80 |
--muted-foreground × 0.8 |
高 |
.text-muted-foreground/50 |
--muted-foreground × 0.5 |
中 |
.text-accent-color |
--accent-color |
高 |
.text-accent-foreground |
--accent-foreground |
中 |
.text-primary |
--primary |
中 |
.bg-background |
--background |
极高 |
.bg-muted |
--muted |
高 |
.bg-muted/30 |
--muted × 0.3 |
中 |
.bg-muted/50 |
--muted × 0.5 |
中 |
.bg-card |
--card |
中 |
.bg-popover |
--popover |
中 |
.bg-accent |
--accent |
中 |
.bg-accent-color/10 |
--accent-color × 0.1 |
中 |
.border-border |
--border |
高 |
.border-border/50 |
--border × 0.5 |
高 |
.border-border/30 |
--border × 0.3 |
中 |
.ring-primary/20 |
--primary × 0.2 |
中 |
.text-[10px] |
直接像素值 | 高(状态栏、小字) |
.text-[11px] |
直接像素值 | 中 |
.text-[9px] |
直接像素值 | 低(极小字) |
四、实战配方(直接抄)
4.1 改全局文字颜色更深
{
"selector": ":root, :root.theme-minimalist:not(.dark)",
"styles": {
"--muted-foreground": "0 0% 25%",
"--foreground": "0 0% 8%"
}
}
4.2 暖白主题(全局暖色)
{
"selector": ":root, :root.theme-minimalist:not(.dark)",
"styles": {
"--background": "40 30% 99%",
"--foreground": "0 0% 8%",
"--card": "40 20% 99%",
"--popover": "40 20% 99%",
"--secondary": "40 20% 96%",
"--muted": "40 20% 95%",
"--accent": "40 20% 95%",
"--muted-foreground": "0 0% 25%",
"--border": "38 15% 88%",
"--input": "40 20% 96%",
"--sidebar-background": "40 30% 96%",
"--sidebar-foreground": "0 0% 10%",
"--sidebar-border": "38 15% 88%",
"--ring": "38 60% 50%"
}
}
4.3 改活动栏图标颜色
{
"selector": ".activity-bar-item",
"styles": {
"color": "hsl(0 0% 30%) !important"
}
}
// 激活状态
{
"selector": ".activity-bar-item.active",
"styles": {
"color": "hsl(215 95% 55%) !important"
}
}
4.4 改标签页样式
{
"selector": ".editor-tab",
"styles": {
"font-size": "13px",
"color": "hsl(0 0% 30%)"
}
}
// 激活标签
{
"selector": ".editor-tab.active",
"styles": {
"color": "hsl(0 0% 8%)",
"font-weight": "600"
}
}
4.5 改滚动条样式
{
"selector": ".custom-scrollbar::-webkit-scrollbar-thumb",
"styles": {
"background": "hsl(0 0% 70%)",
"border-radius": "4px"
}
}
{
"selector": ".custom-scrollbar::-webkit-scrollbar-thumb:hover",
"styles": {
"background": "hsl(0 0% 50%)"
}
}
4.6 改代码块字体大小
{
"selector": ".ProseMirror pre, .code-block-wrapper pre",
"styles": {
"font-size": "13px"
}
}
4.7 改沉浸式 AI 界面
{
"selector": ".immersive-ai-canvas",
"styles": {
"background": "hsl(220 20% 97%)"
}
}
// 用户消息气泡
{
"selector": ".immersive-ai-user-bubble",
"styles": {
"background": "hsl(var(--primary) / 0.08)",
"border-radius": "12px"
}
}
4.8 改状态栏
{
"selector": ".status-bar",
"styles": {
"background": "hsl(0 0% 95%)",
"color": "hsl(0 0% 30%)",
"font-size": "11px"
}
}
4.9 改标题栏
{
"selector": ".app-region-drag",
"styles": {
"background": "hsl(0 0% 98%)",
"border-bottom": "1px solid hsl(0 0% 90%)"
}
}
4.10 改侧边栏会话记录字体加深加大
// 1. 改 CSS 变量(从根源改)
{
"selector": ":root, :root.theme-minimalist:not(.dark)",
"styles": {
"--muted-foreground": "0 0% 25%",
"--sidebar-foreground": "0 0% 10%"
}
}
// 2. 强制覆盖(变量改不动时的暴力方案)
{
"selector": ".text-muted-foreground, [class*=\"text-muted-foreground\"]",
"styles": {
"color": "hsl(0 0% 25%) !important",
"opacity": "1 !important"
}
}
4.11 改字号
{
"selector": ":root, :root.theme-minimalist:not(.dark)",
"styles": {
"--font-size-base": "15px",
"--font-size-sm": "13px"
}
}
4.12 自定义主色调
{
"selector": ":root, :root.theme-minimalist:not(.dark)",
"styles": {
"--primary": "270 80% 55%",
"--accent-color": "#8b5cf6",
"--accent-hover": "#7c3aed",
"--ring": "270 80% 55%"
}
}
常用色相参考:
| 风格 | --primary (HSL) |
--accent-color |
|---|---|---|
| 蓝(默认) | 215 95% 55% |
#3b82f6 |
| 紫 | 270 80% 55% |
#8b5cf6 |
| 绿 | 150 60% 45% |
#10b981 |
| 橙 | 30 90% 50% |
#f59e0b |
| 红 | 0 80% 55% |
#ef4444 |
| 青 | 180 70% 45% |
#06b6d4 |
| 粉 | 330 75% 55% |
#ec4899 |
4.13 切换主题(config 层面)
// 通过 config_set
{ "key": "theme", "value": "dark" }
// 或通过 toggle
config_toggle_theme()
// 或直接读当前配置
config_get_all()
4.14 恢复默认
slot_clear_all() // 清除所有 style/props/behavior/content 覆盖
五、Tailwind class 与 CSS 变量对应关系
⚠️ Tailwind 的 /70 透明度后缀会在编译后变成 opacity: 0.7 或 color-mix(),用 !important 强制覆盖时需要同时设 color 和 opacity。
透明度叠加问题示例:
text-muted-foreground/70 → hsl(0 0% 45% / 0.7) → 实际亮度 ≈ 58% ❌ 看不清
text-muted-foreground/60 → hsl(0 0% 45% / 0.6) → 实际亮度 ≈ 63% ❌ 更看不清
修改 --muted-foreground 为 25% 后:
text-muted-foreground/70 → hsl(0 0% 25% / 0.7) → 实际亮度 ≈ 33% ✅ 清楚
text-muted-foreground/60 → hsl(0 0% 25% / 0.6) → 实际亮度 ≈ 40% ✅ 可接受
六、调试技巧
6.1 查看当前状态
config_get_all() // 看当前主题、字号等配置
ui_get_state() // 看当前活动 tab、打开文件
6.2 CSS 变量改了没效果?
排查顺序:
- 选择器优先级:主题 class(如
.theme-minimalist)比:root高,需要同时写两个 - Tailwind 编译:Tailwind 在构建时把
text-muted-foreground编译成color: hsl(var(--muted-foreground)),改变量会影响所有用了这个 class 的元素 - 透明度后缀:
text-muted-foreground/70=hsl(var(--muted-foreground) / 0.7),需要额外加opacity: 1 !important - !important 叠加:如果之前注入了
!important的样式,后注入的也需要!important - slot_clear_all 后重设:如果改动叠加太多产生冲突,先 clear 再重新设
6.3 批量覆盖策略
如果 CSS 变量方案不够,可以按 Tailwind class 名批量覆盖:
// 所有次要文字
{ "selector": ".text-muted-foreground", "styles": { "color": "hsl(0 0% 25%) !important" } }
// 所有主要文字
{ "selector": ".text-foreground", "styles": { "color": "hsl(0 0% 8%) !important" } }
// 所有小字
{ "selector": ".text-\\[10px\\]", "styles": { "font-size": "12px !important" } }
// 侧边栏整体
{ "selector": ".sidebar-panel *", "styles": { "font-size": "14px !important" } }
6.4 查看实际 DOM 结构
用 ui_get_state() 获取当前 UI 状态,或用 ui_click 配合 ui_type 模拟交互验证样式是否生效。
七、注意事项
- slot 覆盖是临时的:
slot_clear_all()或刷新页面后恢复默认。如需永久生效,需要改 Notrat 源代码。 - 全局变量影响范围大:改
--muted-foreground会影响整个 app 所有用了这个变量的组件,不只侧边栏。 - HSL 格式:Notrat 的 CSS 变量值不含
hsl()前缀(写0 0% 10%而非hsl(0 0% 10%))。但在slot_set_style的 styles 里写最终 CSS 值时(如直接给某个元素设 color),需要带hsl()(因为 slot 注入的是最终 CSS 值,不是变量赋值)。**改变量本身时不需要hsl()**。 **!important要慎用**:一旦加了!important,后续所有覆盖都需要!important。能用变量解决的优先用变量。- 暗色主题适配:如果用户用暗色主题,选择器要改成
:root.theme-minimalist.dark或对应的主题 class。 - reload 会清除覆盖:
app_reload_window()会清除所有 slot 注入的样式。需要时重新注入。 - 自定义 class vs Tailwind class:自定义 class(如
.activity-bar、.editor-tab)可直接用 selector 覆盖。Tailwind class(如.text-muted-foreground)背后是 CSS 变量,改变量更优雅。 - 伪元素:
.activity-bar-item::before、.editor-tab.active::after等伪元素可以直接作为 selector 传给slot_set_style。
八、弹窗与对话框(2026-07-30 新增)
8.1 语义钩子类速查
所有弹窗都已挂语义钩子类(与 .notrat-editor-root 同一约定),DIY / slot_set_style 直接定位:
| 弹窗 | 根类 | 关键子类 |
|---|---|---|
| 角落活动提醒(右下角) | .notrat-corner-notify |
-host(容器)/ -accent(顶部渐变条)/ -title / -body / -item / -item-title / -item-desc / -item-action / -actions / -action(-primary) / -close |
| 官方推荐技能(模态) | .notrat-recommend-dialog |
-accent / -title / -subtitle / -items / -item / -item-action / -actions / -action-primary |
| AI 服务商导入(模态) | .notrat-import-dialog |
-title / -subtitle / -actions / -action-primary |
| 全局确认框(globalDialog) | .notrat-global-dialog |
-accent / -title / -body / -actions / -action-primary |
8.2 弹窗 z-index 层级表
| 层级 | z-index | 用途 |
|---|---|---|
| 导入服务商 | 90 | 模态 |
| 角落提醒 | 9990 | 右下角非模态 |
| 推荐技能 | 9995 | 模态(带 backdrop) |
| 全局确认框 | 9999 | 最高优先 |
改弹窗层级前先想交互:角落提醒必须低于模态框,否则会把模态框顶穿。
8.3 一条规则统一改全部弹窗
{
"selector": ".notrat-corner-notify, .notrat-recommend-dialog, .notrat-import-dialog, .notrat-global-dialog",
"styles": { "border-color": "#e07856", "border-radius": "16px" }
}
8.4 单独改角落提醒(示例)
{ "selector": ".notrat-corner-notify", "styles": { "border": "2px solid hsl(16 68% 50%)", "box-shadow": "0 8px 30px hsl(16 68% 50% / 0.25)" } }
{ "selector": ".notrat-corner-notify-item-action", "styles": { "background": "hsl(16 68% 50%)", "color": "#fff" } }
九、踩过的坑(2026-07 实录)
- CDN Referer 热链保护:
public.cdn.nestmold.cn的图片带 Referer 请求返回 403,不带 200。Electron 里<img>默认带 Referer,技能图标/头像会裂图。源码里写<img>必须加referrerPolicy="no-referrer"。slot 改不了这个属性,只能改源码。 - backdrop-filter 创建 stacking context:给
.activity-bar这类容器加backdrop-filter: blur(...)后,整个子树(含内部 z-50 的下拉菜单)会被主内容区压在下面——菜单 z-index 多大都没用。弹层被遮挡时先查祖先有没有backdrop-filter/filter/transform/perspective。 - Electron 不支持
window.prompt():调用直接抛Error: prompt() is not supported。需要输入时改用应用内对话框(如 ImageDialog)或内联编辑,keymap 里用window.dispatchEvent(new CustomEvent(...))把事件桥到 React 组件里开对话框。 - slot 注入 CSS 变量 vs 最终值的区别:改
:root变量写 HSL 通道(40 30% 96%),改具体元素的color/background写完整值(hsl(40 30% 96%)或#hex),别混。 - 功能提交夹带实验代码:UI 突然和原版不一样时,先
git log -p -- <文件>查最近提交——已发生两次(Icons.tsx 被 debug 提交夹带全量改写、index.css 被 Slot 系统提交夹带背景实验 CSS)。 - 新增主进程/ preload IPC 必须完全重启 dev 应用:Ctrl+R 只刷渲染进程,新 handler 不存在会抛「No handler registered」并被静默 catch,表现为"功能完全没反应"。
十、相关公开接口(NotratPayment / notrat.cn)
| 接口 | 鉴权 | 用途 |
|---|---|---|
GET /api/skills |
公开 | 官方推荐技能列表(name/description/icon_url/skillhub_url/clawhub_url/sort_order) |
GET /api/campaigns/public-active |
OptionalAuth(可匿名) | 公开活动列表;带 token 时附 user_redeemed |
GET /api/campaigns/active |
Bearer | 已登录活动(含领取状态) |
POST /api/campaigns/free-trial |
Bearer | 领取免费体验(body: {campaign_id}) |
POST /api/campaigns/cashback/claim |
Bearer | 领取返现(body: {campaign_id}) |
mente 侧渲染层不直接调,走 preload:window.electronAPI.notratAuth.getPublicCampaigns() / getRecommendedSkills()。