@lovince/ui-vue

中文文档
0.5.0发布于 2026/11/02MITTypeScriptES Module

可访问的无头Vue 3组件为Lovince UI -披露,复选框,选项卡和对话框,无样式。

中文使用文档
文档目录11 节
  1. 组件
  2. 原语
  3. 按钮
  4. 图标
  5. 形式
  6. 共同的约定
  7. Lovince-specific行为
  8. 构建块
  9. 状态属性
  10. 已知的限制
  11. 许可证

@lovince / ui-vue

可访问的,无样式的Vue 3组件为Lovince UI。每个组件都是 状态机来自 @lovince/ui-headless;它的浏览器 效果贯穿始终 @lovince/ui-dom. 这个套餐订阅 机器,输入道具,并呈现什么 connect() 的回报。它不存在 它自己的行为。

状态: 0.5.0、实验。 API之前可能会更改 1.0.

bun add @lovince/ui-vue

需要v3.5 +(用于ssr稳定) useId). 包中没有CSS。风格 它与类和 data-* 状态属性,或使用 @lovince/themes 令牌。

每个组件导出都带有 Lv 前缀(LvButton, LvDialogRoot),所以 名称永远不会与您自己的组件或本地元素冲突。

组件

集团组件部分
原语文本,标题,标签,链接,代码,Kbd,框,对比度,视觉隐藏,分隔符
图标LvIcon,从分离 @lovince/ui-vue/icon 条目
信息披露信息披露LvDisclosureRoot, LvDisclosureTrigger, LvDisclosureContent
手风琴LvAccordionRoot, LvAccordionItem, LvAccordionHeader, LvAccordionTrigger, LvAccordionContent
选项卡LvTabsRoot, LvTabsList, LvTabsTrigger, LvTabsContent
覆盖对话框LvDialogRoot, LvDialogTrigger, LvDialogPortal, LvDialogOverlay, LvDialogContent, LvDialogTitle, LvDialogDescription, LvDialogClose
LightboxLvLightboxRoot, LvLightboxTrigger, LvLightboxPortal, LvLightboxOverlay, LvLightboxContent, LvLightboxTitle, LvLightboxItem, LvLightboxPrevious, LvLightboxNext, LvLightboxCounter, LvLightboxClose
弹出窗口LvPopoverRoot, LvPopoverTrigger, LvPopoverAnchor, LvPopoverPortal, LvPopoverContent, LvPopoverClose
工具提示LvTooltipRoot, LvTooltipTrigger, LvTooltipPortal, LvTooltipContent
悬停卡LvHoverCardRoot, LvHoverCardTrigger, LvHoverCardPortal, LvHoverCardContent
菜单LvDropdownMenuRoot, LvDropdownMenuTrigger, LvDropdownMenuContent, LvDropdownMenuItem, LvDropdownMenuCheckboxItem, LvDropdownMenuRadioGroup, LvDropdownMenuRadioItem, LvDropdownMenuItemIndicator, LvDropdownMenuLabel, LvDropdownMenuGroup, LvDropdownMenuSeparator, LvContextMenuTrigger
导航菜单LvNavigationMenuRoot, LvNavigationMenuList, LvNavigationMenuItem, LvNavigationMenuTrigger, LvNavigationMenuContent, LvNavigationMenuLink
烤面包LvToastViewport, LvToastRoot, LvToastTitle, LvToastDescription, LvToastAction, LvToastClose,再加上 toast()
选择复选框,切换LvCheckboxRoot, LvCheckboxIndicator, LvSwitchRoot, LvSwitchThumb
广播组LvRadioGroupRoot, LvRadioGroupItem, LvRadioGroupIndicator
切换,切换组LvToggleRoot, LvToggleGroupRoot, LvToggleGroupItem
选择LvSelectRoot, LvSelectTrigger, LvSelectValue, LvSelectContent, LvSelectItem, LvSelectItemText, LvSelectItemIndicator, LvSelectGroup, LvSelectLabel, LvSelectSeparator
组合框LvComboboxRoot, LvComboboxAnchor, LvComboboxInput, LvComboboxTrigger, LvComboboxClear, LvComboboxContent, LvComboboxItem, LvComboboxItemIndicator, LvComboboxEmpty
命令面板LvCommandRoot, LvCommandInput, LvCommandList, LvCommandGroup, LvCommandItem, LvCommandEmpty, LvCommandSeparator
Emoji选择器LvEmojiPickerRoot, LvEmojiPickerSearch, LvEmojiPickerList, LvEmojiPickerGroup, LvEmojiPickerItem, LvEmojiPickerNav…
输入滑块LvSliderRoot, LvSliderTrack, LvSliderRange, LvSliderThumb
角滑块LvAngleSliderRoot, LvAngleSliderTrack, LvAngleSliderMarkers, LvAngleSliderIndicator, LvAngleSliderThumb, LvAngleSliderValue
数域LvNumberFieldRoot, LvNumberFieldInput, LvNumberFieldIncrement, LvNumberFieldDecrement
销的输入LvPinInputRoot, LvPinInputInput
日历LvCalendarRoot, LvCalendarHeading, LvCalendarPrev, LvCalendarNext, LvCalendarGrid, LvCalendarHeadCell, LvCalendarCell, LvCalendarDay
形式字段,输入,文本区域,表单,TagsInput, FileUpload, TimeField, PhoneInputLvFieldRoot, LvFieldLabel, LvTagsInputRoot, LvTagsInputInput, LvTagsInputItem, LvTagsInputRemove, LvFileUploadRoot, LvFileUploadInput, LvFileUploadItem, LvFileUploadRemove, LvTimeFieldRoot, LvTimeFieldInput, LvPhoneInputRoot, LvPhoneInputInput, LvPhoneInputCountrySelect
时钟选择器LvClockPickerRoot, LvClockPickerViewTrigger, LvClockPickerMeridiem, LvClockPickerDial, LvClockPickerHand
布局ScrollAreaLvScrollAreaRoot, LvScrollAreaViewport, LvScrollAreaScrollbar, LvScrollAreaThumb
分配器LvSplitterGroup, LvSplitterPanel, LvSplitterHandle
树LvTreeRoot, LvTreeItem, LvTreeGroup
旋转木马LvCarouselRoot, LvCarouselViewport, LvCarouselSlide, LvCarouselPrevious, LvCarouselNext, LvCarouselIndicators, LvCarouselIndicator
可分类的LvSortableRoot, LvSortableItem, LvSortableHandle
部分LvSectionRoot, LvSectionHeader, LvSectionEyebrow, LvSectionTitle, LvSectionDescription, LvSectionContent
显示《阿凡达》,进步LvAvatarRoot, LvAvatarImage, LvAvatarFallback, LvProgressRoot, LvProgressIndicator
计,倒计时LvGauge, LvCountdownRoot, LvCountdownSegment
表格LvTableContainer, LvTableRoot, LvTableCaption, LvTableHeader, LvTableBody, LvTableFooter, LvTableRow, LvTableHead, LvTableCell,再加上 LvDataTable

