# 更新日志

本文件记录 Naive Icons 的每个版本变更。版本号遵循语义化版本规范（SemVer）。

## 1.9.0

新增

- **Vue 3 版本 `naive-icons-vue`** —— 同样 201 枚图标、同样逐字节相同的图形与
  无障碍行为，组件 API 换成 Vue 那套。仓库里在 `vue/` 下独立成包，与 `naive-icons` 并存
  - 组件由 `scripts/generate_vue.py` 从 `svg/` 生成，与 React 版同源，图形不会走偏；
    `vue/tests/svg-parity.test.ts` 逐属性比对 201 枚组件与 `svg/` 源文件
  - `emit.py` 新增 `--format vue`，AI 助手能直接吐出 Vue 代码
  - 框架无关的描边归一逻辑（`resolveStrokeWidth` / `scaledStroke` / `safeDimension`）
    抽到 `core/`，React 版与 Vue 版共用同一份实现，描边缩放规则不会漂移
  - 单枚图标 minify 后约 **1.4 KB**（React 版 1.25 KB），tree-shaking 同样生效
  - API 与 React 版对齐：`size` / `color` / `strokeWidth` / `fill` / `title`，
    另有 `iconNames`、`createIcon`、`NAIVE_PALETTE`；
    拿 DOM 节点用 `ref.value.$el`（React 版是 `forwardRef` 直接给节点）
  - **两个包同版本发布**：自本版起 `naive-icons` 与 `naive-icons-vue` 版本号始终一致。
    `tests/version-sync.test.ts` 会断言两者版本相同，发版漏改一个 CI 就红

其他

- React 侧无功能变化。`core/` 重构后 `dist/` 产物与 1.8.0 **逐字节一致**，
  本版仅为与 Vue 版对齐版本号
- 官网补上 Vue 3 安装与用法、双框架安装命令、`npx skills add` 命令，
  FAQ 增补两条 Vue 条目，并修正两处过期数字（图标数、`color` 默认值）
- README 安装章节改为按 React / Vue 分流，两种包管理器命令各列全

## 1.8.0

新增

- **23 枚图标**（178 → **201**）：
  - 导航方位 8 枚 —— `arrow-up-left` 左上箭头、`arrow-down-left` 左下箭头、
    `arrow-down-right` 右下箭头、`arrow-up-circle` 向上圆圈、`arrow-down-circle` 向下圆圈、
    `arrow-left-circle` 向左圆圈、`arrow-right-circle` 向右圆圈、`map-pin` 地图标记
  - 操作 5 枚 —— `plus-circle` 加号圆圈、`minus-circle` 减号圆圈、`play-circle` 播放圆圈、
    `pause-circle` 暂停圆圈、`stop-circle` 停止圆圈
  - 日常物品 4 枚 —— `calculator` 计算器、`palette` 调色板、`radio` 收音机、
    `shopping-cart` 购物推车
  - 界面基础 2 枚 —— `user-circle` 圆形用户、`sparkles` 星光
  - 文件与媒体 2 枚 —— `newspaper` 报纸、`tv` 电视
  - 通信 2 枚 —— `bolt` 闪电、`wifi-off` 无线关闭
- 圆形容器家族沿用库内 `check-circle` / `x-circle` 的既有惯例：墨色描边圆 r=17 + 彩色符号，
  所以 7 枚圆圈图标与库内已有反馈类图标是同一套视觉语言
- `map-pin` 与 `shopping-cart` 刻意跟库内 `location` / `cart` 区分开——前者是「折页地图上插着
  气泡针」，后者是「装满商品的购物车」，避免库里出现两个几乎一样的图标

重绘

- **`arrow-up-right` 右上箭头** —— 原版是「橙色斜杆 + 转角头 + 青点」的**回信箭头**造型，
  与库里 `arrow-up` / `arrow-down` / `arrow-left` / `arrow-right` 的「墨杆 + 橙三角」
  是完全不同的两套语言；同一个「右上方向」在别的库里都是直箭头。
  改为墨杆 + 橙三角的直箭头，凑成 **8 枚对称方向箭头族**（4 正交 + 4 对角）。
  ⚠️ 造型有变，用过这枚图标的地方需要确认一下视觉效果

