This commit is contained in:
oneao committed 2025-09-04 17:31:49 +08:00
1 parent 068fcb7649
commit 1a33497c5d
29 files changed
+889 -306

No files matched your search

@@ -2,45 +2,85 @@
$prefix: 'ao' !default;
// 基础颜色
$primary: var(--ao-primary); // 色彩-品牌-可操作
$warning: var(--ao-warning); // 色彩-功能-警告
$danger: var(--ao-danger); // 色彩-功能-失败
$success: var(--ao-success); // 色彩-功能-成功
$default-color: var(--ao-default-color); // 色彩-品牌-可操作
$primary-color: var(--ao-primary-color); // 色彩-品牌-可操作
$warning-color: var(--ao-warning-color); // 色彩-功能-警告
$danger-color: var(--ao-danger-color); // 色彩-功能-失败
$success-color: var(--ao-success-color); // 色彩-功能-成功
// 默认颜色的扩展 用于 hover / 聚焦 / 禁用 / 点击 等状态
$default-color-hover: var(--ao-default-color-hover); // hover态
$default-color-focus: var(--ao-default-color-focus); // focus态,包括鼠标和键盘
$default-color-active: var(--ao-default-color-active); // 点击态
$default-color-disabled: var(--ao-default-color-disabled); // 禁用态
// 基础颜色的扩展 用于 hover / 聚焦 / 禁用 / 点击 等状态
$primary-hover: var(--ao-primary-hover); // hover态
$primary-focus: var(--ao-primary-focus); // focus态,包括鼠标和键盘
$primary-active: var(--ao-primary-active); // 点击态
$primary-disabled: var(--ao-primary-disabled); // 禁用态
$primary-color-hover: var(--ao-primary-color-hover); // hover态
$primary-color-focus: var(--ao-primary-color-focus); // focus态,包括鼠标和键盘
$primary-color-active: var(--ao-primary-color-active); // 点击态
$primary-color-disabled: var(--ao-primary-color-disabled); // 禁用态
// 警告色扩展
$warning-hover: var(--ao-warning-hover);
$warning-focus: var(--ao-warning-focus);
$warning-active: var(--ao-warning-active);
$warning-disabled: var(--ao-warning-disabled);
$warning-color-hover: var(--ao-warning-color-hover);
$warning-color-focus: var(--ao-warning-color-focus);
$warning-color-active: var(--ao-warning-color-active);
$warning-color-disabled: var(--ao-warning-color-disabled);
// 失败/错误色扩展
$danger-hover: var(--ao-danger-hover);
$danger-focus: var(--ao-danger-focus);
$danger-active: var(--ao-danger-active);
$danger-disabled: var(--ao-danger-disabled);
$danger-color-hover: var(--ao-danger-color-hover);
$danger-color-focus: var(--ao-danger-color-focus);
$danger-color-active: var(--ao-danger-color-active);
$danger-color-disabled: var(--ao-danger-color-disabled);
// 成功色扩展
$success-hover: var(--ao-success-hover);
$success-focus: var(--ao-success-focus);
$success-active: var(--ao-success-active);
$success-disabled: var(--ao-success-disabled);
$success-color-hover: var(--ao-success-color-hover);
$success-color-focus: var(--ao-success-color-focus);
$success-color-active: var(--ao-success-color-active);
$success-color-disabled: var(--ao-success-color-disabled);
// 文本颜色
$text-primary: var(--ao-text-primary); // 色彩-文字-主要
$text-secondary: var(--ao-text-secondary); // 色彩-文字-次要
$text-assist: var(--ao-text-secondary); // 色彩-文字-次要
$text-placeholder: var(--ao-text-placeholder); // 色彩-文字-占位符/说明
$text-disabled: var(--ao-text-disabled); // 色彩-文字-禁用
$text-anti: var(--ao-text-anti); // 色彩-文字-反色
$text-primary: var(--ao-text-primary); // 色彩-文字-品牌
$text-link: var(--ao-text-link); // 色彩-文字-链接
$text-color-base: var(--ao-text-color-base); // 色彩-文字-主要
$text-color-secondary: var(--ao-text-color-secondary); // 色彩-文字-次要
$text-color-assist: var(--ao-text-color-assist); // 色彩-文字-次要
$text-color-placeholder: var(--ao-text-color-placeholder); // 色彩-文字-占位符/说明
$text-color-disabled: var(--ao-text-color-disabled); // 色彩-文字-禁用
$text-color-anti: var(--ao-text-color-anti); // 色彩-文字-反色
$text-color-link: var(--ao-text-color-link); // 色彩-文字-链接
$border-radius: 2px;
$border-divider: var(--ao-stroke); // 分割线(内容区域之间的分隔,如列表、面板内部)
$border-component: var(--ao-border); // 组件边框(Input、Select、Card 等容器的外部边框)
$stroke-color: var(--ao-stroke-color); // 分割线(内容区域之间的分隔,如列表、面板内部)
$border-color: var(--ao-border-color); // 组件边框(Input、Select、Card 等容器的外部边框)
$bg-color-control: var(
--ao-bg-color-control
); // 特殊组件背景色,目前只用于 button、input 组件多主题场景,浅色主题下固定为白色,深色主题下为 transparent 适配背景颜色
// 高度
$size-height-small: 24px;
$size-height-medium: 28px;
$size-height-large: 32px;
// 字体大小
$size-font-small: 12px;
$size-font-medium: 13px;
$size-font-large: 14px;
// 滚动条颜色
$scrollbar-color: var(--ao-scrollbar-color);
// 滚动条悬浮颜色
$scrollbar-hover-color: var(--ao-scrollbar-hover-color);
// 滚动条轨道颜色
$scroll-track-color: var(--ao-scroll-track-color);
// 容器颜色,使用的组件:popup
$bg-color-container: var(--ao-bg-color-container);
$bg-color-container-hover: var(--ao-bg-color-container-hover);
$bg-color-container-active: var(--ao-bg-color-container-active);
// shadow
// 基础/下层 投影 hover 使用的组件包括:表格 /
$shadow-surface: var(--ao-shadow-surface);
// 中层投影 下拉 使用的组件包括:下拉菜单 / 气泡确认框 / 选择器 /
$shadow-popup: var(--ao-shadow-popup);
// 上层投影(警示/弹窗)使用的组件包括:全局提示 / 消息通知
$shadow-overlay: var(--ao-shadow-overlay);
@@ -1,39 +1,66 @@
:root[theme-mode='dark'] {
--ao-primary: #4582e6;
--ao-warning: #cf6e2d;
--ao-danger: #c64751;
--ao-success: #059465;
--ao-default-color: #393939;
--ao-primary-color: #4582e6;
--ao-warning-color: #cf6e2d;
--ao-danger-color: #c64751;
--ao-success-color: #059465;
--ao-primary-hover: #2667d4;
--ao-primary-focus: #173463;
--ao-primary-active: #699ef5;
--ao-primary-disabled: #143975;
--ao-default-color-hover: #4b4b4b;
--ao-default-color-focus: #505050;
--ao-default-color-active: #5c5c5c;
--ao-default-color-disabled: #2c2c2c;
--ao-warning-hover: #a75d2b;
--ao-warning-focus: #582f21;
--ao-warning-active: #dc7633;
--ao-warning-disabled: #733c23;
--ao-primary-color-hover: #2667d4;
--ao-primary-color-focus: #173463;
--ao-primary-color-active: #699ef5;
--ao-primary-color-disabled: #143975;
--ao-danger-hover: #a03f46;
--ao-danger-focus: #5e2a2d;
--ao-danger-active: #de6670;
--ao-danger-disabled: #703439;
--ao-warning-color-hover: #a75d2b;
--ao-warning-color-focus: #582f21;
--ao-warning-color-active: #dc7633;
--ao-warning-color-disabled: #733c23;
--ao-success-hover: #0d7a55;
--ao-success-focus: #1a4230;
--ao-success-active: #43af8a;
--ao-success-disabled: #17533d;
--ao-danger-color-hover: #a03f46;
--ao-danger-color-focus: #5e2a2d;
--ao-danger-color-active: #de6670;
--ao-danger-color-disabled: #703439;
--ao-text-primary: rgba(255, 255, 255, 90%); /* 主要文字 */
--ao-text-secondary: rgba(255, 255, 255, 55%); /* 次要文字 / 辅助信息 */
--ao-text-assist: rgba(255, 255, 255, 45%); /* 输入框内部辅助元素(icon/count) */
--ao-text-placeholder: rgba(255, 255, 255, 35%); /* 占位符 / 说明文字 */
--ao-text-disabled: rgba(255, 255, 255, 22%); /* 禁用文字 */
--ao-text-anti: #fff; /* 反色文字(深色背景上) */
--ao-text-brand: #4582e6; /* 品牌色文字 / 主操作色 */
--ao-text-link: #4582e6; /* 链接文字 */
--ao-text-watermark: rgba(255, 255, 255, 10%); /* 水印 / 背景文字 */
--ao-success-color-hover: #0d7a55;
--ao-success-color-focus: #1a4230;
--ao-success-color-active: #43af8a;
--ao-success-color-disabled: #17533d;
--ao-stroke: #393939; // 分割线
--ao-border: #5e5e5e; // 边框
--ao-text-color-base: rgba(255, 255, 255, 90%); /* 主要文字 */
--ao-text-color-secondary: rgba(255, 255, 255, 55%); /* 次要文字 / 辅助信息 */
--ao-text-color-assist: rgba(255, 255, 255, 45%); /* 输入框内部辅助元素(icon/count) */
--ao-text-color-placeholder: rgba(255, 255, 255, 35%); /* 占位符 / 说明文字 */
--ao-text-color-disabled: rgba(255, 255, 255, 22%); /* 禁用文字 */
--ao-text-color-anti: #fff; /* 反色文字(深色背景上) */
--ao-text-color-link: #4582e6; /* 链接文字 */
--ao-text-color-watermark: rgba(255, 255, 255, 10%); /* 水印 / 背景文字 */
--ao-stroke-color: #393939; // 分割线
--ao-border-color: #5e5e5e; // 边框
--ao-bg-color-control: transparent; // 特殊组件背景色,目前只用于 button、input 组件多主题场景,浅色主题下固定为白色,深色主题下为 transparent 适配背景颜色
// 滚动条颜色
--ao-scrollbar-color: rgba(255, 255, 255, 10%);
// 滚动条悬浮颜色( hover )
--ao-scrollbar-hover-color: rgba(255, 255, 255, 30%);
// 滚动条轨道颜色,不能是带透明度,否则纵向滚动时,横向滚动条会穿透
--ao-scroll-track-color: #333;
// 容器颜色,使用的组件:popup
--ao-bg-color-container: #242424;
--ao-bg-color-container-hover: #2c2c2c;
--ao-bg-color-container-active: #4b4b4b;
// shadow阴影
// 基础/下层 投影 hover 使用的组件包括:表格 /
--ao-shadow-surface: 0 4px 6px rgba(0, 0, 0, 6%), 0 1px 10px rgba(0, 0, 0, 8%), 0 2px 4px rgba(0, 0, 0, 12%);
// 中层投影 下拉 使用的组件包括:下拉菜单 / 气泡确认框 / 选择器 /
--ao-shadow-popup: 0 8px 10px rgba(0, 0, 0, 12%), 0 3px 14px rgba(0, 0, 0, 10%), 0 5px 5px rgba(0, 0, 0, 16%);
// 上层投影(警示/弹窗)使用的组件包括:全局提示 / 消息通知
--ao-shadow-overlay: 0 16px 24px rgba(0, 0, 0, 14%), 0 6px 30px rgba(0, 0, 0, 12%), 0 8px 10px rgba(0, 0, 0, 20%);
}
@@ -1,40 +1,69 @@
:root,
:root[theme-mode='light'] {
--ao-primary: #0052d9;
--ao-warning: #e37318;
--ao-danger: #d54941;
--ao-success: #2ba471;
--ao-default-color: #e7e7e7;
--ao-primary-color: #0052d9;
--ao-warning-color: #e37318;
--ao-danger-color: #d54941;
--ao-success-color: #2ba471;
--ao-primary-hover: #366ef4;
--ao-primary-focus: #d9e1ff;
--ao-primary-active: #003cab;
--ao-primary-disabled: #b5c7ff;
--ao-default-color-hover: #dddddd;
--ao-default-color-focus: #cfcfcf;
--ao-default-color-active: #ababab;
--ao-default-color-disabled: #eeeeee;
--ao-warning-hover: #fa9550;
--ao-warning-focus: #ffd9c2;
--ao-warning-active: #be5a00;
--ao-warning-disabled: #ffb98c;
--ao-primary-color-hover: #366ef4;
--ao-primary-color-focus: #d9e1ff;
--ao-primary-color-active: #003cab;
--ao-primary-color-disabled: #b5c7ff;
--ao-danger-hover: #f6685d;
--ao-danger-focus: #ffd8d2;
--ao-danger-active: #ad352f;
--ao-danger-disabled: #ffb9b0;
--ao-warning-color-hover: #fa9550;
--ao-warning-color-focus: #ffd9c2;
--ao-warning-color-active: #be5a00;
--ao-warning-color-disabled: #ffb98c;
--ao-success-hover: #56c08d;
--ao-success-focus: #c6f3d7;
--ao-success-active: #008858;
--ao-success-disabled: #92dab2;
--ao-danger-color-hover: #f6685d;
--ao-danger-color-focus: #ffd8d2;
--ao-danger-color-active: #ad352f;
--ao-danger-color-disabled: #ffb9b0;
--ao-text-primary: rgba(0, 0, 0, 90%); /* 主要文字 */
--ao-text-secondary: rgba(0, 0, 0, 60%); /* 次要文字 / 辅助信息 */
--ao-text-assist: rgba(0, 0, 0, 50%); /* 输入框内部辅助元素(icon/count) */
--ao-text-placeholder: rgba(0, 0, 0, 40%); /* 占位符 / 说明文字 */
--ao-text-disabled: rgba(0, 0, 0, 26%); /* 禁用文字 */
--ao-text-anti: #fff; /* 反色文字(深色背景上) */
--ao-text-brand: #0052d9; /* 品牌色文字 / 主操作色 */
--ao-text-link: #003cab; /* 链接文字 */
--ao-text-watermark: rgba(0, 0, 0, 10%); /* 水印 / 背景文字 */
--ao-success-color-hover: #56c08d;
--ao-success-color-focus: #c6f3d7;
--ao-success-color-active: #008858;
--ao-success-color-disabled: #92dab2;
--ao-stroke: #e8e8e8; // 分割线
--ao-border: #ddd; // 边框
--ao-text-color-base: rgba(0, 0, 0, 90%); /* 主要文字 */
--ao-text-color-secondary: rgba(0, 0, 0, 60%); /* 次要文字 / 辅助信息 */
--ao-text-color-assist: rgba(0, 0, 0, 50%); /* 输入框内部辅助元素(icon/count) */
--ao-text-color-placeholder: rgba(0, 0, 0, 40%); /* 占位符 / 说明文字 */
--ao-text-color-disabled: rgba(0, 0, 0, 26%); /* 禁用文字 */
--ao-text-color-anti: #fff; /* 反色文字(深色背景上) */
--ao-text-color-link: #003cab; /* 链接文字 */
--ao-text-color-watermark: rgba(0, 0, 0, 10%); /* 水印 / 背景文字 */
--ao-stroke-color: #e8e8e8; // 分割线
--ao-border-color: #ddd; // 边框
--ao-bg-color-control: #fff; // 特殊组件背景色,目前只用于 button、input 组件多主题场景,浅色主题下固定为白色,深色主题下为 transparent 适配背景颜色
// 滚动条颜色
--ao-scrollbar-color: rgba(0, 0, 0, 10%);
// 滚动条悬浮颜色( hover )
--ao-scrollbar-hover-color: rgba(0, 0, 0, 30%);
// 滚动条轨道颜色,不能是带透明度,否则纵向滚动时,横向滚动条会穿透
--ao-scroll-track-color: #fff;
// 容器颜色,使用的组件:popup
--ao-bg-color-container: #fff;
--ao-bg-color-container-hover: #f3f3f3;
--ao-bg-color-container-active: #e8e8e8;
// shadow阴影
// 基础/下层 投影 hover 使用的组件包括:表格 /
--ao-shadow-surface: 0 1px 10px rgba(0, 0, 0, 5%), 0 4px 5px rgba(0, 0, 0, 8%), 0 2px 4px -1px rgba(0, 0, 0, 12%);
// 中层投影 下拉 使用的组件包括:下拉菜单 / 气泡确认框 / 选择器 /
--ao-shadow-popup:
0 3px 14px 2px rgba(0, 0, 0, 5%), 0 8px 10px 1px rgba(0, 0, 0, 6%), 0 5px 5px -3px rgba(0, 0, 0, 10%);
// 上层投影(警示/弹窗)使用的组件包括:全局提示 / 消息通知
--ao-shadow-overlay:
0 6px 30px 5px rgba(0, 0, 0, 5%), 0 16px 24px 2px rgba(0, 0, 0, 4%), 0 8px 10px -5px rgba(0, 0, 0, 8%);
}
@@ -1,7 +1,6 @@
<template>
<!-- 状态按钮 (solid) -->
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal">
<div style="display: flex; gap: 8px;">
<AButton>
Normal
</AButton>
<AButton status="primary">
@@ -18,8 +17,8 @@
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" type="outline">
<div style="display: flex; gap: 8px;">
<AButton type="outline">
Normal
</AButton>
<AButton status="primary" type="outline">
@@ -36,8 +35,8 @@
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" type="dashed">
<div style="display: flex; gap: 8px;">
<AButton type="dashed">
Normal
</AButton>
<AButton status="primary" type="dashed">
@@ -54,8 +53,8 @@
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" type="text">
<div style="display: flex; gap: 8px;">
<AButton type="text">
Normal
</AButton>
<AButton status="primary" type="text">
@@ -72,8 +71,8 @@
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" disabled>
<div style="display: flex; gap: 8px;">
<AButton disabled>
禁用
</AButton>
<AButton status="primary" disabled>
@@ -90,8 +89,8 @@
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" loading>
<div style="display: flex; gap: 8px;">
<AButton loading>
loading
</AButton>
<AButton status="primary" loading>
@@ -107,7 +106,7 @@
loading
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<div style="display: flex; gap: 8px;">
<AButton status="primary" size="small">
small
</AButton>
@@ -17,6 +17,7 @@ $btn-prefix: #{$prefix}-btn;
transition: all 0.2s ease;
font-weight: 500;
border: 1px solid transparent;
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
&-small {
height: 24px;
@@ -64,47 +65,47 @@ $btn-prefix: #{$prefix}-btn;
}
&-solid {
&.#{$btn-prefix}-status-normal {
background: $bg-color-component;
color: $text-color-primary;
&.#{$btn-prefix}-status-default {
background: $default-color;
color: $text-color-base;
&:hover:enabled {
background: $bg-color-component-hover;
background: $default-color-hover;
}
&:active:enabled {
background: $bg-color-component-active;
background: $default-color-active;
}
}
&.#{$btn-prefix}-status-primary {
background: $primary;
color: $text-anti;
background: $primary-color;
color: $text-color-anti;
&:hover:enabled {
background: $primary-hover;
background: $primary-color-hover;
}
&:active:enabled {
background: $primary-active;
background: $primary-color-active;
}
}
&.#{$btn-prefix}-status-danger {
background: $danger;
color: $text-anti;
background: $danger-color;
color: $text-color-anti;
&:hover:enabled {
background: $danger-hover;
background: $danger-color-hover;
}
&:active:enabled {
background: $danger-active;
background: $danger-color-active;
}
}
&.#{$btn-prefix}-status-warning {
background: $danger;
color: $text-anti;
background: $warning-color;
color: $text-color-anti;
&:hover:enabled {
background: $danger-hover;
background: $warning-color-hover;
}
&:active:enabled {
background: $danger-active;
background: $warning-color-active;
}
}
&.#{$btn-prefix}-status-success {
@@ -118,4 +119,208 @@ $btn-prefix: #{$prefix}-btn;
}
}
}
&-outline {
&.#{$btn-prefix}-status-default {
background: $bg-color-control;
color: $text-color-base;
border-color: $border-color;
&:hover:enabled {
color: $primary-color-hover;
border-color: $primary-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-primary {
background: $bg-color-control;
color: $primary-color;
border-color: $primary-color;
&:hover:enabled {
color: $primary-color-hover;
border-color: $primary-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-danger {
background: $bg-color-control;
color: $danger-color;
border-color: $danger-color;
&:hover:enabled {
color: $danger-color-hover;
border-color: $danger-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-warning {
background: $bg-color-control;
color: $warning-color;
border-color: $warning-color;
&:hover:enabled {
color: $warning-color-hover;
border-color: $warning-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-success {
background: $bg-color-control;
color: $success-color;
border-color: $success-color;
&:hover:enabled {
color: $success-color-hover;
border-color: $success-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
}
&-dashed {
&.#{$btn-prefix}-status-default {
background: $bg-color-control;
color: $text-color-base;
border-color: $border-color;
border-style: dashed;
&:hover:enabled {
color: $primary-color-hover;
border-color: $primary-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-primary {
background: $bg-color-control;
color: $primary-color;
border-color: $primary-color;
border-style: dashed;
&:hover:enabled {
color: $primary-color-hover;
border-color: $primary-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-danger {
background: $bg-color-control;
color: $danger-color;
border-color: $danger-color;
border-style: dashed;
&:hover:enabled {
color: $danger-color-hover;
border-color: $danger-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-warning {
background: $bg-color-control;
color: $warning-color;
border-color: $warning-color;
border-style: dashed;
&:hover:enabled {
color: $warning-color-hover;
border-color: $warning-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
&.#{$btn-prefix}-status-success {
background: $bg-color-control;
color: $success-color;
border-color: $success-color;
border-style: dashed;
&:hover:enabled {
color: $success-color-hover;
border-color: $success-color-hover;
}
&:active:enabled {
background: $default-color-hover;
}
}
}
&-text {
&.#{$btn-prefix}-status-default {
color: $text-color-base;
background-color: transparent;
border-color: transparent;
&:hover:enabled {
color: $text-color-base;
background-color: $default-color-hover;
}
&:active:enabled {
background-color: $default-color-active;
}
}
&.#{$btn-prefix}-status-primary {
color: $primary-color;
background-color: transparent;
border-color: transparent;
&:hover:enabled {
color: $primary-color-hover;
background-color: $default-color-hover;
}
&:active:enabled {
background-color: $default-color-active;
}
}
&.#{$btn-prefix}-status-danger {
color: $danger-color;
background-color: transparent;
border-color: transparent;
&:hover:enabled {
color: $danger-color-hover;
background-color: $default-color-hover;
}
&:active:enabled {
background-color: $default-color-active;
}
}
&.#{$btn-prefix}-status-warning {
color: $warning-color;
background-color: transparent;
border-color: transparent;
&:hover:enabled {
color: $warning-color-hover;
background-color: $default-color-hover;
}
&:active:enabled {
background-color: $default-color-active;
}
}
&.#{$btn-prefix}-status-success {
color: $success-color;
background-color: transparent;
border-color: transparent;
&:hover:enabled {
color: $success-color-hover;
background-color: $default-color-hover;
}
&:active:enabled {
background-color: $default-color-active;
}
}
}
}
@@ -11,8 +11,8 @@ export default defineComponent({
default: 'solid',
},
status: {
type: String as () => 'primary' | 'danger' | 'warning' | 'success' | 'normal',
default: 'normal',
type: String as () => 'primary' | 'danger' | 'warning' | 'success' | 'default',
default: 'default',
},
disabled: { type: Boolean, default: false },
loading: { type: Boolean, default: false },
@@ -3,5 +3,6 @@ export { default as Button } from './button'
export { default as Group } from './group'
export { default as Icon } from './icon'
export { default as Input } from './input'
export { default as Popup } from './popup'
export { default as Spin } from './spin'
export { default as Textarea } from './textarea'
@@ -0,0 +1,4 @@
@use 'sass:color';
@use '../_styles/_variables.scss' as *;
$btn-prefix: #{$prefix}-btn;
Whitespace-only changes.
@@ -3,36 +3,66 @@
$group-prefix: #{$prefix}-group;
.#{$group-prefix}-size {
&-small {
height: $size-height-small;
font-size: $size-font-small;
}
&-medium {
height: $size-height-medium;
font-size: $size-font-medium;
}
&-large {
height: $size-height-large;
font-size: $size-font-large;
}
}
.#{$group-prefix}-wrapper {
display: flex;
width: 100%;
border-radius: $border-radius;
overflow: hidden;
position: relative;
.#{$group-prefix}-prepend,
.#{$group-prefix}-append {
background-color: $default-color;
color: $text-color-base;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid $border-color;
}
> * {
flex: 1;
margin: 0;
border-radius: 0;
position: relative;
border-radius: 0;
z-index: 0;
border: $border-outline-color;
border-left: none;
box-shadow: none;
&:hover {
border-left: $brand-color;
z-index: 1;
box-shadow: none;
// 抵消左边 border,避免叠加
& + * {
margin-left: -1px;
}
// hover / focus / active 高亮
&:hover,
&:focus-within,
&:active {
border-left: $brand-color;
z-index: 1;
box-shadow: none;
// 高亮边框
outline: 1px solid $primary-color;
outline-offset: -1px;
}
}
// 首尾圆角
> *:first-child {
border-left: $border-outline-color;
border-top-left-radius: $border-radius;
border-bottom-left-radius: $border-radius;
}
@@ -1,16 +1,30 @@
import type { PropType } from 'vue'
import { defineComponent } from 'vue'
import { getPrefixCls } from '../_utils/getPrefixCls'
export default defineComponent({
name: 'Group',
props: {},
props: {
prepend: { type: String, default: '' },
append: { type: String, default: '' },
size: { type: String as () => 'small' | 'medium' | 'large', default: 'medium' },
},
setup(props, { slots }) {
const prefixCls = getPrefixCls('group')
const renderNode = (slotName: 'prepend' | 'append', propValue: string) => {
// slot 优先
if (slots[slotName])
return slots[slotName]!()
if (propValue)
return <div class={`${prefixCls}-${slotName}`}>{propValue}</div>
return null
}
return () => (
<div class={[`${prefixCls}-wrapper`]}>
<div class={[`${prefixCls}-wrapper`, `${prefixCls}-size-${props.size}`]}>
{renderNode('prepend', props.prepend)}
{slots.default?.()}
{renderNode('append', props.append)}
</div>
)
},
@@ -5,7 +5,7 @@ import { getPrefixCls } from '../_utils/getPrefixCls'
import './index.scss'
export default defineComponent({
name: 'AIcon',
name: 'Icon',
props: {
icon: { type: String as PropType<string>, required: true },
size: { type: Number, default: 16 },
@@ -4,10 +4,5 @@
@use './input/index.scss' as *;
@use './textarea/index.scss' as *;
@use './group/index.scss' as *;
@use "./popup/tooltip.scss" as *;
input,
button,
select,
textarea {
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
@@ -5,18 +5,18 @@ $input-prefix: #{$prefix}-input;
.#{$input-prefix}-size {
&-small {
height: 24px;
font-size: 12px;
height: $size-height-small;
font-size: $size-font-small;
}
&-medium {
height: 28px;
font-size: 13px;
height: $size-height-medium;
font-size: $size-font-medium;
}
&-large {
height: 32px;
font-size: 14px;
height: $size-height-large;
font-size: $size-font-large;
}
}
@@ -24,21 +24,22 @@ $input-prefix: #{$prefix}-input;
display: flex;
align-items: center;
width: 100%;
border: 1px solid $border-outline-color;
border: 1px solid $border-color;
border-radius: $border-radius;
box-sizing: border-box;
padding: 0 8px;
background: $bg-color-control;
transition:
border cubic-bezier(0.38, 0, 0.24, 1) 0.2s,
box-shadow cubic-bezier(0.38, 0, 0.24, 1) 0.2s,
background-color cubic-bezier(0.38, 0, 0.24, 1) 0.2s;
.#{$input-prefix}-inner {
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
width: 100%;
border: none;
outline: none;
background: transparent;
box-sizing: border-box;
padding: 0;
font-size: inherit;
@@ -46,19 +47,20 @@ $input-prefix: #{$prefix}-input;
display: flex;
align-items: center;
height: 100%;
color: $text-color-base;
background-color: transparent;
&::placeholder {
color: $text-color-placeholder;
}
}
&:hover {
border-color: $brand-color;
border-color: $primary-color;
}
&:focus-within {
border-color: $brand-color;
box-shadow: 0 0 0 2px $brand-color-focus;
border-color: $primary-color;
box-shadow: 0 0 0 2px $primary-color-focus;
}
.#{$input-prefix}-align {
@@ -90,7 +92,7 @@ $input-prefix: #{$prefix}-input;
}
&.#{$input-prefix}-disabled {
background-color: $bg-color-component-disabled;
background-color: $default-color-disabled;
cursor: not-allowed;
.#{$input-prefix}-input {
@@ -106,13 +108,13 @@ $input-prefix: #{$prefix}-input;
&:hover,
&:focus-within {
border: $border-outline-color;
border: $border-color;
box-shadow: none;
}
}
&.#{$input-prefix}-readonly {
background-color: $bg-color-component-readonly;
// background-color: $bg-color-component-readonly;
}
.#{$input-prefix}-icon {
@@ -120,7 +122,7 @@ $input-prefix: #{$prefix}-input;
transition:
color 0.2s,
background-color 0.2s;
color: $text-color-secondary;
color: $text-color-assist;
display: inline-flex;
align-items: center;
@@ -130,7 +132,7 @@ $input-prefix: #{$prefix}-input;
border-radius: 50%;
&:hover {
background-color: $bg-color-component-hover;
background-color: $default-color-hover;
}
}
@@ -138,6 +140,6 @@ $input-prefix: #{$prefix}-input;
flex-shrink: 0;
margin-left: 4px;
white-space: nowrap;
color: $text-color-secondary;
color: $text-color-assist;
}
}
@@ -25,7 +25,7 @@ export default defineComponent({
maxlength: Number,
password: Boolean,
},
emits: ['update:modelValue'],
emits: ['update:modelValue', 'focus', 'blur'],
setup(props, { slots, emit }) {
const prefixCls = getPrefixCls('input')
const inputValue = ref(props.modelValue || '')
@@ -85,6 +85,8 @@ export default defineComponent({
disabled={props.disabled}
readonly={props.readonly}
onInput={(e: Event) => updateValue((e.target as HTMLInputElement).value)}
onFocus={e => emit('focus', e)}
onBlur={e => emit('blur', e)}
/>
{props.clearable && inputValue.value && !props.disabled && !props.readonly && (
@@ -0,0 +1,140 @@
import type { PropType } from 'vue'
import { cloneVNode, defineComponent, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
interface Position {
top: number
left: number
}
export default defineComponent({
name: 'Tooltip',
props: {
content: { type: String, required: true },
placement: { type: String as PropType<'top' | 'bottom' | 'left' | 'right'>, default: 'top' },
trigger: { type: String as PropType<'hover' | 'click'>, default: 'hover' },
offset: { type: Number, default: 6 },
},
setup(props, { slots }) {
const visible = ref(false)
const targetEl = ref<HTMLElement | null>(null)
const tooltipEl = ref<HTMLDivElement | null>(null)
const createTooltip = () => {
const el = document.createElement('div')
el.className = `tooltip tooltip-${props.placement}` // 初始隐藏,不加 visible
el.innerHTML = `${props.content}<div class="tooltip-arrow"></div>`
document.body.appendChild(el)
tooltipEl.value = el
}
const updatePosition = () => {
const target = targetEl.value
const tooltip = tooltipEl.value
if (!target || !tooltip)
return
let dom: HTMLElement | null = null
if (target instanceof HTMLElement)
dom = target
else if ((target as any)?.$el instanceof HTMLElement)
dom = (target as any).$el
if (!dom)
return
const rect = dom.getBoundingClientRect()
const tooltipRect = tooltip.getBoundingClientRect()
const scrollX = window.scrollX || window.pageXOffset
const scrollY = window.scrollY || window.pageYOffset
let top = 0
let left = 0
const offset = props.offset
switch (props.placement) {
case 'top':
top = rect.top + scrollY - tooltipRect.height - offset
left = rect.left + scrollX + rect.width / 2 - tooltipRect.width / 2
break
case 'bottom':
top = rect.bottom + scrollY + offset
left = rect.left + scrollX + rect.width / 2 - tooltipRect.width / 2
break
case 'left':
top = rect.top + scrollY + rect.height / 2 - tooltipRect.height / 2
left = rect.left + scrollX - tooltipRect.width - offset
break
case 'right':
top = rect.top + scrollY + rect.height / 2 - tooltipRect.height / 2
left = rect.right + scrollX + offset
break
}
tooltip.style.top = `${top}px`
tooltip.style.left = `${left}px`
}
const show = () => {
const tooltip = tooltipEl.value
if (!tooltip || !targetEl.value)
return
visible.value = true
nextTick(() => {
updatePosition()
tooltip.classList.add('visible') // CSS 控制动画
})
}
const hide = () => {
const tooltip = tooltipEl.value
if (!tooltip)
return
visible.value = false
tooltip.classList.remove('visible')
}
const toggle = () => {
visible.value ? hide() : show()
}
onMounted(() => {
createTooltip()
window.addEventListener('scroll', () => {
if (visible.value)
updatePosition()
})
window.addEventListener('resize', () => {
if (visible.value)
updatePosition()
})
})
onBeforeUnmount(() => {
window.removeEventListener('scroll', () => {
if (visible.value)
updatePosition()
})
window.removeEventListener('resize', () => {
if (visible.value)
updatePosition()
})
if (tooltipEl.value && tooltipEl.value.parentNode) {
tooltipEl.value.parentNode.removeChild(tooltipEl.value)
}
})
return () => {
const child = slots.default?.()[0]
if (!child)
return null
return cloneVNode(child, {
ref: targetEl,
onMouseenter: props.trigger === 'hover' ? show : undefined,
onMouseleave: props.trigger === 'hover' ? hide : undefined,
onClick: props.trigger === 'click' ? toggle : undefined,
})
}
},
})
@@ -0,0 +1,56 @@
@use '../_styles/_variables.scss' as *;
.tooltip {
position: absolute;
z-index: 9999;
padding: 6px 10px;
background: #fff;
border-radius: 4px;
color: #333;
font-size: 12px;
white-space: nowrap;
pointer-events: none;
/* ---------------- 动画 ---------------- */
opacity: 0;
transition: opacity 0.2s ease-in-out;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
&.visible {
opacity: 1;
pointer-events: auto;
}
.tooltip-arrow {
position: absolute;
width: 8px;
height: 8px;
background: #fff;
transform: rotate(45deg);
z-index: 0;
}
&.tooltip-top .tooltip-arrow {
bottom: -4px;
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
&.tooltip-bottom .tooltip-arrow {
top: -4px;
left: 50%;
transform: translateX(-50%) rotate(45deg);
}
&.tooltip-left .tooltip-arrow {
right: -4px;
top: 50%;
transform: translateY(-50%) rotate(45deg);
}
&.tooltip-right .tooltip-arrow {
left: -4px;
top: 50%;
transform: translateY(-50%) rotate(45deg);
}
}
@@ -20,13 +20,13 @@ $spin-prefix: #{$prefix}-spin;
flex-direction: column;
justify-content: center;
align-items: center;
color: $brand-color;
color: $text-color-base;
}
&-tip {
margin-top: 4px;
font-size: 12px;
color: #000;
color: $text-color-base;
}
&.rounded {
@@ -12,6 +12,8 @@ $textarea-prefix: #{$prefix}-textarea;
width: 100%;
.#{$textarea-prefix}-inner {
font-family: 'PingFang SC', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
height: 100%;
width: 100%;
display: flex;
padding: 5px 8px;
@@ -23,20 +25,21 @@ $textarea-prefix: #{$prefix}-textarea;
transition:
all cubic-bezier(0.38, 0, 0.24, 1) 0.2s,
height 0s;
border: 1px solid $border-outline-color;
border: 1px solid $border-color;
border-radius: $border-radius;
background-color: $bg-color-control;
color: $text-color-base;
&::placeholder {
color: $text-color-placeholder;
}
&:hover {
border-color: $brand-color;
border-color: $primary-color;
}
&:focus-within {
border-color: $brand-color;
box-shadow: 0 0 0 2px $brand-color-focus;
border-color: $primary-color;
box-shadow: 0 0 0 2px $primary-color-focus;
}
&::-webkit-scrollbar {
@@ -44,33 +47,33 @@ $textarea-prefix: #{$prefix}-textarea;
}
&::-webkit-scrollbar-track {
background: transparent;
background: $scroll-track-color;
}
&::-webkit-scrollbar-thumb {
background-color: #e5e5e5;
background-color: $scrollbar-color;
border-radius: 0px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: #b2b2b2;
background-color: $scrollbar-hover-color;
}
}
.#{$textarea-prefix}-disabled {
background-color: $bg-color-component-disabled;
background-color: $default-color-disabled;
cursor: not-allowed;
color: $text-color-disabled;
&:hover,
&:focus-within {
border: $border-outline-color;
border: $border-color;
box-shadow: none;
}
}
.#{$textarea-prefix}-readonly {
background-color: $bg-color-component-readonly;
// background-color: $bg-color-component-readonly;
}
.#{$textarea-prefix}-clear {
@@ -88,13 +91,13 @@ $textarea-prefix: #{$prefix}-textarea;
align-items: center;
justify-content: center;
color: $text-color-secondary;
color: $text-color-assist;
transition:
color 0.2s,
background-color 0.2s;
&:hover {
background-color: $bg-color-component-hover;
background-color: $default-color-hover;
}
}
@@ -103,6 +106,6 @@ $textarea-prefix: #{$prefix}-textarea;
right: 8px;
bottom: 0px;
font-size: 12px;
color: $text-color-secondary;
color: $text-color-assist;
}
}
+8 -124
View File
@@ -1,15 +1,18 @@
<script setup lang="ts">
function setDark() {
document.documentElement.setAttribute('theme-mode', 'dark')
document.body.style.backgroundColor = '#242424'
}
function setLight() {
document.documentElement.setAttribute('theme-mode', 'light')
document.body.style.backgroundColor = '#ffffff'
}
</script>
<template>
<div style="height: 100vh;width: 100%;display: flex;align-items: center;flex-direction: column;justify-content: center;">
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<div style="height: 100vh;width: 100%;display: flex;align-items: center;flex-direction: column;justify-content: center;gap:16px">
<div style="display: flex; gap: 8px;">
<AButton status="primary" size="medium" @click="setDark">
黑色主题
</AButton>
@@ -18,127 +21,8 @@ function setLight() {
白色主题
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal">
Normal
</AButton>
<AButton status="primary">
主按钮
</AButton>
<AButton status="warning">
警告
</AButton>
<AButton status="danger">
危险
</AButton>
<AButton status="success">
成功
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" type="outline">
Normal
</AButton>
<AButton status="primary" type="outline">
主按钮
</AButton>
<AButton status="warning" type="outline">
警告
</AButton>
<AButton status="danger" type="outline">
危险
</AButton>
<AButton status="success" type="outline">
成功
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" type="dashed">
Normal
</AButton>
<AButton status="primary" type="dashed">
主按钮
</AButton>
<AButton status="warning" type="dashed">
警告
</AButton>
<AButton status="danger" type="dashed">
危险
</AButton>
<AButton status="success" type="dashed">
成功
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" type="text">
Normal
</AButton>
<AButton status="primary" type="text">
主按钮
</AButton>
<AButton status="warning" type="text">
警告
</AButton>
<AButton status="danger" type="text">
危险
</AButton>
<AButton status="success" type="text">
成功
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" disabled>
禁用
</AButton>
<AButton status="primary" disabled>
禁用
</AButton>
<AButton type="outline" disabled>
禁用
</AButton>
<AButton type="dashed" disabled>
禁用
</AButton>
<AButton type="text" disabled>
禁用
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="normal" loading>
loading
</AButton>
<AButton status="primary" loading>
loading
</AButton>
<AButton type="outline" loading>
loading
</AButton>
<AButton type="dashed" loading>
loading
</AButton>
<AButton type="text" loading>
loading
</AButton>
</div>
<div style="display: flex; gap: 8px; margin-bottom: 16px;">
<AButton status="primary" size="small">
small
</AButton>
<AButton status="primary" size="medium">
medium
</AButton>
<AButton status="primary" size="large">
large
</AButton>
</div>
<AInput style="width: 200px;" clearable show-count />
<ATextarea style="width: 200px;" clearable show-count />
<APopup content="2222222222222222222222" trigger="click">
<AButton>测试</AButton>
</APopup>
</div>
</template>
+2
View File
@@ -9,6 +9,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
A: typeof import('@ao/ao-design')['default']
AB: typeof import('@ao/ao-design')['B']
AButton: typeof import('@ao/ao-design')['Button']
AConfigProvider: typeof import('@ao/ao-design')['ConfigProvider']
AGroup: typeof import('@ao/ao-design')['Group']
@@ -16,6 +17,7 @@ declare module 'vue' {
AInput: typeof import('@ao/ao-design')['Input']
ALoading: typeof import('@ao/ao-design')['Loading']
ALoding: typeof import('@ao/ao-design')['Loding']
APopup: typeof import('@ao/ao-design')['Popup']
ASpin: typeof import('@ao/ao-design')['Spin']
AT: typeof import('@ao/ao-design')['T']
ATex: typeof import('@ao/ao-design')['Tex']
@@ -99,6 +99,8 @@ public class EmailServiceImpl implements EmailService {
Long folderId = emailSummaryPageDTO.getFolderId();
EmailFolder emailFolder = emailFolderMapper.selectById(folderId);
String category = emailFolder.getCategory();
boolean showRecipient = EmailFolderTypeEnum.DRAFT.name().equals(category)
|| EmailFolderTypeEnum.SENT.name().equals(category);
@@ -0,0 +1,12 @@
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import timezone from 'dayjs/plugin/timezone'
export function getBuildTime() {
dayjs.extend(utc)
dayjs.extend(timezone)
const buildTime = dayjs.tz(Date.now(), 'Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss')
return buildTime
}
@@ -0,0 +1 @@
export * from './time'
@@ -0,0 +1,34 @@
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'
import { ArcoResolver } from 'unplugin-vue-components/resolvers'
import type { PluginOption } from 'vite'
export function setupAutoImport(viteEnv: Env.ImportMeta) {
// 从环境变量中提取图标相关的前缀
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv
// 从本地图标前缀中提取图标集合名称
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '')
const plugins: PluginOption[] = [
Components({
// 自动导入的组件类型声明文件
dts: 'src/types/auto-import.d.ts',
types: [
{
from: 'vue-router',
names: ['RouterLink', 'RouterView'],
},
],
// 配置图标解析器
resolvers: [
IconsResolver({
customCollections: [collectionName], // 本地图标集合
componentPrefix: VITE_ICON_PREFIX, // 图标组件的前缀
}),
ArcoResolver(),
],
}),
]
return plugins
}
@@ -0,0 +1,13 @@
import type { Plugin } from 'vite'
export function setupHtmlPlugin(buildTime: string) {
const plugin: Plugin = {
name: 'html-plugin',
apply: 'build',
transformIndexHtml(html) {
return html.replace('<head>', `<head>\n <meta name="buildTime" content="${buildTime}">`)
},
}
return plugin
}
@@ -0,0 +1,22 @@
import type { PluginOption } from 'vite'
import vue from '@vitejs/plugin-vue'
import VueDevtools from 'vite-plugin-vue-devtools'
import progress from 'vite-plugin-progress'
import { setupUnocss } from './unocss'
import { setupHtmlPlugin } from './html'
import { setupUnPluginIcon } from './unplugin-icon'
import { setupAutoImport } from './auto-import'
export function setupVitePlugins(viteEnv: Env.ImportMeta, buildTime: string) {
const plugins: PluginOption = [
vue(),
VueDevtools(),
progress(),
setupUnocss(viteEnv),
setupHtmlPlugin(buildTime),
setupAutoImport(viteEnv),
...setupUnPluginIcon(viteEnv),
]
return plugins
}
@@ -0,0 +1,32 @@
import process from 'node:process'
import path from 'node:path'
import unocss from '@unocss/vite'
import presetIcons from '@unocss/preset-icons'
import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'
export function setupUnocss(viteEnv: Env.ImportMeta) {
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon')
/** The name of the local icon collection */
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '')
return unocss({
presets: [
presetIcons({
prefix: `${VITE_ICON_PREFIX}-`,
scale: 1,
extraProperties: {
display: 'inline-block',
},
collections: {
[collectionName]: FileSystemIconLoader(localIconPath, (svg) =>
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" '),
),
},
warn: true,
}),
],
})
}
@@ -0,0 +1,34 @@
import path from 'node:path'
import process from 'node:process'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import type { PluginOption } from 'vite'
import Icons from 'unplugin-icons/vite'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export function setupUnPluginIcon(viteEnv: Env.ImportMeta) {
const { VITE_ICON_PREFIX, VITE_ICON_LOCAL_PREFIX } = viteEnv
const localIconPath = path.join(process.cwd(), 'src/assets/svg-icon')
/** The name of the local icon collection */
const collectionName = VITE_ICON_LOCAL_PREFIX.replace(`${VITE_ICON_PREFIX}-`, '')
const plugins: PluginOption[] = [
createSvgIconsPlugin({
iconDirs: [localIconPath],
symbolId: `${VITE_ICON_LOCAL_PREFIX}-[dir]-[name]`,
inject: 'body-last',
customDomId: '__SVG_ICON_LOCAL__',
}),
Icons({
compiler: 'vue3',
customCollections: {
[collectionName]: FileSystemIconLoader(localIconPath, (svg) =>
svg.replace(/^<svg\s/, '<svg width="1em" height="1em" '),
),
},
scale: 1,
defaultClass: 'inline-block',
}),
]
return plugins
}