原语

这些原语提供了语义HTML和稳定的样式挂钩,而不会强加于人 CSS。 LvText 和 LvHeading 公开 data-text-role 匹配排版 角色 @lovince/tokens;标题级别控制语义独立于 视觉的大小。

<script setup lang="ts">
import { LvAspectRatio, LvCode, LvHeading, LvKbd, LvLabel, LvLink, LvSeparator, LvText, LvVisuallyHidden } from '@lovince/ui-vue'
</script>

<template>
  <LvHeading :level="1" size="display-md">Workspace</LvHeading>
  <LvText variant="body-md">Manage projects and members.</LvText>
  <LvLabel for="query">Search</LvLabel>
  <LvLink href="/guide">Read the guide</LvLink>
  <LvCode>bun test</LvCode>
  <LvKbd>Ctrl+K</LvKbd>
  <LvAspectRatio :ratio="16 / 9">
    <img src="/product.webp" alt="Product detail" />
  </LvAspectRatio>
  <LvVisuallyHidden>Search projects</LvVisuallyHidden>
  <LvSeparator :decorative="false" />
</template>

LvBox, LvAspectRatio, LvText, LvHeading, LvLabel, LvLink, LvCode, LvKbd, LvVisuallyHidden 支持 as 和 asChild. LvAspectRatio 默认为1:1 框架;集 ratio 到一个正有限数,例如 16 / 9 来衡量它的大小 内容区域。 LvLink 默认为锚,并留下导航属性 如 href, target, rel 在来电者的控制之下。 LvCode 和 LvKbd 默认为它们对应的语义元素。当 LvHeading 呈现一个非标题元素,它保持其语义级别 role="heading" 和 aria-level. LvVisuallyHidden 应用最小的内联 剪辑风格需要保持辅助技术的可用性。一个 non-decorative LvSeparator 公开分隔符语义及其方向; 装饰性分隔符隐藏在可访问性树中。

