vue-vben-admin 5.8.0 的 shadcn-ui 包:Progress 原语与 progressbar 无障碍语义解析
2026/9/10 16:18:11 网站建设 项目流程

vue-vben-admin 5.8.0 的 shadcn-ui 包:Progress 原语与 progressbar 无障碍语义解析

【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin

导读

@vben-core/shadcn-ui是 vue-vben-admin Monorepo 中基于 shadcn-vue 风格封装的 UI 组件包,5.8.0 版本为其带来了首个具备标准 progressbar 语义的 Progress 进度条原语。本文将围绕该版本的变更记录,深入解析 Progress 原语的源码实现、ARIA 无障碍语义、非法 max 回退规则与测试用例验证,帮助你理解 shadcn-ui 组件在 vue-vben-admin 内部的封装模式,并掌握在新版本中直接使用进度条组件的方式。

1. 变更记录概览:5.8.0 的 Minor 变更

关联文档 CHANGELOG.md 记录了@vben-core/shadcn-ui5.8.0 的唯一一次 Minor Changes:

feat(@vben-core/shadcn-ui): add Progress primitive with progressbar semantics

该变更由 PR #8305 引入(提交142b544),为组件库新增了带progressbar无障碍语义的 Progress 基础原语。同时,本次版本的 Patch Changes 声明了对同版本号各核心依赖的同步更新:

  • @vben-core/design@5.8.0
  • @vben-core/icons@5.8.0
  • @vben-core/shared@5.8.0
  • @vben-core/typings@5.8.0
  • @vben-core/composables@5.8.0

从 package.json 可以看到,该包的核心依赖还包括reka-ui(无头 UI 原语库)、class-variance-authority(变体样式)、@vueuse/core@lucide/vuevue本身。这意味着 Progress 并非从零实现,而是建立在 reka-ui 的ProgressRoot/ProgressIndicator之上的一层有样式、有语义的封装。

2. shadcn-ui 包在 vue-vben-admin 中的定位

2.1 目录结构与职责划分

@vben-core/shadcn-ui位于 packages/@core/ui-kit/shadcn-ui,其src目录清晰地划分为两层:

  • src/ui/:对标 shadcn 官方风格的“基础原语层”,按组件逐个目录存放,例如progress/button/dialog/select/等。每个目录通常包含 PascalCase 命名的.vue组件、统一的index.ts导出文件,复杂的原语还附带__tests__/测试目录。
  • src/components/:业务封装层,如table-actionsegmentedpin-inputscrollbar等,它们组合多个 ui 原语或第三方能力形成开箱即用的业务组件。
  • src/assets/index.css:样式入口文件,仅一行@reference "@vben/tailwind-config/theme";,通过 Tailwind 的@reference机制引用 internal/tailwind-config/src/theme.css 中的主题设计变量。

入口文件 src/index.ts 同时导出了./components./ui两层内容,并额外转发 reka-ui 的createContextSlotVisuallyHidden三个底层工具,方便外层在组合原语时使用。

2.2 与官方 shadcn-vue 的兼容配置

components.json 沿用了 shadcn-vue 的配置规范,可据此判断该包与官方生态的兼容关系:

{ "$schema": "https://shadcn-vue.com/schema.json", "style": "new-york", "typescript": true, "tailwind": { "config": "", "css": "src/assets/index.css", "baseColor": "slate", "cssVariables": true }, "aliases": { "components": "@vben-core/shadcn-ui/components", "utils": "@vben-core/shared/utils" } }

关键点解读:

  • stylenew-york(纽约风格),即组件默认采用较紧凑的现代样式变体;
  • cssVariablestrue,样式基于 CSS 变量主题,配合baseColor: slate提供整套语义色板;
  • 工具函数别名指向@vben-core/shared/utils(即cn等类名合并工具),而非 shadcn 默认的tailwind-merge独立实现。

3. Progress 原语源码深度解析

3.1 组件结构

Progress 原语由两个文件组成:Progress.vue 与 index.ts,后者仅做单一导出:

export { default as Progress } from './Progress.vue';

并在 src/ui/index.ts 中以export * from './progress'随包整体导出,因此业务代码可直接import { Progress } from '@vben-core/shadcn-ui'

3.2 核心实现

Progress.vue的实现简洁而克制,完整源码如下(已省略部分样式细节):

<script setup lang="ts"> import type { ProgressRootEmits, ProgressRootProps } from 'reka-ui'; import type { HTMLAttributes } from 'vue'; import { computed } from 'vue'; import { cn } from '@vben-core/shared/utils'; import { reactiveOmit } from '@vueuse/core'; import { ProgressIndicator, ProgressRoot, useForwardPropsEmits } from 'reka-ui'; const props = defineProps< ProgressRootProps & { class?: HTMLAttributes['class'] } >(); const emits = defineEmits<ProgressRootEmits>(); /** ProgressRoot 对非法 max 的回退值(max 必须为正数)。 */ const DEFAULT_MAX = 100; const delegatedProps = reactiveOmit(props, 'class'); const forwarded = useForwardPropsEmits(delegatedProps, emits); const normalizedMax = computed(() => { const { max } = props; return typeof max === 'number' && Number.isFinite(max) && max > 0 ? max : DEFAULT_MAX; }); </script> <template> <ProgressRoot v-slot="slotProps" >const normalizedMax = computed(() => { const { max } = props; return typeof max === 'number' && Number.isFinite(max) && max > 0 ? max : DEFAULT_MAX; });