其他

- 开发依赖 `vitest` 升到 5.0.5，CI 的 Node 从 20 提到 22（vitest 5 要求 Node ≥ 22.12）
- 文档、注释与 skill 资产里的图标总数同步到 201

## 1.7.0

新增

- **15 枚图标**（163 → **178**）：
  - 导航方位 2 枚 —— `arrow-up-down` 上下双箭头（竖直 ⇅，两支箭头共轴、尖端朝外，
    对应「切换日期 / 切换月份与年份」）、`arrow-jump` 单箭头（上箭头 + 时间轴基线 +
    奶油色当前段，语义是「跳到时间轴某点」）
  - 界面基础 4 枚 —— `bold` 加粗、`italic` 斜体、`underline` 下划线、`user-minus` 移除成员
  - 日常物品 3 枚 —— `printer` 打印机、`clipboard` 剪贴板、`battery` 电池
  - 文件与媒体 3 枚 —— `rss` 订阅、`folder-plus` 新建文件夹、`folder-minus` 删除文件夹
  - 操作 2 枚 —— `scissors` 剪刀、`power` 电源
  - 交通工具 1 枚 —— `truck` 卡车
- **两个新 API**：
  - `iconNames` —— 178 个 kebab id 的**运行时数组**，外加类型 `IconId`。
    此前 `IconName` 只是纯类型、编译后即消失，运行时按名字取图标只能 `import * as naive`，
    那会把全部图标打进包、tree-shaking 直接归零；现在可以拿 `iconNames` 配动态 import，
    只拉真正用到的几枚
  - `createIcon(name, body)` —— 自建图标的工厂。根节点、无障碍属性、描边缩放与内置 178 枚一致；
    body 可以是普通节点，也可以是接收 `sw(designed)` 的函数——把设计时的描边宽度交给 `sw()`，
    整体加粗时层次才不会散
- `tests/createIcon.test.tsx` 12 条用例，钉住工厂产出与内置图标逐项一致

修复

- **30 枚既有图标的描边外缘边距不足 3 单位**，违反设计规范第 2 节。最严重的 `rainbow`
  与 `flag` 只有 **0.75**，`scooter` 只有 **0.25**——内容几乎贴边。
  统一按「绕画布中心 (24,24) 均匀缩放几何、保持描边宽度不变」修正，缩放幅度 0.4% ~ 12.7%，
  改完全库 178 枚都落在 3.05 ~ 15.65
- 新增 `tests/margin.test.ts` 回归测试：按描边外缘计算四边边距并要求 ≥ 3。
  这条规则以前只靠肉眼把关，攒到 30 枚违规都没被发现；而补图时最容易照着现有图标描，
  也就最容易继续复制违规——现在由代码钉住

其他

- `build_website.py` 清掉一处重复的 `'printer'` 键（同键同值，删除不影响行为）
- 文档、注释与 skill 资产里的图标总数同步到 178

## 1.6.0

新增

- **4 枚外设图标**，全部归入「日常物品」（18 → 22 枚），总数 159 → **163**：
  `keyboard` 键盘、`mouse` 鼠标、`monitor` 显示器、`charger` 充电头。
  配色刻意错开：键盘黄、鼠标与显示器青、充电头橙，无两枚撞色
- `search.py` 为 4 枚新图标补了同义词，「键鼠」「副屏」「快充」「电源适配器」等口语说法都能命中

重绘

- **`anchor` 锚** — 原版是纯线条图标，与库里「大实心主形体占 60%+」的三段式不合
  （设计规范里列的 16 枚纯线条图标不含它，它靠体积感识别）。改为 navy 单路径实心锚身，
  一条 path 画完竖杆 + 横杆 + U 形锚臂，轮廓是整体的一条墨线、无内部断线；橙色锚环作点缀
- **`watermelon` 西瓜** — 原版三层色块是嵌套填充、每层各带 3.5 宽墨边，色带被描边吃掉：
  按描边内缘算绿皮只剩 0.5 单位、白瓤是负的（两条边完全叠住，视觉上并不存在）。
  改为填充与轮廓线拆开——三层纯填充 + 外轮廓 + 两条 2.2 宽内部分界线，
  绿皮 0.5 → **2.15**、白瓤 0 → **1.30**，外层半径 17 → 19