按钮

LvButton 是命名设计决策的部分: variant (solid, subtle, outline, ghost, danger), size (sm, md, lg, icon)成为 data-variant 和 data-size,而样式表决定了什么 他们每个人看起来都像。组件所拥有的是手写的标记 按钮出错了。

<script setup lang="ts">
import { LvButton } from '@lovince/ui-vue'
</script>

<template>
  <LvButton @click="save">Save</LvButton>
  <LvButton type="submit" variant="solid" size="lg" :loading="saving">Save</LvButton>
  <LvButton as="a" href="/settings" variant="ghost" size="sm">Settings</LvButton>
  <LvButton :disabled="!valid" variant="outline">Publish</LvButton>
</template>
  • type 默认为 button,因此表单中的按钮永远不会提交 事故;问......为...... submit 或者 reset 明确。
  • disabled 当元素为实元素时,设置native属性 button, aria-disabled 当它不是,因为锚不能被禁用。
  • loading 集合 aria-busy 并将控件保持在TAB顺序中——这是一个请求 从键盘开始,在吞咽时保持键盘可见 单击以使处理程序不能触发两次。
  • 这两个状态也显示为 data-disabled 和 data-loading,两者都没有 运行 onClick 这是给定的。与 asChild 元素是你的,点击 处理包括;状态属性仍然到达。

图标

LvIcon 从中绘制一个象形符号 @lovince/icons 在注册表的共享24单元上 画布。它是它自己的条目,因为icon注册表是一个可选的peer: 进口 @lovince/ui-vue 没有加载图标数据,一个应用程序带来了自己的 icon不需要额外的东西。

<script setup lang="ts">
import { LvIcon } from '@lovince/ui-vue/icon'
</script>

<template>
  <LvIcon name="arrowRight" />
  <LvIcon name="success" :size="16" :stroke-width="1.5" label="Completed" />
</template>

图标是装饰性的 aria-hidden="true" -除非给出 label, 也就是说 role="img" 用那个通俗易懂的名字。 absoluteStrokeWidth 使渲染的描边厚度恒定为 size 生长; fill 取0到 1用于部分洗涤; rotate 和 flip 围绕画布中心转动。大小和 笔画退回到注册表自己的默认值,并且未知 name 呈现一个 空框而不是破坏布局。

形式

LvFieldRoot 提供一个稳定的输入id,并连接标签、描述和 误差为 LvInput 或者 LvTextarea. 描述和错误副本可以作为参数传递 道具或命名槽。集 invalid 暴露一个错误槽,或通过 error 来 自动将该字段标记为无效。 required 和 disabled 传播 对现场进行控制;每个控件都可以覆盖它们。

<script setup lang="ts">
import { LvFieldLabel, LvFieldRoot, LvForm, LvInput, LvTextarea } from '@lovince/ui-vue'
</script>

<template>
  <LvForm @submit.prevent="save">
    <LvFieldRoot required description="Use your work email.">
      <LvFieldLabel>Email</LvFieldLabel>
      <LvInput type="email" name="email" autocomplete="email" />
    </LvFieldRoot>

    <LvFieldRoot :invalid="Boolean(message)" :error="message">
      <LvFieldLabel>Project summary</LvFieldLabel>
      <LvTextarea name="summary" />
    </LvFieldRoot>

    <button type="submit">Save</button>
  </LvForm>
</template>