归一化后的max同时用于:

  • 传入ProgressRoot:max属性(保证 ARIA 语义一致);
  • 指示条transform的计算分母(保证视觉填充正确)。

这保证了「无障碍属性值」与「实际渲染宽度」在任何边界输入下都保持一致,不会出现语义与视觉分裂。

4. 测试验证:progressbar 语义如何被保证

Progress 原语配套了完整的 Vitest 单测 progress.test.ts,测试通过挂载受控组件、查询[data-slot="progress"][data-slot="progress-indicator"]两个钩子来断言行为。测试覆盖的语义契约如下:

测试场景输入期望行为
基础进度语义modelValue=42, max=100role="progressbar"aria-valuemin=0aria-valuemax=100aria-valuenow=42
自定义 max 归一化modelValue=30, max=50aria-valuemax=50,指示条填充 60%(translateX(-40%)
非法 max 回退max=NaN/Infinityaria-valuemax=100,填充按 30/100 计算(translateX(-70%)
不确定状态modelValue=null省略aria-valuenowdata-state="indeterminate"
零值隐藏modelValue=0指示条完全隐藏(translateX(-100%)

这些用例直接印证了 5.8.0 CHANGELOG 中 “progressbar semantics” 的具体含义:

  • 确定性语义role="progressbar"+aria-valuemin/max/now三元组,让屏幕阅读器可以播报精确进度;
  • 不确定性语义modelValue=null时省略aria-valuenow并标记data-state="indeterminate",适用于加载中但无法估算进度的场景;
  • 边界防御:非法max一律回退 100,杜绝无穷百分比导致的渲染异常。

5. 使用方式与样式定制

5.1 基础用法

Progress 与原生 HTML 进度条(<progress>)不同,它是完全可控(controlled)组件,进度由modelValue驱动:

<script setup lang="ts"> import { Progress } from '@vben-core/shadcn-ui'; import { ref } from 'vue'; const progress = ref(42); </script> <template> <Progress v-model="progress" /> </template>

由于组件透传了 reka-ui 的ProgressRootProps,你可以继续传入 reka-ui 支持的其他属性(如getValueLabel自定义读屏播报文案)。

5.2 自定义 max 与不确定状态

<template> <!-- 自定义总量:30/50 会显示 60% 填充 --> <Progress :model-value="30" :max="50" /> <!-- 不确定状态:不显示具体数值,data-state 为 indeterminate --> <Progress :model-value="null" /> </template>

5.3 样式覆盖

两种定制方式:

  1. class透传:内置样式通过cn()与外部类合并,例如class="h-4 rounded-sm"可覆盖默认的h-2 rounded-full尺寸与圆角。
  2. 主题变量:进度条默认使用bg-primary/20轨道与bg-primary指示条,二者均基于 internal/tailwind-config/src/theme.css 中的primary主题色,因此会跟随项目的深浅色主题与品牌色联动,无需单独维护颜色。

6. 与业务封装层的配合

src/ui/层的原语被上层src/components/业务组件引用。以进度条为参照可以举一反三:基础原语只保证“语义正确 + 基础样式”,复杂交互(如spinnerloadingcount-to-animator等业务组件)则在原语之上组合状态逻辑。这种「无头原语(reka-ui)→ 基础 UI 原语(ui/)→ 业务组件(components/)」的三层架构,是整个 shadcn-ui 包的通用模式,也保证了 5.8.0 新增的 Progress 可以直接被后续业务组件安全复用。

7. 版本配套说明

5.8.0 的 Patch Changes 表明,本次发布同时升级了@vben-core/design@vben-core/icons@vben-core/shared@vben-core/typings@vben-core/composables至同版本号。如果你正在维护基于本仓库的派生项目,升级@vben-core/shadcn-ui时建议连同上述工作区依赖一并同步,以保证类型与样式 token 的一致性;完整的版本演进记录可查阅 CHANGELOG.md。

小结

vue-vben-admin 5.8.0 为@vben-core/shadcn-ui带来的 Progress 原语,是一个「小而完整」的工程范例:它以 reka-ui 的无头能力为底座,用少量代码补齐了样式、类名合并与非法输入防御,并通过单测把progressbar语义固化为可回归验证的契约。理解它的实现与测试,就等于理解了整个 shadcn-ui 包的设计方法论,也让你在新版本中能够安全、无障碍地使用进度条组件。

【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. It's fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询