@cghbcf/xp-ui

Vue3 component library - A modern UI component library for Vue 3
662
Install
npm install @cghbcf/xp-ui
Latest Version:1.3.0
Vue:3
License:MIT
Last Updated:Sep 11, 2026
Links: npm
Maintainer: cghbcf

@cghbcf/xp-ui

Vue3 组件库 - 基于 Vue3 + Vite 构建的现代化 UI 组件库

特性

  • ⚡ 基于 Vue3 和 Vite,性能卓越
  • 📦 开箱即用,无需繁琐配置
  • 🎨 现代化设计风格,支持主题定制(浅色 / 暗黑双主题)
  • 🎛️ 可视化主题定制面板 —— 实时修改颜色、一键导出 JSON/CSS
  • 🌈 主色自动派生(-light / -dark / -bg / -border),无需手动配置
  • 🔧 丰富的组件库,覆盖常用场景(Button / Input / Select / Dialog / Card / Icon / Tabs / Table / Pagination / Empty / Toast / ContextMenu / Menu 等 27+ 组件)
  • 💎 完整的 CSS 变量(Design Tokens)系统,便于深度定制
  • 💾 主题配置自动持久化到 localStorage,刷新页面不丢失

快速开始

安装

# npm
npm install @cghbcf/xp-ui --save

# yarn
yarn add @cghbcf/xp-ui

# pnpm
pnpm install @cghbcf/xp-ui

完整引入

import { createApp } from 'vue'
import App from './App.vue'
import XpUi from '@cghbcf/xp-ui'
import '@cghbcf/xp-ui/dist/style.css'

const app = createApp(App)
app.use(XpUi)
app.mount('#app')

按需引入

import { createApp } from 'vue'
import App from './App.vue'
import { XpButton, XpInput, XpDialog, XpCard, XpTabs } from '@cghbcf/xp-ui'
import '@cghbcf/xp-ui/dist/style.css'

const app = createApp(App)
app.component('XpButton', XpButton)
app.component('XpInput', XpInput)
app.mount('#app')

也可以直接使用主题 composable:

import { useTheme, applyThemeConfig, setTheme, toggleTheme } from '@cghbcf/xp-ui'

const { theme, themeConfig, initTheme, applyThemeConfig, buildCssString } = useTheme()
initTheme()

组件

Icon 图标

基于内联 SVG 的图标组件,支持预设/自定义尺寸、颜色、旋转与加载动画。

图标文件统一存放在 src/components/icon/icons/ 目录下,组件在构建时通过 import.meta.glob 自动扫描该目录,新增图标只需放入 .svg 文件,即可用同名 name 直接引用(例如 jiantou.svg 对应 name="jiantou")。

图标内部硬编码的 fill / stroke 颜色(除 none 外)会被自动替换为 currentColor,因此 color 属性始终生效。未指定 color 时图标默认继承当前文字颜色,便于通过父元素着色(如按钮 hover 高亮)。 当 name 不存在时,会展示占位符(?)便于排查。

内置图标

下表为当前内置的 18 个图标(不含占位符):

name 视觉 name 视觉
back 返回 ← forward 前进 →
up 上一级 ↑ arrow-right 右箭头 →▸
refresh 刷新 ⟳ chevron-up 上箭头 ∧
chevron-down 下箭头 ∨ close 关闭 ✕
folder 文件夹 📁 folder-add 新建文件夹 📁+
list 列表视图 ☰ grid 网格视图 ▦
settings 设置 ⚙ star 星标 ☆
star-fill 星标实心 ★ upload 上传 ⇧
home 首页 ⌂ jiantou 箭头 ◀

图标总览见演示站 Icon 图标 页,点击图标可复制 XpIcon 代码。新增图标只需放入 icons/ 目录即可自动出现。

基础用法
<template>
  <!-- 内置图标 -->
  <XpIcon name="jiantou" />

  <!-- 方向:通过 rotate 或内联样式旋转 -->
  <XpIcon name="jiantou" :rotate="180" />

  <!-- 预设尺寸 -->
  <XpIcon name="jiantou" size="small" />
  <XpIcon name="jiantou" size="medium" />
  <XpIcon name="jiantou" size="large" />

  <!-- 自定义尺寸(数字按 px 处理) -->
  <XpIcon name="jiantou" :size="32" />

  <!-- 自定义颜色 -->
  <XpIcon name="jiantou" color="#67c23a" />

  <!-- 加载动画 -->
  <XpIcon name="jiantou" spin color="var(--xp-color-primary)" />

  <!-- name 不存在时显示占位符 -->
  <XpIcon name="not-exist" />
</template>
Props
属性 类型 默认值 说明
name string '' 图标名称,对应 icons/ 目录下 .svg 文件名(不含后缀)
size string / number medium 尺寸:预设值 small(14) / medium(18) / large(24),或自定义数字(px) / 带单位字符串(如 48px)
color string '' 图标颜色,值为任意合法 CSS 颜色
spin boolean false 是否持续旋转(加载动画)
rotate number 0 旋转角度(单位:度)
Slots
插槽名 说明
default 自定义图标内容(传入则优先渲染插槽内容,而非 SVG)

Button 按钮

按钮用于触发一个操作,如提交表单、打开对话框等。