- **`rocket` 火箭** — 保留原配色（奶油箭体 + 青舷窗 + 橙尾翼与火焰），只修几何

修复

- **`rocket` 火焰尖的底边距只有 0.25**，加描边外缘到 47.75，远低于 ≥3 的下限，
  是全库唯一一处越界。修正后为 3.75。同时箭体底从 `y38` 提到 `y34`、火焰上端延伸到 `y32`
  并压在箭体之下，原版箭体与火焰之间 4 单位的悬空缝隙消除

其他

- `width` / `height` 也走尺寸校验，不再绕过 `size`
- `strokeWidth=""` 回落 3.5（`Number('') === 0` 而非 NaN，空串原本会静默变成「不描边」）
- 文档、注释与 skill 资产里的图标总数同步到 163

## 1.5.3

修复

- `size` 不再泄漏进 svg 的 props。它是本库的语义属性而非 SVG 属性，之前留在 `...rest` 里被
  一并展开，污染下游（SSR 产物实测因此虚增 1.9%）
- `strokeWidth` 支持字符串。`"7"` 与 `7` 现在同样触发缩放；`'abc'` / `NaN` / 负数会回落到
  基准 3.5，不再直接透传成非法属性（Props 类型本来就允许 `number | string`）
- `strokeWidth={0}` 不再出现「外框 0、内层 3.5 与 4」的半残图标，根节点与内层一起归零
- 缩放结果取两位小数，不再输出 `11.428571428571429` 这类 17 位浮点
- `size={NaN}` / `size={Infinity}` 回落 24，不再报 `Received NaN`（`NaN < 0` 为 false，
  原来的负数校验挡不住它）
- `strokeWidth=""` 回落 3.5。`Number('') === 0` 而非 NaN，空串原本会静默变成「不描边」
- 文档同步：`strokeWidth` 的语义已是相对 3.5 的缩放系数，`patterns.md` 里按旧的绝对宽度
  语义写的整节已重写，Quick Start 示例与属性表同步更新

## 1.5.2

修复

- **109 / 159 枚图标（68%）的 JSX 里带 kebab-case 属性**。SVG 里 `stroke-width` /
  `stroke-linecap` / `stroke-linejoin` 是合法的 kebab-case，JSX 里必须写 camelCase。
  TSX 的 body 是从 SVG 原样搬过来的，历史上忘了转换，React 会报
  `Invalid DOM property \`stroke-width\``。该缺陷自 1.1/1.2 起就在线上（v1.3.0 时已有 89 枚命中）
- **`strokeWidth` 真正作用到整枚图标**。SVG 的 `stroke-width` 是可继承属性，但子元素一旦自带值
  就不再继承根节点。库里有 220 处内层自带描边（182 处是刻意的粗细层次：细节 1.5–2、
  主体 3.5、强调 4–5），所以以前只改根节点的话，`<Icon strokeWidth={7} />` 会得到
  「外框 7、内层还是 3.5 与 4」的断裂效果。现在内层写成 `strokeWidth={sw(设计值)}`，
  `sw` 由 `scaledStroke(props.strokeWidth)` 提供，把 `strokeWidth` 当作**相对 3.5 的缩放系数**：
  默认 3.5 时 scale 为 1，设计值一根线都不变；传 7 则所有描边一起加倍，层次关系保持
- `size` 传 `null` 时不再让尺寸属性消失。以前用解构默认值 `const { size = 24 }`，
  它只对 `undefined` 生效，于是 `size={isLarge ? 32 : null}` 这种很自然的写法会传进 `null`，
  结果 svg 上 `width` / `height` 属性整个缺失，图标按浏览器默认尺寸渲染。
  现在改用 `??`，负数同样回落 24；`size={0}` 保留（用 0 隐藏图标是合理用法）

其他

- 订正 1.5.1 CHANGELOG 里的体积数据。当时用 `sourcemap: false` 的探针构建去量，
  却发布了 `sourcemap: true` 的版本，数字对不上。实测 145.8 KB → 217.5 KB（单位 KB = 1024 字节）