LvInput 和 LvTextarea 支持 modelValue / defaultValue 并发出 update:modelValue. LvTextarea 使用基于内容的字段大小 浏览器支持它,并保留了一个本机 rows 回退。 LvForm 是本地人 表单包装器:浏览器约束验证和提交事件保留在 控制。集 submitting 暴露 aria-busy 和 data-submitting,或者 noValidate 在其他地方处理验证时。

TagsInput 和 FileUpload 公开它们的当前值和被拒绝的条目 通过根节点的默认槽位。他们纯粹的规则和拒绝的理由依然存在 @lovince/ui-headless.

<script setup lang="ts">
import {
  LvFileUploadInput,
  LvFileUploadItem,
  LvFileUploadRemove,
  LvFileUploadRoot,
  LvTagsInputInput,
  LvTagsInputItem,
  LvTagsInputRemove,
  LvTagsInputRoot,
} from '@lovince/ui-vue'
</script>

<LvTagsInputRoot v-model="emails" :max="5" :validate="isEmail" name="emails">
  <LvTagsInputItem v-for="(email, index) in emails" :key="email" :index="index">
    {{ email }} <LvTagsInputRemove />
  </LvTagsInputItem>
  <LvTagsInputInput label="Add email address" />
</LvTagsInputRoot>

<LvFileUploadRoot v-model="files" accept="image/*,.pdf" :max-files="4" :max-size="5000000">
  <LvFileUploadInput />
  <LvFileUploadItem v-for="(file, index) in files" :key="file.name" :index="index">
    <template #default="{ file, size }">
      {{ file.name }} ({{ size }}) <LvFileUploadRemove />
    </template>
  </LvFileUploadItem>
</LvFileUploadRoot>

使用Enter或配置的分隔符创建标签;粘贴separator-delimited 文本被分割,并产生重复、无效和超出限制的值 rejected. 文件选择和删除共享相同的类型、每个文件大小、计数和总数 尺寸检查。 LvFileUploadRoot 发出接受 File[] 值和被拒绝的文件 用他们的理性; LvFileUploadItem 还暴露了kind, extension和localized 大小到它的槽。

TimeField 接受人工输入的时间并进行规范化存储 HH:mm 值。 它验证了可选 min 和 max 模糊或回车键的边界,并曝光 invalid 解析或范围验证失败时。 PhoneInput 格式一个 国家号码模糊,识别支持的国际前缀,还有 发出E.164值。它包含一个国家选择器,并接受一个可选的 自定义国家列表。

<LvTimeFieldRoot v-model="appointment" min="09:00" max="17:00" required name="appointment">
  <LvTimeFieldInput label="Appointment time" />
</LvTimeFieldRoot>

<LvPhoneInputRoot v-model="phone" country="KE" name="phone">
  <LvPhoneInputCountrySelect />
  <LvPhoneInputInput label="Mobile number" />
</LvPhoneInputRoot>

ScrollArea 保持滚动原生,同时暴露自定义,键盘可操作 滚动条的部分。从其容器中调整根的大小,然后渲染viewport和 滚动条/拇指部分在其中。根槽位报告当前溢出 指标;样式跟踪和拇指与他们的 data-scroll-area-* 属性。 视口保持其原生滚动行为和用途 scrollbar-width: none 支持该属性的地方。

<LvScrollAreaRoot class="results">
  <LvScrollAreaViewport>
    <div v-for="result in results" :key="result.id">{{ result.title }}</div>
  </LvScrollAreaViewport>
  <LvScrollAreaScrollbar>
    <LvScrollAreaThumb />
  </LvScrollAreaScrollbar>
</LvScrollAreaRoot>

可组合: useDataTable, useVirtualList, useInView, useScrollEdges, useActiveSection, useClipboard,再加上下面的积木。

包裹是 sideEffects: false. 只能导入应用程序 LvDialogRoot 船只 没有菜单、选择或表代码,测试强制执行这一点。