基础用法
<template>
  <XpButton>Default</XpButton>
  <XpButton type="primary">Primary</XpButton>
  <XpButton type="success">Success</XpButton>
  <XpButton type="warning">Warning</XpButton>
  <XpButton type="danger">Danger</XpButton>
  <XpButton type="info">Info</XpButton>

  <XpButton type="primary" plain>Plain Primary</XpButton>
  <XpButton type="primary" text>Text Primary</XpButton>

  <XpButton size="small" type="primary">Small</XpButton>
  <XpButton size="medium" type="primary">Medium</XpButton>
  <XpButton size="large" type="primary">Large</XpButton>

  <XpButton type="primary" disabled>Disabled</XpButton>
  <XpButton type="primary" loading @click="handleClick">Loading</XpButton>
</template>

<script setup>
const handleClick = () => {}
</script>
Props
属性 类型 默认值 说明
type string default 按钮类型,可选值:primary / default / success / warning / danger / info / ghost
size string medium 按钮尺寸,可选值:small / medium / large
plain boolean false 是否朴素按钮
text boolean false 是否文字按钮
disabled boolean false 是否禁用按钮
loading boolean false 是否显示加载状态
Events
事件名 说明 回调参数
click 点击按钮时触发 event

Input 输入框

用于收集用户输入信息。

基础用法
<template>
  <XpInput v-model="inputValue" placeholder="请输入内容" showClear />

  <XpInput placeholder="Small" size="small" />
  <XpInput placeholder="Medium" size="medium" />
  <XpInput placeholder="Large" size="large" />

  <XpInput placeholder="用户名">
    <template #prefix>👤</template>
  </XpInput>

  <XpInput placeholder="密码">
    <template #suffix>🔒</template>
  </XpInput>

  <XpInput placeholder="禁用状态" disabled />
</template>

<script setup>
import { ref } from 'vue'
const inputValue = ref('')
</script>
Props
属性 类型 默认值 说明
modelValue string / number '' 输入框的值,支持 v-model
id string '' 原生 input 的 id,配合 label[for] 使用
type string text 输入框类型,可选值:text / password / number / email / tel / url
placeholder string '' 占位符文本
disabled boolean false 是否禁用
size string medium 输入框尺寸,可选值:small / medium / large
maxlength string / number null 最大输入长度
showClear boolean false 是否显示清空按钮
Events
事件名 说明 回调参数
update:modelValue 值改变时触发 value
focus 获得焦点时触发 event
blur 失去焦点时触发 event
clear 点击清空按钮时触发 -
Slots
插槽名 说明
prefix 前缀内容
suffix 后缀内容
实例方法

通过模板 ref 可调用内部原生 input 的方法(如自动聚焦 / 全选):

<template>
  <XpInput ref="inputRef" v-model="value" placeholder="请输入" />
</template>

<script setup>
import { ref, nextTick } from 'vue'
const inputRef = ref(null)
nextTick(() => {
  inputRef.value.focus()
  inputRef.value.select()
})
</script>
方法 说明
focus 聚焦输入框
select 全选输入框内容
blur 失焦

Select 选择器

下拉选择器,使用 Teleport 渲染浮层。支持键盘操作(Enter/Space 打开、上下键切换、Esc 关闭)、清空、尺寸与禁用态。

基础用法
<template>
  <XpSelect v-model="city" :options="options" placeholder="请选择城市" @change="onChange" />
</template>

<script setup>
import { ref } from 'vue'

const city = ref('shanghai')
const options = [
  { label: '北京', value: 'beijing' },
  { label: '上海', value: 'shanghai' },
  { label: '深圳', value: 'shenzhen' }
]
const onChange = (value) => console.log(value)
</script>

options 兼容纯值数组(如 ['北京', '上海']),此时选中值即为该值本身。

Props
属性 类型 默认值 说明
modelValue string / number / boolean '' 当前选中值,支持 v-model
options array [] 选项列表:{ label, value, disabled } 或纯值
placeholder string 请选择 未选中时的占位文案
size string medium 尺寸:small / medium / large
disabled boolean false 是否禁用
clearable boolean false 是否可清空
Events
事件名 说明 回调参数
update:modelValue 选中值变化(配合 v-model 使用) (value)
change 选择某一项后触发 (value)
clear 点击清空按钮时触发 -
visible-change 浮层显隐变化 (visible: boolean)

Switch 开关

表示两种相互对立的状态间的切换。

基础用法
<template>
  <XpSwitch v-model="value" />
  <XpSwitch v-model="value" size="small" />
  <XpSwitch v-model="value" size="large" />
  <XpSwitch :model-value="true" disabled />
</template>

<script setup>
import { ref } from 'vue'
const value = ref(false)
</script>
Props
属性 类型 默认值 说明
modelValue boolean false 绑定值,支持 v-model
size string medium 尺寸:small / medium / large
disabled boolean false 是否禁用
Events
事件名 说明 回调参数
update:modelValue 值改变时触发 value
change 值改变时触发 value

Checkbox 多选框

一组备选项中进行多选。

基础用法
<template>
  <XpCheckbox v-model="value1">同意协议</XpCheckbox>
  <XpCheckbox v-model="value2">接收邮件</XpCheckbox>
  <XpCheckbox :model-value="true" disabled>已勾选(禁用)</XpCheckbox>
  <XpCheckbox :model-value="false" disabled>未勾选(禁用)</XpCheckbox>
</template>

<script setup>
import { ref } from 'vue'
const value1 = ref(true)
const value2 = ref(false)
</script>
Props
属性 类型 默认值 说明
modelValue boolean false 绑定值,支持 v-model
disabled boolean false 是否禁用
indeterminate boolean false 是否半选状态
Events
事件名 说明 回调参数
update:modelValue 值改变时触发 value
change 值改变时触发 value

Radio 单选框

在一组备选项中进行单选。

