- 后端
- 前端
- CRM
- 人工智能
- AI Agent
【免费下载链接】crm
Comp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM.
本文以仓库内
.agents/skills/better-ui/icons.md设计工程规范为主体,结合 Comp AI CRM(开源 Agentic-first CRM)前端实际使用的 Lucide 图标体系与 shadcn/ui 配置,系统讲解图标描边权重、状态着色、轮廓/填充语义、渲染尺寸设计以及 RTL 翻转五大法则。读完你将掌握一套可直接落地的图标使用规范——从「单个图标好不好看」进阶到「整套图标在界面里是否自洽」,并能用 CSS 与 Tailwind 代码在真实组件中复现。
图标是界面中最容易被低估的细节:单个图标看起来没问题,放进界面却总让人觉得「哪里不对」。Comp AI CRM 的设计工程技能集(.agents/skills/better-ui/)把这类问题归结为一条主线——图标的光学重量、状态表达、尺寸适配与方向语义。本文围绕该技能集中的 icons.md 展开,并用仓库前端代码(apps/app 与 packages/ui)中的真实用法作为佐证。
一、仓库里的图标事实基础:Lucide 与currentColor
在进入规范之前,先确认本仓库的图标体系。Comp AI CRM 的 shadcn/ui 配置在两个层级都声明了统一的图标库:
- apps/app/components.json:
"iconLibrary": "lucide" - packages/ui/components.json:
"iconLibrary": "lucide"
对应到代码层面,packages/ui的组件统一从lucide-react导入图标,例如 accordion.tsx 的ChevronDownIcon / ChevronUpIcon、checkbox.tsx 的CheckIcon / MinusIcon、combobox.tsx 的ChevronDownIcon。这意味着全仓库共用一套 Lucide 线框图标,其默认stroke-width为1.5(24px 网格)、统一使用currentColor着色——这正是下文所有规范能够成立的前提:图标库本身支持描边变体,因此「描边匹配文字字重」与「状态用 CSS 驱动」两条规则在本仓库完全适用。
仓库配置了
"style": "radix-nova"、"baseColor": "neutral"与 CSS 变量模式(见 apps/app/components.json),图标作为独立层不受这些配置影响,但仍应遵守「一表面一套描边策略」的约束。
二、让图标与文字「同重」:描边宽度匹配文本字重
图标与相邻文字并排时,视觉上应该承载相同的光学重量,否则二者看起来不匹配:细线图标配粗体文字显得「断了」,粗重图标配常规文字则显得「吵闹」。核心做法是让图标描边宽度跟随文字字重变化:
| 相邻文字 | 图标描边宽度(24px 网格) |
|---|---|
| Regular(400),14–16px | 1.5px |
| Medium/Semibold(500–600) | 2px |
| Bold(700),或强调的独立展示 | 2.5px |
好与坏的对照
<!-- 好:描边与标签字重匹配 --> <button class="flex items-center gap-2 font-semibold"> <PlusIcon stroke-width="2" class="size-4" /> New project </button> <!-- 坏:默认 1.5px 描边对着粗体标签 --> <button class="flex items-center gap-2 font-bold"> <PlusIcon stroke-width="1.5" class="size-4" /> New project </button>Lucide 的 React 组件接受strokeWidth属性,因此在 Comp AI CRM 中可直接这样调整:<PlusIcon strokeWidth={2} className="size-4" />(React 中驼峰写法)。注意class需改为className,stroke-width改为strokeWidth。
两条相关的一致性规则
- 每个表面只采用一种光学策略。不要在同一个工具栏里混用描边约定互不兼容的图标库。如果所选图标库原生支持描边变体(Lucide 即是),就按上表让它匹配相邻文字;否则保持该图标集的固有描边,用尺寸或颜色来强调,而不是换一套图标。
- 图标尺寸相对文字的 x-height 设定。与文字内联时,图标尺寸通常取
1em–1.25em,让二者随字号一起缩放。在 Tailwind 中即size-4(16px)对应 14px 文字、size-5(20px)对应 16px 文字这类配对,或直接使用w-[1.2em]跟随字体大小。
仓库中的落地参照:spinner.tsx 通过strokeWidth控制加载指示器线条粗细,dashboard-chart.tsx 同样使用描边参数,证明「用描边而非换图」是团队既有做法。
三、一份 SVG,多种状态:currentColor与 CSS 状态着色
永远不要为 default / hover / selected / disabled 各准备一份图标资产。正确做法是:用一个以currentColor绘制的 SVG,让 CSS 状态驱动颜色。
<!-- 好:一份资产,状态交给 CSS --> <svg fill="none" stroke="currentColor" stroke-width="2">…</svg>.icon-button { color: oklch(0.552 0.016 285.938); } .icon-button:hover { color: oklch(0.21 0.006 285.885); } .icon-button[aria-pressed="true"] { color: oklch(0.623 0.188 259.815); } .icon-button:disabled { opacity: 0.4; }Tailwind 版本(Comp AI CRM 使用 Tailwind,见 packages/ui/src/styles/globals.css):
<button class="text-zinc-500 hover:text-zinc-900 aria-pressed:text-blue-600 disabled:opacity-40"> <BookmarkIcon /> </button>关键禁忌:SVG 内部写死的fill="#666"会破坏这一机制。导入图标时若发现硬编码填充,必须剥离为currentColor。Lucide 图标本身就是stroke="currentColor",因此导入后无需处理;但若从其他来源复制 SVG(如设计稿导出的单色图标),务必检查并替换。
从仓库角度看,这一规则与 globals.css 中定义的 CSS 变量令牌体系一致——颜色状态由 token 与工具类驱动,而非为状态复制图标文件。
四、轮廓为默认,填充为激活:用变体表达状态
当图标集同时提供 outline 与 fill 两种变体时,应把它们当作状态对使用,而不是随意混用:
| 变体 | 用途 |
|---|---|
| Outline | 默认状态:工具栏、列表行、与文字内联 |
| Fill | 选中/激活状态:当前标签页、已收藏的书签、已点赞的心形 |
// 好:变体传达状态 <TabIcon variant={isActive ? "solid" : "outline"} /> // 坏:到处都是填充图标,激活标签页反而失去了状态信号 <TabIcon variant="solid" />如果同一图标集没有 fill 变体(Lucide 部分图标需要fill="currentColor"显式开启填充),则用颜色 + 描边双重信号表达激活:激活项用text-primary加粗描边,未激活项用次级色。
变体切换时的动画
轮廓/填充之间的切换属于上下文图标动画。原文规范明确指出:应使用 animations.md 中规定的精确交叉淡化数值——scale从0.25到1、opacity从0到1、blur从4px到0px;使用 Motion 时transition: { type: "spring", duration: 0.3, bounce: 0 }(bounce 必须为 0);无动效库时用 CSS 交叉淡化cubic-bezier(0.2, 0, 0, 1),且两个图标同时留在 DOM 中、其中一个绝对定位。这里不展开动画细节,完整参数见 animations.md 的「Contextual Icon Animations」一节。
五、按渲染尺寸设计:16px 下依然可辨认
一个在 48px 下很漂亮的图标,缩到 16px 可能糊成一团。大尺寸下能看清的细节(细内线、紧密字怀、细腻纹理)在小尺寸时会发生模糊或锯齿。
四条硬性要求:
- 在每个图标将要渲染的最小尺寸下测试它(通常为
16px),它必须在那里依然可辨认。 - 小场景优先用简化字形,而不是等比缩小精细图稿。
- 在渲染尺寸上对齐像素网格:16px 图标如果用 24px 网格做分数缩放,会渲染发软。使用图标集的原生网格尺寸(
16、20、24),不要随意缩放。 - 永远用 SVG,不用位图,同一份资产才能在任意密度下保持清晰。
在 Comp AI CRM 中,size-4(16px)、size-5(20px)正好对应 Lucide 原生网格;工具栏图标一律用size-4,行内强调图标可用size-5。避免size-[17px]这类非网格尺寸。
六、RTL 下的图标翻转:只翻方向相关的
在dir="rtl"环境下,只翻转含义与阅读方向绑定的图标,其余保持原样:
| 翻转 | 不翻转 |
|---|---|
| 后退/前进箭头、导航中的 chevron | Logo 与品牌标识 |
| 文本块字形(对齐、列表、缩进) | 对勾(checkmark) |
| 扬声器/音量波纹(沿阅读方向发散) | 物理物件:时钟、杯子、铅笔 |
| 「发送」类方向字形 | 媒体播放(播放/快退参照磁带方向,惯例保持 LTR) |
CSS 实现(仅镜像方向依赖图标):
/* 好:只镜像方向依赖的图标 */ [dir="rtl"] .icon-directional { scale: -1 1; }Tailwind 实现:
<ChevronRightIcon class="icon-directional rtl:-scale-x-100" />两个进阶要点:
- 复合图标要逐部分分析:徽标(badge)或斜杠叠加层在基础字形翻转后可能仍需保持原位。
- 仅图标按钮的无障碍名称由
better-accessibility技能覆盖,见 better-accessibility/SKILL.md。
仓库当前components.json中"rtl": false(见 apps/app/components.json),但设计工程规范仍要求代码具备 RTL 正确性,以便未来启用国际化时(见 i18n ADR)不返工。
七、把这些法则放进代码评审
上述规范在 better-ui/SKILL.md 中被编码为可审查的原则,其「常见错误」清单可以作为图标自查表:
| 错误 | 修正 |
|---|---|
| 细线图标配粗体文字 | 让描边宽度匹配文字字重 |
| 每种状态一份图标资产 | 一份currentColorSVG,状态交给 CSS |
| 到处用填充图标 | 轮廓为默认,填充只用于激活状态 |
结合 better-ui 的评审方法:慢放动画(浏览器 Animations 面板 10% 速度)逐状态走查 hover、focus、active、disabled,图标是否「发虚」「过重」「方向错误」会非常明显。评审输出时用 Severity / Location / Before / After / Why 表格记录,引用path/to/file:line(例如packages/ui/src/components/accordion.tsx:5)。
小结
图标设计的本质不是「选一个好看的图标」,而是让图标体系在光学重量、状态语义、渲染清晰度与方向一致性上整体自洽。在 Comp AI CRM 中,这套规范有明确的落地载体:统一 Lucide 图标库(packages/ui/components.json)、currentColor+ CSS 变量状态着色(globals.css)、以及 16/20/24 原生网格尺寸。遵循本文五条法则,再配合 animations.md 规定的图标切换动画,图标就能真正「坐进」界面,而不是贴上去。
- 后端
- 前端
- CRM
- 人工智能
- AI Agent
【免费下载链接】crm
Comp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM.
相关推荐
ZyPlayer自定义光标:界面个性化的细节设计
ZyPlayer自定义光标:界面个性化的细节设计 光标作为用户与界面交互的直接媒介,其设计质量直接影响操作体验。ZyPlayer在界面设计中通过精心规划的光标样
桌面应用音视频即时通讯Ant Design Breadcrumb 图标用法:在面包屑中把图标放在文字前面
Ant Design Breadcrumb 图标用法:在面包屑中把图标放在文字前面 导读 本篇基于 ant design 仓库中 components/brea
前端UI组件设计系统从0到1搭建开发环境:Linux on LiteX-VexRiscv依赖安装与配置详解
从0到1搭建开发环境:Linux on LiteX VexRiscv依赖安装与配置详解 Linux on LiteX VexRiscv是一个基于VexRiscv
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考