共同的约定

  • as 和 asChild. 每个部分都是一个合理的元素 as 去改变它。与 asChild,部分呈现你的独生子女, 将其属性和处理程序合并到。
  • 控制与否。 离开 v-model 关闭,组件拥有自己的状态。 把它和你的价值结合起来,就是真理的源泉。每一个被接受的改变 发出,并将模型设置为 undefined 清除它。
  • 你的身份受到尊重。 给任何部分 id 和ARIA参考文献 其他地方也一样。
  • 退出动画播放。 关闭内容保持安装状态,使用 data-state="closed",直到它的CSS动画结束。没有动画,或者 减少运动,它立即卸载。
  • Hydration-safe门户。 只在挂载后覆盖传送,所以服务器和 客户端呈现总是同意。
  • 可删除的解雇。 覆盖发出 escapeKeyDown 和 pointerDownOutside (对话框也 focusOutside)。呼叫 event.preventDefault() 让它们保持开放。

Lovince-specific行为

以下两种行为与Doitrix组件不同:

  • 披露内容和选项卡面板留在DOM中 与 hidden 而 关闭了,所以在页面中找到 aria-controls 继续工作。
  • Tabs选择第一个启用的选项卡 当没有给出值时,包括during 服务器呈现。

模态对话框也构成了页面的其余部分 inert而不仅仅是专注。

构建块

这个包中的每个组件都是以同样的方式构建的:

const machine = useMachine(dialogMachine, initialContext, {
  controlled: { open: () => props.open },          // a v-model, synced in
  onChange: (next, previous) => emit(…),           // accepted changes, never echoes of props
  beforeSend: dismiss.filter,                      // e.g. cancellable dismissal
})
const api = computed(() => connectDialog(machine.snapshot.value, machine.send))
// h(Primitive, normalizeProps(api.value.contentProps), slots)
  • useMachine 在挂载时启动效果(在服务器上没有),在挂载时停止效果 卸载,保持一个受控值的来源的真理,并提供 query 那 connect 通读整页。组件永远不会接触 DOM。
  • normalizeProps 转动引擎的中性支柱(onKeyDown)到Vue's (onKeydown). React适配器将在相同的机器上发布自己的适配器。
  • useListEnv 以视觉顺序从DOM中读取机器的列表项 导航列表。
  • Primitive, Slot, Portal, usePresence, useIdWatch 处理 呈现的问题: as/asChild水合安全的入口,出口动画, 消费者的id。

状态属性

属性值
data-stateopen / closed, checked / unchecked / indeterminate, active / inactive
data-disabled, data-readonly设定时呈现
data-orientationhorizontal / vertical
data-side, data-align碰撞处理后,浮动内容放置在哪里

浮动内容载体 data-anchor-hidden 当它的锚滚动时 看,又暴露 --lovince-floating-available-height, --lovince-floating-available-width 和 --lovince-anchor-width. 信息披露 内容公开 --lovince-collapsible-height 和 -width 用于高度动画。

已知的限制

  • 定位是引擎自己的(参见 @lovince/ui-headless): 它尊重滚动容器和转换后的祖先,并隐藏内容 谁的锚已经卷走(data-anchor-hidden). 箭头不是内置的。
  • 看到 @lovince/ui-dom 用于 inert 滚动锁浏览器警告。

许可证

麻省理工学院

版本与发布记录

@lovince/ui-vue 共发布 11 个版本,首次发布于 2026/10/16;过去 12 个月发布了 11 个版本。

版本发布日期距今
0.5.0latest2026/11/021 天前
0.4.02026/11/021 天前
0.3.02026/11/011 天前
0.2.02026/11/011 天前
0.1.12026/10/1618 天前
0.1.02026/10/1618 天前

关于 @lovince/ui-vue 的常见问题

@lovince/ui-vue 是什么?

可访问的无头Vue 3组件为Lovince UI -披露,复选框,选项卡和对话框,无样式。

如何安装 @lovince/ui-vue?

在项目目录运行 npm install @lovince/ui-vue,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:vue(^3.5.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@lovince/ui-vue 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@lovince/ui-vue 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@lovince/ui-vue 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@lovince/ui-vue 可以商用吗?

@lovince/ui-vue 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@lovince/ui-vue 还在维护吗?

最新版本 0.5.0 发布于 2026/11/02(1 天前);至今共发布 11 个版本,其中过去 12 个月发布了 11 个;首次发布于 2026/10/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。