基础用法
<template>
  <XpRadio v-model="value" value="A">选项 A</XpRadio>
  <XpRadio v-model="value" value="B">选项 B</XpRadio>
  <XpRadio v-model="value" value="C">选项 C</XpRadio>
</template>

<script setup>
import { ref } from 'vue'
const value = ref('A')
</script>
Props
属性 类型 默认值 说明
modelValue string / number / boolean '' 绑定值
value string / number / boolean '' 选项的值
disabled boolean false 是否禁用
Events
事件名 说明 回调参数
update:modelValue 值改变时触发 value
change 值改变时触发 value

Tag 标签 & Badge 徽标

Tag 用于标记和分类;Badge 用于消息数量提示。

基础用法
<template>
  <XpTag>Default</XpTag>
  <XpTag type="primary">Primary</XpTag>
  <XpTag type="success">Success</XpTag>
  <XpTag type="warning">Warning</XpTag>
  <XpTag type="danger">Danger</XpTag>
  <XpTag type="info">Info</XpTag>

  <XpTag round type="primary">Round</XpTag>
  <XpTag size="small">Small</XpTag>
  <XpTag size="large">Large</XpTag>
  <XpTag closable>Closable</XpTag>

  <XpBadge value="5">
    <XpButton size="small">消息</XpButton>
  </XpBadge>
  <XpBadge value="120" type="warning">
    <XpButton size="small">通知</XpButton>
  </XpBadge>
  <XpBadge isDot type="danger">
    <XpButton size="small">新消息</XpButton>
  </XpBadge>
