feat: 接入 iconify 图标库,右栏改成 Figma 式收起分组

图标统一走 unplugin-icons + hugeicons,构建期内联,出口收在 src/ui/icons.ts。
顺带修掉 TopBar 那个 undo 图标缺弧命令的 path。

右栏下半四组默认全收,收起态只有一行 32px;顶栏导出按钮改成先展开
「导出与模板」再滚,否则滚到底只看得到一行标题。

属性区去掉分组标题,改成 Figma 那种「字母/图标 + 无边框输入框」两列密排,
新增 W/H 宽高比锁(比例在开锁那一刻定格,不每次编辑现算)。

删掉 Sidebar.vue 和 panels/CanvasPanel.vue:上一轮改 Figma 布局之后
它们已无人 import,--sidebar-w 同批遗留。
This commit is contained in:
2026-09-05 17:51:43 +08:00
parent ee303bcd44
commit 3a3798e37b
16 changed files with 722 additions and 619 deletions
+81
View File
@@ -0,0 +1,81 @@
/**
* 全站图标出口。**组件不要直接写 `~icons/...`**,一律从这里 import。
*
* 这么做的理由是「同一个动作在任何地方长同一个样」:删除在图层行、右键菜单、
* 选中浮条上是三个组件,但只要它们都用 `IconDelete`,换图标就是改这一行。
*
* 图标集统一用 **hugeicons**(24×24、`fill:none` + `stroke:currentColor`、
* stroke-width 1.5),风格和 Figma 的界面图标一致。混用别的集会在同一行里
* 出现粗细不一的描边,所以要加新图标先在 hugeicons 里找:
*
* node scripts/find-icon.mjs <关键词>
*
* `~icons/*` 由 vite.config.ts 的 unplugin-icons 在构建期解析成 Vue 组件,
* 只有用到的图标会进产物,不联网。类型来自 tsconfig 的
* `unplugin-icons/types/vue`。
*
* 尺寸和颜色由 CSS 控制:插件给每个图标挂了 `.icon` 类,规则在 style.css。
*/
/* ---- 工具 ---- */
export { default as IconSelect } from "~icons/hugeicons/cursor-01";
export { default as IconText } from "~icons/hugeicons/text-font";
export { default as IconRect } from "~icons/hugeicons/square";
export { default as IconImage } from "~icons/hugeicons/image-01";
/* ---- 历史与导出 ---- */
export { default as IconUndo } from "~icons/hugeicons/undo";
export { default as IconRedo } from "~icons/hugeicons/redo";
export { default as IconExport } from "~icons/hugeicons/download-01";
/* ---- 视口 ---- */
export { default as IconZoomIn } from "~icons/hugeicons/plus-sign";
export { default as IconZoomOut } from "~icons/hugeicons/minus-sign";
export { default as IconFit } from "~icons/hugeicons/maximize-01";
/* ---- 图层行 ---- */
export { default as IconEye } from "~icons/hugeicons/eye";
export { default as IconEyeOff } from "~icons/hugeicons/eye-off";
export { default as IconLocked } from "~icons/hugeicons/square-lock-01";
export { default as IconUnlocked } from "~icons/hugeicons/square-unlock-01";
export { default as IconDelete } from "~icons/hugeicons/delete-02";
export { default as IconDuplicate } from "~icons/hugeicons/copy-01";
/* ---- 层序 ---- */
export { default as IconBringToFront } from "~icons/hugeicons/layer-bring-to-front";
export { default as IconSendToBack } from "~icons/hugeicons/layer-send-to-back";
export { default as IconBringForward } from "~icons/hugeicons/arrow-up-01";
export { default as IconSendBackward } from "~icons/hugeicons/arrow-down-01";
/* ---- 属性 ---- */
export { default as IconArtboard } from "~icons/hugeicons/artboard";
export { default as IconLinked } from "~icons/hugeicons/link-02";
export { default as IconUnlinked } from "~icons/hugeicons/unlink-02";
export { default as IconAngle } from "~icons/hugeicons/angle";
export { default as IconRadius } from "~icons/hugeicons/square-round-corner";
export { default as IconOpacity } from "~icons/hugeicons/contrast";
/* ---- 对齐与分布 ---- */
export { default as IconAlignLeft } from "~icons/hugeicons/align-left";
export { default as IconAlignCenterH } from "~icons/hugeicons/align-horizontal-center";
export { default as IconAlignRight } from "~icons/hugeicons/align-right";
export { default as IconAlignTop } from "~icons/hugeicons/align-top";
export { default as IconAlignCenterV } from "~icons/hugeicons/align-vertical-center";
export { default as IconAlignBottom } from "~icons/hugeicons/align-bottom";
export { default as IconDistributeH } from "~icons/hugeicons/distribute-horizontal-center";
export { default as IconDistributeV } from "~icons/hugeicons/distribute-vertical-center";
/* ---- 文字 ---- */
export { default as IconBold } from "~icons/hugeicons/text-bold";
export { default as IconTextLeft } from "~icons/hugeicons/text-align-left";
export { default as IconTextCenter } from "~icons/hugeicons/text-align-center";
export { default as IconTextRight } from "~icons/hugeicons/text-align-right";
/* ---- 右栏分组 ---- */
export { default as IconFilter } from "~icons/hugeicons/blur";
export { default as IconTemplate } from "~icons/hugeicons/layers-01";
/* ---- 通用 ---- */
export { default as IconChevronRight } from "~icons/hugeicons/chevron-right";
export { default as IconChevronDown } from "~icons/hugeicons/chevron-down";
export { default as IconPlus } from "~icons/hugeicons/plus-sign";
+22
View File
@@ -0,0 +1,22 @@
import { ref } from "vue";
/** 右栏下半的四个工具分组。 */
export type ToolGroupId = "bg" | "filter" | "text" | "export";
/**
* 「请求展开某一组」的信号。
*
* 四个组默认全部收起,所以顶栏那个导出按钮光滚到底是没用的——滚过去只看得到
* 一行标题。别处要把用户送到某个面板前,就调 `openToolGroup(id)`,
* `ToolPanels` watch 这个 ref 把对应的组打开。
*
* 带一个自增序号,是为了让**连点两次同一个组**也能触发 watch:只放 id 的话
* 第二次赋的是同一个字符串,ref 不变,watch 不响应,用户会觉得按钮坏了。
*/
export const toolGroupRequest = ref<{ id: ToolGroupId; seq: number } | null>(null);
let seq = 0;
export function openToolGroup(id: ToolGroupId) {
toolGroupRequest.value = { id, seq: seq++ };
}