- 发布时排除 `dist/**/*.map`（640 个文件，占 dist 总量 52%）。仓库里仍然保留，
  只是不进 tarball。tarball 因此从 217.5 KB 回到 **153.2 KB**，相对 1.5.0 只 +5.1%，
  文件数 1775 → 1135
- 两个生成器（`generate_icons.py` / `generate_icons_add.py`）都加上 kebab → camel 转换
  与描边缩放，`emit.py` 的 tsx 输出也一并修正，以后新增图标不会再犯
- `scaledStroke` 与 `normalizeIconProps` 从包入口导出
- 测试从 13 个增加到 27 个：
  - `tests/jsx-attrs.test.ts` 断言 159 个 tsx 的 JSX 体内没有 kebab 属性、内层描边是
    `sw(...)` 形式、svg/ 源文件仍保持 kebab（那是合法的，不能被「修」成 camel）
  - `tests/iconProps.test.ts` 补 size 的 5 个边界用例与 `scaledStroke` 的 4 组缩放用例

## 1.5.1

修复

- **tree-shaking 恢复生效**。以前只把 `src/index.ts` 作为单一入口，产物是一个大文件，
  里面有 159 条顶层 `XxxIcon.displayName = "..."` 赋值。打包器无法证明这些语句无副作用，
  于是整个模块必须保留，连带保留全部 159 个组件——`sideEffects: false` 只允许跳过
  「整个模块」，管不到模块内部的顶层语句，所以那时它等于没写。
  实测只导入 `HomeIcon` 一个图标会打进 **105,054 B（gzip 11.8 KB）**。
  改为每个图标各自成为入口 + `splitting: true` 后，同样的导入降到 **1,200 B**（约 1/88），
  产物里只剩用到的那一个图标。
  代价是 dist 文件数从 6 涨到约 960，tarball 从 145.8 KB 涨到 217.5 KB（+49%）、
  unpacked 从 1.37 MB 涨到 1.73 MB。1.5.2 起发布时排除 `.map`（占 dist 总量 52%），
  tarball 回到 153.2 KB，相对 1.5.0 只 +5.1%
- 新增 `naive-icons/icons/*` 子路径，可绕过顶层入口直接引单个图标
- `width` / `height` 不再被静默忽略。以前 `normalizeIconProps` 无条件写
  `svgProps.width = size`，导致 `width={40}` 渲染出来还是 24×24，README 承诺的
  「单独指定宽或高」根本做不到。现在 `width` / `height` 优先于 `size`，
  没传的那一边回落到 `size`：`size={32} width={64}` → 64 × 32
- 补上 1.0.0 CHANGELOG 提到过的 `IconCategory`：它实际在 1.2.0 重构 `types.ts` 时被移除，
  且从未从包入口导出过。1.5.1 起以本条为准，分类信息请查官网或 `catalog.md`

其他

- 新增测试：`npm test`（vitest），13 个用例
  - `tests/bundle-size.test.ts` 盯住单图标打包体积与残留图标数，
    把 tsup 配置改回单入口或关掉 splitting 会直接失败
  - `tests/iconProps.test.ts` 钉住 width/height 优先级规则
  - `tests/exports.test.ts` 钉住包入口的导出数量与 svg/ 目录的对应关系
- 新增 CI（`.github/workflows/ci.yml`）：typecheck → build → test，
  并校验官网数据与 skill 派生产物是否与 `svg/` 同源
- 补 `files` 里的 `skills`，`npm i naive-icons` 后可从 `node_modules` 直接取用 skill
- 把 `@types/react` 声明为可选 peer dependency。包的 `.d.ts` 引用了 React 类型，
  消费者若没装 `@types/react`，`SVGProps` 解析失败会让 `IconProps` 只剩自己声明的
  5 个属性——而这个错误会被 `skipLibCheck` 静默吞掉，直到用到 `className` 之类才暴露
- 移除有破坏性的 `npm run icons:build`：`scripts/generate_icons.py` 是 1.0.0 的一次性引导
  脚本，会把 `package.json` 写回 `0.1.0`、覆盖 `README.md`、重建 `src/index.ts`。
  现已从 npm scripts 摘除，并给脚本加了守卫：检测到仓库已有 100+ 图标就拒跑