</template>
Tag Props
属性 类型 默认值 说明
type string default 类型:primary / default / success / warning / danger / info
size string medium 尺寸:small / medium / large
color string '' 自定义颜色(#xxx 或 rgb)
plain boolean false 是否朴素样式
round boolean false 是否圆角
closable boolean false 是否可关闭
Badge Props
属性 类型 默认值 说明
value string / number 0 显示值
max number 99 最大值,超出显示 {max}+
type string danger 类型:primary / success / warning / danger / info
isDot boolean false 是否以小圆点显示
hidden boolean false 是否隐藏徽标

Alert 提示

用于页面中展示重要的提示信息。

基础用法
<template>
  <XpAlert title="这是一条成功消息" type="success" />
  <XpAlert title="这是一条警告消息" type="warning" />
  <XpAlert title="这是一条错误消息" type="danger" />
  <XpAlert title="这是一条提示消息" type="info" />
</template>
Props
属性 类型 默认值 说明
title string '' 标题
type string info 类型:success / warning / danger / info
effect string light 样式:light / dark / plain
closable boolean true 是否可关闭
showIcon boolean true 是否显示图标
Events
事件名 说明 回调参数
close 关闭 alert 时触发 -

Avatar 头像

用图标、图片或者字符展示用户头像。

基础用法
<template>
  <XpAvatar size="small">Xp</XpAvatar>
  <XpAvatar>User</XpAvatar>
  <XpAvatar size="large">Demo</XpAvatar>
  <XpAvatar shape="square">Sq</XpAvatar>
  <XpAvatar shape="square" size="large">UI</XpAvatar>
  <XpAvatar src="https://example.com/avatar.png" alt="Avatar" />
</template>
Props
属性 类型 默认值 说明
src string '' 图片头像地址
alt string '' 替代文本
shape string circle 形状:circle / square
size string medium 尺寸:small / medium / large
icon string '' 图标
colorful boolean false 无图片时依据 alt 自动分配柔和主题色
Events
事件名 说明 回调参数
error 图片加载失败时触发 -

Progress 进度条 & Rate 评分

进度条用于展示操作进度;评分用于对事物进行评级操作。

基础用法
<template>
  <XpProgress :percentage="30" style="width:240px" />
  <XpProgress :percentage="60" status="warning" style="width:240px" />
  <XpProgress :percentage="85" status="success" style="width:240px" />
  <XpProgress :percentage="100" status="exception" style="width:240px" />

  <XpRate v-model="rate" showText />
</template>

<script setup>
import { ref } from 'vue'
const rate = ref(3)
</script>
Progress Props
属性 类型 默认值 说明
percentage number 0 百分比(0-100)
color string '' 自定义进度条颜色
showText boolean true 是否显示百分比文字
type string line 类型:line / circle
status string '' 状态:success / warning / exception
strokeWidth number 8 line 模式下进度条高度(px),紧凑场景可设小值
Rate Props
属性 类型 默认值 说明
modelValue number 0 绑定值
max number 5 最大分值
color string #f7ba2a 颜色
disabled boolean false 是否禁用
showText boolean false 是否显示文字

Tooltip 提示

常用于展示鼠标 hover 时的提示信息。

基础用法
<template>
  <XpTooltip content="顶部提示">
    <XpButton type="primary">Top</XpButton>
  </XpTooltip>
  <XpTooltip content="底部提示" placement="bottom">
    <XpButton>Bottom</XpButton>
  </XpTooltip>
  <XpTooltip content="左侧提示" placement="left">
    <XpButton type="success">Left</XpButton>
  </XpTooltip>
  <XpTooltip content="右侧提示" placement="right">
    <XpButton type="warning">Right</XpButton>
  </XpTooltip>
</template>
Props
属性 类型 默认值 说明
content string '' 显示的内容
placement string top 出现位置:top / bottom / left / right
trigger string hover 触发方式:hover / click / manual
disabled boolean false 是否禁用

Dropdown 下拉菜单

将动作或菜单折叠到下拉菜单中。

基础用法
<template>
  <XpDropdown :items="items" @select="handleSelect">
    <XpButton type="primary">下拉菜单 ▾</XpButton>
  </XpDropdown>
</template>

<script setup>
const items = [
  { label: '选项一', command: 'a' },
  { label: '选项二', command: 'b' },
  { label: '选项三(禁用)', command: 'c', disabled: true },
  { divider: true },
  { label: '选项四', command: 'd' }
]
const handleSelect = (item) => {
  console.log('选中:', item)
}
</script>
Props
属性 类型 默认值 说明
items Array [] 菜单项:{ label, command, disabled, divider }
disabled boolean false 是否禁用
Events
事件名 说明 回调参数
select 点击菜单项时触发 item
command 点击菜单项时触发(传 command) command, item
open 菜单打开时触发 -
close 菜单关闭时触发 -

Card 卡片

将信息聚合在卡片容器中展示。

基础用法
<template>
  <XpCard title="卡片标题">
    <p>这是卡片内容</p>
  </XpCard>

  <XpCard title="卡片标题">
    <p>卡片内容区域</p>
    <template #footer>
      <div style="display:flex;justify-content:flex-end;gap:8px">
        <XpButton size="small">取消</XpButton>
        <XpButton size="small" type="primary">确定</XpButton>
      </div>
    </template>
  </XpCard>

  <XpCard title="卡片标题" shadow="hover">
    <p>悬停出现阴影</p>
  </XpCard>
</template>
Props
属性 类型 默认值 说明
title string '' 卡片标题
shadow string always 阴影效果:always / hover / never
bordered boolean true 是否显示边框
hover boolean false 是否 hover 时上移
Slots
插槽名 说明
header 自定义头部内容
default 卡片主体内容
footer 底部内容
extra 头部右侧内容

Tabs 标签页

分隔内容上有关联但属于不同类别的数据集合。

基础用法
<template>
  <XpTabs v-model="active">
    <XpTabPane name="tab1" title="选项一">
      <p>这是选项一的内容。</p>
    </XpTabPane>
    <XpTabPane name="tab2" title="选项二">
      <p>这是选项二的内容。</p>
    </XpTabPane>
    <XpTabPane name="tab3" title="选项三">
      <p>这是选项三的内容。</p>
    </XpTabPane>
  </XpTabs>
</template>

<script setup>
import { ref } from 'vue'
const active = ref('tab1')
</script>
Tabs Props
属性 类型 默认值 说明
modelValue string / number null 当前激活的 name,支持 v-model
TabPane Props
属性 类型 默认值 说明
name string / number - 必填,唯一标识
title string '' 标签标题
disabled boolean false 是否禁用
Tabs Events
事件名 说明 回调参数
update:modelValue 切换时触发 name
change 切换时触发 name

Menu 菜单

为页面提供导航的菜单列表。支持目录(子菜单)嵌套目录,层级不限制;提供「组装模式」(通过 XpSubMenu / XpMenuItem 组合)与「数据驱动模式」(传入 items 树自动生成)两种用法。

基础用法
<template>
  <XpMenu v-model="active" @select="handleSelect">
    <XpMenuItem index="dashboard">仪表盘</XpMenuItem>
    <XpSubMenu index="system">
      <template #title>系统管理</template>
      <XpMenuItem index="system-users">用户管理</XpMenuItem>
      <XpMenuItem index="system-settings" disabled>系统设置</XpMenuItem>
    </XpSubMenu>
  </XpMenu>
</template>

<script setup>
import { ref } from 'vue'
const active = ref('dashboard')

const handleSelect = (index, item) => {
  // index: 选中项完整 index;item: 数据驱动模式下对应的原始节点(组装模式为 null)
}
</script>
多级嵌套(不限制层级)

目录(XpSubMenu)内部可以继续放置目录,逐层展开:

<XpMenu v-model="active">
  <XpSubMenu index="1">
    <template #title>导航一</template>
    <XpMenuItem index="1-1">选项一</XpMenuItem>
    <XpSubMenu index="1-2">
      <template #title>导航二(子目录)</template>
      <XpSubMenu index="1-2-2">
        <template #title>导航三(再嵌套)</template>
        <XpMenuItem index="1-2-2-1">四级选项一</XpMenuItem>
      </XpSubMenu>
    </XpSubMenu>
  </XpSubMenu>
</XpMenu>
数据驱动模式

传入 items 树自动递归生成菜单,children 可无限嵌套。节点结构: { index, label, icon?, children?, disabled? },其中 icon 传内联 SVG 字符串(图标内部颜色使用 currentColor 便于跟随主题着色)。节点还可携带任意扩展字段(如 path),经 select 事件随原节点一并透出。深度嵌套时依赖插件全局注册(app.use(XpUi) 或逐一注册 XpSubMenu / XpMenuItem)。

<template>
  <XpMenu :items="items" v-model="active" @select="handleSelect"></XpMenu>
</template>

<script setup>
import { ref } from 'vue'
const active = ref('system.system-users')

const items = [
  { index: 'dashboard', label: '仪表盘' },
  {
    index: 'system',
    label: '系统管理',
    children: [
      { index: 'system-users', label: '用户管理' },
      {
        index: 'system-log',
        label: '日志记录',
        children: [
          { index: 'system-log-login', label: '登录日志' },
          { index: 'system-log-operation', label: '操作日志' }
        ]
      }
    ]
  }
]
</script>

激活项使用叶子节点的「完整 index」:数据驱动模式下 = 各级 index 以 . 拼接(如 system.system-log.system-log-login);组装模式下直接使用各组件上声明的 index。

手风琴 & 多展开

uniqueOpen(默认 true)开启手风琴:同一分支下仅保留一个展开的目录,其余自动收起;设为 false 可同时展开多个。

分组标题

使用 XpMenuGroup 为相邻菜单添加分组说明(仅组装模式):

<XpMenu v-model="active">
  <XpMenuGroup title="导航">
    <XpMenuItem index="home">首页</XpMenuItem>
    <XpMenuItem index="news">消息</XpMenuItem>
  </XpMenuGroup>
</XpMenu>
横向 / 折叠
  • mode="horizontal":横向排列,一级目录悬停下拉弹出面板;
  • collapse(仅 vertical 生效):折叠为仅图标模式,悬停一级目录在右侧弹出面板(面板内部仍支持无限嵌套)。折叠态下菜单宽度由外层容器控制(如 64px ~ 68px)。
<XpMenu mode="horizontal" :items="items" v-model="active"></XpMenu>
<XpMenu :items="items" collapse v-model="active"></XpMenu>
样式定制

菜单使用 --xp-menu-* 系列 CSS 变量(默认对齐全局主题),可在使用处按需覆盖,例如深色侧边栏:

.my-sidebar .xp-menu {
  --xp-menu-text: rgba(226, 232, 255, 0.62);
  --xp-menu-text-primary: rgba(236, 242, 255, 0.92);
  --xp-menu-active: #fff;
  --xp-menu-active-bg: rgba(64, 158, 255, 0.32);
  --xp-menu-hover-bg: rgba(255, 255, 255, 0.04);
  --xp-menu-panel-bg: #1c2333;
  --xp-menu-disabled: rgba(226, 232, 255, 0.35);
}
Menu Props
属性 类型 默认值 说明
modelValue string / number '' 当前激活项(叶子节点)的完整 index,支持 v-model
mode string 'vertical' 菜单方向:vertical / horizontal
items array [] 数据驱动模式的菜单树,children 可无限嵌套
collapse boolean false 折叠为仅图标模式(仅 vertical 生效),悬停弹出面板
uniqueOpen boolean true 手风琴模式,同一分支下仅展开一个目录
disabled boolean false 是否禁用整个菜单
Menu Events
事件名 说明 回调参数
update:modelValue 选择菜单项时触发 index
select 选择菜单项时触发 (index, item):item 为数据驱动模式下选中的原始节点,组装模式为 null
open 展开子菜单时触发 index
close 收起子菜单时触发 index
SubMenu Props
属性 类型 默认值 说明
index string / number - 必填,完整路径 index
label string '' 数据驱动模式下的标题文案
icon string '' 数据驱动模式下的内联 SVG 图标
items array [] 数据驱动模式下子级菜单树
disabled boolean false 是否禁用

标题内容也支持 #title 插槽,插槽优先级高于 label / icon。

MenuItem Props
属性 类型 默认值 说明
index string / number - 必填,叶子节点完整 index
disabled boolean false 是否禁用
item object null 数据驱动模式下对应的原始节点(随 select 事件透传)
MenuGroup Props
属性 类型 默认值 说明
title string '' 分组标题
Slots
插槽名 说明
default(Menu) 组装模式:组合 XpSubMenu / XpMenuItem / XpMenuGroup
default(SubMenu) 子级菜单内容
title(SubMenu) 子菜单标题内容

Dialog 对话框

在保留当前页面状态的情况下,告知用户并承载相关操作。

基础用法
<template>
  <XpButton type="primary" @click="visible = true">打开对话框</XpButton>
  <XpDialog
    v-model:visible="visible"
    title="提示"
    @confirm="handleConfirm"
    @cancel="handleCancel"
  >
    <p>这是一段弹窗内容</p>
  </XpDialog>
</template>

<script setup>
import { ref } from 'vue'
const visible = ref(false)
const handleConfirm = () => { visible.value = false }
const handleCancel = () => { visible.value = false }
</script>
自定义宽度
<template>
  <XpDialog
    v-model:visible="visible"
    title="宽弹窗"
    width="700px"
  >
    <p>弹窗内容</p>
  </XpDialog>
</template>
自定义按钮文字
<template>
  <XpDialog
    v-model:visible="visible"
    title="确认删除"
    confirm-button-text="删除"
    cancel-button-text="我再想想"
  >
    <p>确定要删除这条记录吗?</p>
  </XpDialog>
</template>
Props
属性 类型 默认值 说明
visible boolean false 是否显示,支持 v-model
title string '' 弹窗标题
width string 500px 弹窗宽度
confirmButtonText string 确定 确认按钮文字
cancelButtonText string 取消 取消按钮文字
closeOnClickModal boolean true 点击遮罩层是否关闭弹窗
showDefaultFooter boolean true 是否显示默认底部按钮
Events
事件名 说明 回调参数
confirm 点击确认按钮时触发 -
cancel 点击取消按钮时触发 -
close 关闭弹窗时触发 -
update:visible 可见性改变时触发 visible
Slots
插槽名 说明
default 弹窗主体内容
footer 自定义底部按钮区域

按 Esc 键同样可以关闭弹窗。


Empty 空状态

用于列表、目录等数据为空时的占位展示。

基础用法
<template>
  <XpEmpty title="目录为空" hint="拖入文件或点击工具栏上传" />
</template>
自定义图标与操作
<template>
  <XpEmpty title="连接失败" hint="无法连接到服务器,请检查网络后重试">
    <template #icon>
      <div class="my-icon" />
    </template>
    <XpButton type="primary" size="small">重新加载</XpButton>
  </XpEmpty>
</template>
Props
属性 类型 默认值 说明
title string 暂无内容 主文案
hint string '' 辅助说明文案
Slots
插槽名 说明
icon 自定义图标(默认是一个文件占位图形)
default 底部操作区(如重试按钮)

Pagination 分页

分页条组件,展示数据总数与页码序列(首尾 + 当前页前后 2 页,跳跃处用省略号)。total 为 0 时不渲染。通过 v-model:page 双向绑定当前页,翻页成功后触发 change 事件;传入 pageSizes 会额外渲染每页条数选择器,配合 v-model:page-size 使用。

基础用法
<template>
  <XpPagination v-model:page="page" :total="128" :page-size="10" @change="fetchPage" />
</template>

<script setup>
import { ref } from 'vue'

const page = ref(1)
const fetchPage = (n) => {
  // 依据新页码 page 向后端拉取数据
  console.log('当前页', n)
}
</script>
每页条数选择
<template>
  <XpPagination
    v-model:page="page"
    v-model:page-size="pageSize"
    :total="186"
    :page-sizes="[10, 20, 50]"
    @change="fetchPage"
    @size-change="fetchPage"
  />
</template>
Props
属性 类型 默认值 说明
total number 0 数据总条数(为 0 时不渲染分页条)
page number 1 当前页码,从 1 开始,支持 v-model:page
pageSize number 10 每页条数,支持 v-model:page-size
pageSizes array [] 可选的每页条数列表;为空时不渲染条数选择器
Events
事件名 说明 回调参数
update:page 页码变化(配合 v-model:page 使用) (page: number)
update:pageSize 每页条数变化(配合 v-model:page-size 使用) (pageSize: number)
change 翻页成功 (page: number)
size-change 每页条数变化 (pageSize: number)

Table 表格

列式定义表格:XpTable 负责整体渲染(含加载遮罩、空状态),通过子组件 XpTableColumn 声明列。支持字段自动渲染、自定义单元格/表头、排序、多选、斑马纹与边框、固定列,适用于各数据列表页面。

基础用法
<template>
  <XpTable :data="list" row-key="id">
    <XpTableColumn prop="name" label="姓名" />
    <XpTableColumn prop="email" label="邮箱" />
    <XpTableColumn prop="active" label="状态" width="100">
      <template #default="{ row }">
        <XpTag size="small" :type="row.active ? 'success' : 'info'">
          {{ row.active ? '启用' : '禁用' }}
        </XpTag>
      </template>
    </XpTableColumn>
  </XpTable>
</template>
XpTable Props
属性 类型 默认值 说明
data array [] 表格数据源
loading boolean false 加载中状态,为真时显示加载遮罩
emptyTitle string 暂无数据 空状态标题
emptyHint string '' 空状态提示文案
rowKey string id 行唯一标识字段名,用于 :key 与多选标识;行数据缺失该字段时回退到行索引(多选/排序建议显式配置)
stripe boolean false 斑马纹:奇偶行交替背景色
border boolean false 边框模式:单元格带纵向边框并整体加外框
XpTableColumn Props
属性 类型 默认值 说明
prop string '' 对应数据行字段名,自动渲染 row[prop];配合 formatter / #default 插槽时可不传
label string '' 表头文案
type string default 列类型:default 普通列 / selection 多选列
width number / string '' 列宽(number 为 px);固定列必须显式指定
minWidth number / string '' 最小列宽
align string left 对齐方式:left / center / right
sortable boolean / string false 是否可排序:true 内置升/降序;'custom' 仅触发 sort-change 由外部处理
fixed string '' 固定列位置:'left' / 'right',需配合 width 使用
formatter function - 单元格格式化:(row, column, cellValue, index) => string
className string '' 自定义列 class,同时作用于表头与单元格(如配合媒体查询隐藏整列)
XpTable Events
事件名 说明 回调参数
sort-change 排序状态变化 { column, prop, order },order 为 ascending / descending / null
selection-change 勾选集合变化 (rows: array) 当前选中的行
select 单个行勾选状态变化 (row, selected)
row-click 点击行 (row, index)
XpTable 实例方法
方法名 说明
clearSelection 清空所有勾选
toggleRowSelection(row, selected?) 切换指定行勾选状态;selected 缺省时反转当前状态
XpTable Slots
插槽名 说明
default 放置若干 XpTableColumn(列定义)
empty 自定义空状态内容(默认渲染 XpEmpty,由 emptyTitle / emptyHint 控制文案)
XpTableColumn Slots
插槽名 说明
default 自定义单元格内容,作用域暴露 { row, index }
header 自定义表头内容,作用域暴露 { column }
排序
<XpTable :data="list" row-key="id" @sort-change="({ prop, order }) => onSort(prop, order)">
  <XpTableColumn prop="name" label="姓名" sortable width="130" />
</XpTable>

sortable 为 true 时表格内置升/降序(重复点击在升序 → 降序 → 复原间切换);为 'custom' 时不排序,仅触发 sort-change,由外部维护排序后的数据。

多选
<template>
  <XpTable ref="tableRef" :data="list" row-key="id" @selection-change="onSelectionChange">
    <XpTableColumn type="selection" width="48" />
    <XpTableColumn prop="name" label="姓名" />
  </XpTable>
</template>

<script setup>
const tableRef = ref(null)

const onSelectionChange = (rows) => {
  console.log(rows) // 选中的行数组
}

const clearAll = () => tableRef.value.clearSelection()
</script>

多选通过与 row-key 对应的字段标识行,请确保数据包含该字段。

固定列
<XpTable :data="list" row-key="id">
  <XpTableColumn type="selection" fixed="left" width="48" />
  <XpTableColumn prop="name" label="姓名" fixed="left" width="110" />
  <XpTableColumn prop="email" label="邮箱" />
  <XpTableColumn label="操作" fixed="right" width="140">
    <template #default="{ row }">
      <XpButton size="small" type="primary" @click="onEdit(row)">编辑</XpButton>
    </template>
  </XpTableColumn>
</XpTable>

fixed="left" / fixed="right" 将列冻结在容器两侧,表体可左右横向滚动(移动端同样生效)。固定列需显式传 width。


FileIcon 文件图标

按文件类型展示对应的矢量图标,内置文件夹与常见文件类型,适用于文件管理器等场景。

基础用法
<template>
  <XpFileIcon type="folder" :size="34" />
  <XpFileIcon type="pdf" :size="34" />
  <XpFileIcon type="code" :size="20" />
</template>
Props
属性 类型 默认值 说明
type string file 类型:folder / image / video / audio / pdf / doc / sheet / slide / archive / code / text / file
size number 20 图标边长(px)

ContextMenu 右键菜单

在指定屏幕坐标位置弹出的菜单,常用于右键 / 长按等交互场景。

基础用法
<template>
  <div @contextmenu.prevent="openMenu($event, items)">右键点击此区域</div>
  <XpContextMenu :visible="menu.visible" :x="menu.x" :y="menu.y" :items="menu.items" @close="menu.visible = false" />
</template>

<script setup>
import { reactive } from 'vue'
const menu = reactive({ visible: false, x: 0, y: 0, items: [] })
const openMenu = (e, items) => {
  menu.x = e.clientX
  menu.y = e.clientY
  menu.items = items
  menu.visible = true
}
const items = [
  { label: '打开', command: 'open' },
  { label: '禁用项', disabled: true },
  { divider: true },
  { label: '删除', command: 'delete', danger: true }
]
</script>

菜单会自动进行视口边界校正;点击菜单项、遮罩或按 Esc 均会关闭菜单。

Props
属性 类型 默认值 说明
visible boolean false 是否显示
x number 0 菜单左上角 x 坐标(px)
y number 0 菜单左上角 y 坐标(px)
items Array [] 菜单项:{ label, icon?, command?, danger?, disabled?, divider?, onClick? }
Events
事件名 说明 回调参数
select 点击菜单项时触发 item
command 点击菜单项时触发(传 command) command, item
close 菜单关闭时触发 -

兼容用法:菜单项里直接传 onClick 函数也会在点击时被调用。


Toast 轻提示

轻量级的全局消息提示,需要配合 useToast() 组合式函数使用。

基础用法
<template>
  <!-- 在应用根节点挂载一次即可 -->
  <XpToast />
</template>

<script setup>
import { useToast } from '@cghbcf/xp-ui'
const { toast, success, error, warn, info } = useToast()

success('操作成功')
error('操作失败')
warn('请注意该操作的后果')
info('这是一条普通提示')
</script>
useToast API
方法 说明 参数
toast 触发提示,可自定义类型与时长 (message, type?, duration?)
success 成功提示(2200ms) message
error 错误提示(3600ms) message
warn 警告提示(2800ms) message
info 信息提示(2600ms) message
toasts 响应式提示列表(ref) -

toast 的 type 可选值:info / success / error / warn。


主题定制

Xp UI 内置完整的 浅色 / 暗黑双主题 系统,并支持 可视化颜色定制、配置导入导出,可在任意项目中按需使用。

主题色(Design Tokens)

组件库的所有颜色都通过 CSS 变量 控制,你可以在浏览器开发者工具中实时查看和调试:

变量名 说明
--xp-color-primary 主色(品牌色)
--xp-color-success 成功色
--xp-color-warning 警告色
--xp-color-danger 危险色
--xp-color-info 信息色
--xp-text-color-primary 主要文字色
--xp-text-color-regular 常规文字色
--xp-border-color 边框色
--xp-bg-color 背景色
--xp-fill-color 填充色
--xp-shadow-sm / --xp-shadow-md / --xp-shadow-lg 阴影

每个主题色还自动派生出 -light(30% 浅色)、-dark(20% 深色)、-bg(背景色)、-border(边框色),无需手动配置。

浅色 / 暗黑模式切换

在入口文件中调用 initTheme() 即可自动初始化主题(读取 localStorage 或跟随系统偏好):

import { useTheme } from '@cghbcf/xp-ui'

const { initTheme, toggleTheme, setTheme, theme } = useTheme()

// 1. 页面加载时初始化主题(读取 localStorage)
initTheme()

// 2. 切换主题按钮
const handleToggle = () => toggleTheme()

// 3. 强制切换到指定主题
setTheme('dark')    // 或 'light'

// 4. 响应式读取当前主题
console.log(theme.value)  // 'light' | 'dark'

Vue 组件中的示例用法:

<template>
  <button @click="toggleTheme">
    当前主题:{{ theme === 'dark' ? '🌙 暗黑' : '☀️ 浅色' }}
  </button>
</template>

<script setup>
import { useTheme } from '@cghbcf/xp-ui'
const { theme, toggleTheme, initTheme } = useTheme()
initTheme()  // 在页面挂载时调用
</script>

自定义主题色(applyThemeConfig)

通过 applyThemeConfig 可以一次性替换所有颜色变量,支持:

  • 修改主色系(primary / success / warning / danger / info)
  • 分别定制浅色和暗黑两套文本、边框、背景、填充、阴影
import { applyThemeConfig } from '@cghbcf/xp-ui'

// 修改主色为绿色 —— 只需一个颜色值,其他衍生色自动生成
applyThemeConfig({
  primary: {
    primary: '#22c55e',   // 绿色主色
    success: '#67c23a',
    warning: '#e6a23c',
    danger: '#f56c6c',
    info: '#909399'
  }
})

// 完整配置:浅色 + 暗黑各一套
applyThemeConfig({
  primary: {
    primary: '#22c55e',
    success: '#67c23a',
    warning: '#e6a23c',
    danger: '#f56c6c',
    info: '#909399'
  },
  light: {
    text: { primary: '#303133', regular: '#606266', secondary: '#909399', placeholder: '#c0c4cc' },
    border: { base: '#dcdfe6', light: '#ebeef5', lighter: '#f2f6fc' },
    bg: { base: '#ffffff', page: '#f2f3f5', soft: '#f5f7fa', overlay: 'rgba(0, 0, 0, 0.5)' },
    fill: { base: '#f0f2f5', light: '#f5f7fa', lighter: '#fafafa' },
    shadow: { sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)', md: '0 2px 12px 0 rgba(0, 0, 0, 0.1)', lg: '0 4px 20px 0 rgba(0, 0, 0, 0.15)', overlay: '0 8px 24px 0 rgba(0, 0, 0, 0.2)' }
  },
  dark: {
    text: { primary: '#e5eaf3', regular: '#cfd3dc', secondary: '#a3a6ad', placeholder: '#8d9095' },
    border: { base: '#4c4d4f', light: '#414243', lighter: '#363637' },
    bg: { base: '#1d1e1f', page: '#141414', soft: '#2a2b2c', overlay: 'rgba(0, 0, 0, 0.7)' },
    fill: { base: '#303030', light: '#262727', lighter: '#1d1d1d' },
    shadow: { sm: '0 1px 2px 0 rgba(0, 0, 0, 0.4)', md: '0 2px 12px 0 rgba(0, 0, 0, 0.45)', lg: '0 4px 20px 0 rgba(0, 0, 0, 0.5)', overlay: '0 8px 24px 0 rgba(0, 0, 0, 0.6)' }
  }
})

注意:applyThemeConfig 会自动做深合并——你只需传入要修改的部分,未传的部分保持默认。

导出主题配置(buildCssString)

可以将当前的主题配置导出为完整的 CSS 文件,放到其他项目(非 Vue 项目也可使用):

import { buildCssString, applyThemeConfig, getDefaultThemeConfig } from '@cghbcf/xp-ui'

// 1. 先应用你的自定义主题
applyThemeConfig({ primary: { primary: '#22c55e' } })

// 2. 生成 CSS(包含 :root 和 [data-theme="dark"] 两套规则)
const css = buildCssString({
  primary: { primary: '#22c55e' },
  light: { text: { primary: '#303133' } },
  dark: { text: { primary: '#e5eaf3' } }
})

// 3. 写入文件(Node / Vite 构建时使用)
// fs.writeFileSync('dist/xp-ui-theme.css', css)
console.log(css)

也可以直接读取 themeConfig 响应式对象:

const { themeConfig } = useTheme()
console.log(JSON.stringify(themeConfig.value, null, 2))
// 输出完整的主题配置,供导入/导出

导出 JSON 配置文件

导出 JSON 后可以保存到项目配置文件中,下次启动时重新导入:

import { useTheme } from '@cghbcf/xp-ui'

const { themeConfig, applyThemeConfig, resetThemeConfig } = useTheme()

// 导出
const json = JSON.stringify(themeConfig.value, null, 2)
// 可以保存到 localStorage 或上传到服务器

// 导入(从文件 / localStorage / API 读取)
applyThemeConfig(JSON.parse(json))

// 恢复默认
resetThemeConfig()

主题 API 汇总

import { useTheme } from '@cghbcf/xp-ui'

const {
  theme,               // 响应式 ref: 当前主题 ('light' | 'dark')
  themeConfig,         // 响应式 ref: 完整主题配置对象
  setTheme,            // 设置主题: setTheme('dark' | 'light')
  toggleTheme,         // 在 light/dark 之间切换
  initTheme,           // 初始化:读取 localStorage + 跟随系统偏好
  applyThemeConfig,    // 应用自定义主题配置(CSS 变量会立即更新)
  resetThemeConfig,    // 恢复默认配置
  getDefaultThemeConfig, // 获取默认配置对象
  buildCssString,      // 根据配置生成 CSS 字符串
  buildCssVars         // 根据配置生成 { '--xp-color-xxx': value } 映射
} = useTheme()

主题持久化

initTheme() 和 applyThemeConfig() 都会自动将设置写入 localStorage(键名 xp-ui-theme 和 xp-ui-theme-config),下次访问时自动恢复,无需额外处理。


浏览器支持

支持所有现代浏览器:

  • Chrome(推荐)
  • Firefox
  • Safari
  • Edge

License

MIT

Related Packages

mesh-ui-components

UI Component library

9,059
@a2simcode/ui

A Vue 3 UI Component Library

63,028
ketekny-ui-kit

A Vue 3 UI component library with Tailwind CSS styling

25,243
bms-shared-components

Shared Vue 3 components library

17,668
@cck-ui/core

Vue component library focused on usability, accessibility and developer experien...

15,519 0

Version History

Version Released Vue License
1.3.0 ^3.4.0 MIT
1.2.0 ^3.4.0 MIT
1.1.0 ^3.4.0 MIT
1.0.1 ^3.4.0 MIT
1.0.0 ^3.4.0 MIT