- 归一 svg 文件格式：7 个文件去掉多余的尾换行，`scooter` 去掉 body 缩进。
  159 个 tsx 与 svg 现在全部同源，`emit.py` 可逐行复现

## 1.5.0

新增

- 官方 Agent Skill：让 AI 编码助手能按语义检索图标、输出可直接粘贴的代码，并知道这套图标的设计规范
- 一条命令装好，不用先装本库、不用挑 agent：

  ```bash
  npx skills add guokaigdg/naive-icons
  ```

  会先展示要装的内容再确认，并自动识别本机已装的 agent。
  可选 Project（跟着仓库走，团队共享）或 Global（装到用户目录），加 `-g` 可跳过该选择。
- Skill 自带全部 SVG 源码（收在 `scripts/icons.json` 一个文件里），装到哪都能出码，
  不依赖项目里是否装了本库
- 脚本只用 Python 标准库，skill 被装到任何位置都能跑
- 新增 `scripts/build_skill_assets.py`，从 `svg/` 生成 skill 的 `catalog.md` 与
  `icons.json`，并校验 `svg/`、`ICON_CATEGORY`、`ZH_NAMES` 三者一致

修复

- 补上 `index.ts` 对类型与色板的转发，`NAIVE_PALETTE`、`IconProps`、`IconName`、
  `IconComponent`、`PaletteColor` 从包入口真正可用了。此前 `src/types.ts` 里都有定义，
  但入口只导出 159 个图标组件，导致 README 里的
  `import { NAIVE_PALETTE } from 'naive-icons'` 报运行时 `SyntaxError`、
  `import type { IconProps } from 'naive-icons'` 报 `TS2305` / `TS2459`。
  该问题自 1.0.0 起就存在
- 两个生成器（`generate_icons.py` / `generate_icons_add.py`）的 `index.ts` 模板同步补上
  转发，否则下次新增图标时会被全量重建冲掉

## 1.4.0

新增

- 新增 25 个图标，图标总数增至 159
  - 界面基础 +11：users、user-plus、more-vertical、check-square、shield、bell-off、sliders、grid、list、ban、badge-check
  - 操作 +7：filter、sort、undo、redo、maximize、zoom-in、zoom-out
  - 文件与媒体 +3：volume、volume-x、paperclip
  - 通信 +2：send、inbox
  - 导航方位 +1：arrow-up-right
  - 交通工具 +1：scooter
- 撤销 / 重做改为墨色长弧搭配橙色实心箭头的形态，两枚互为镜像，箭头水平朝外
- 放大 / 缩小改用青色线框镜片加橙色大符号，与 search 的实心镜片彻底区分开

改进

- 重绘 refresh 为上下双弧的循环箭头，两段弧各占 120°，上下各留 100° 缺口，弧段与留白接近 1:2
- external-link 的橙色箭头描边由 3.5 加粗到 4.0，小尺寸下更清晰
- cart 从「交通工具」重新归入「日常物品」
- 官网取色器与主题换色改为只替换墨色描边。图标自带的彩色描边（橙色箭头、黄色勾等）本来就是 naive 风格的一部分，此前会被一并刷成单色

修复

- 官网深色模式下首次加载时，hero 贴纸改用奶油色描边，不会因墨色与深色底糊在一起而看不见
- hero 贴纸切换主题时只替换上一个主题色并在颜色未变时跳过，不再逐个重写 DOM
- 移除图标详情弹窗的左右切换按钮与键盘 ← → 导航，连带删除 step / indexOfCurrent 等死代码
- 扩充脚本重新生成 package.json 时会剥掉文件末尾的换行，导致凭空多出一行 diff，现已修复

## 1.3.0

新增

- 新增 9 个状态 / 反馈图标（alert-circle、alert-triangle、check-circle、eye-off、help-circle、info、lock-open、spinner、x-circle），图标总数增至 134

改进

- 微调 check 图标勾形几何，提升小尺寸下的清晰度

## 1.2.0

新增

- 新增 9 个图标（basketball、dumbbell、google-chrome、mountain、tent、pause、stop、coffee-cup、water-cup），图标总数增至 125
- 官网图标总数改为从图标数据动态读取，不再硬编码，避免与 svg/ 实际数量脱节

改进

- 重绘 airplane 机尾与 snowflake 雪花几何，雪花改为三等分旋转结构
- 官网图标浏览器工具栏吸顶时改为直角，与头部贴合；圆角改用独立变量，修复左上/右上边框显示不全的问题

## 1.1.0

新增导航 / 操作骨架一组图标（menu、chevron 四向、ellipsis、external-link、link / unlink、copy、minus），图标总数增至 116。

修复

- 修正 `IconName` 类型中图标名后缀重复的问题，现在与组件导出名一一对应
- 全部 105 个组件改用 `forwardRef`，支持 ref 透传，并补全 `displayName` 便于 DevTools 识别
- 补齐无障碍属性：装饰性图标默认 `aria-hidden`，传入 `title` 时自动渲染 `<title>` 子节点并标记 `role="img"`
- `normalizeIconProps` 不再把 `title` 误写为原生 `title` 属性，避免与无障碍 `<title>` 节点冲突

改进

- 官网三层（HTML / CSS / JS）完全重写：语义化标签、统一的设计令牌体系（间距 4px 基数、圆角与阴影尺度）、清除模板导出的冗余属性
- 信息架构收敛：原先并列的 4 个代码面板合并为「安装 / React / SVG / TypeScript」标签页，调色板与设计原则合并为「设计规范」一节
- 视觉基调改为温暖手绘：纸张颗粒纹理、暖调深色模式、手绘分隔线，浅色与深色主题均可手动切换并记忆
- 新增 4 个方向键图标：上（arrow-up）、下（arrow-down）、左（arrow-left）、右（arrow-right），与已有的关闭（close）图标组成基础方向/操作图标组；同步更新 `index.ts`、`types.ts`、`svg/` 与官网数据
- 引入 LXGW 悠哉字体（OFL，自托管子集化，仅 715 个字符 ≈ 170KB ×2 个字重）作为网站字体；图标库本体仍无任何字体/资源依赖
- 图标浏览器工具栏在宽屏下吸顶，新增分类结果计数、搜索清空、描边快捷色板与自定义取色器
- 预览切换深色底时，若描边仍为默认墨黑会自动换成奶油色，避免图标不可见；用户显式选择的颜色不会被改写
- 详情弹窗支持键盘方向键连续切换图标，打开时背景内容设为 inert
- 无障碍补强：skip link、aria-live 结果计数、标签页方向键切换、焦点归还

## 1.0.2

修复

- 修复组件不传 `size` 时没有明确尺寸的问题：`normalizeIconProps` 现在始终向 svg 写入 `width` / `height`，默认 24，保证 `<HomeIcon />` 也有稳定的 24px 尺寸
- 顺手补上默认 `fill="none"`，避免与 SVG 内部已有的 `fill` 属性在覆盖时产生歧义

## 1.0.1

修复

- 修复 1.0.0 中组件未真正处理 `size` 与 `color` 属性的问题：现在 `size` 会同时映射为 `width` 与 `height`、`color` 会映射为描边 `stroke`，行为与 README 文档示例一致；`strokeWidth` 同样正确透传

## 1.0.0

首个正式版本发布。

新增

- 105 个手绘 naive folk art 风格 SVG 图标，覆盖界面基础、操作、文件与媒体、导航方位、通信、自然天气、动物、食物饮品、日常物品、交通工具、表情共 11 个分类
- 每个图标同时提供 SVG 源文件与 React TSX 组件
- 完整 TypeScript 类型定义：IconProps、IconName、IconCategory、PaletteColor、NAIVE_PALETTE
- 统一规格：48x48 viewBox、3.5 描边宽度、round 线帽与线角
- 9 色复古调色板，可作为设计令牌直接引用
- 官方文档站点，支持搜索、分类筛选、尺寸与描边颜色实时调整、一键复制与下载
- MIT 协议，全部图标为原创作品

改进

- 组件默认使用 currentColor，可自动继承父级文字颜色
- 支持 size、color、strokeWidth、fill、title 五个语义属性，同时继承全部原生 SVG 属性
- 单个图标体积控制在 400 至 700 字节，无运行时依赖
