场景组件

LoadingState、SearchList、CodeBlock、SidebarNav 四个场景化组件,覆盖加载、搜索、代码展示与侧边导航。

场景组件(beautiful 系列)解决特定页面形态的问题:等待、检索、代码展示、多栏导航。它们与宿主的视觉语言同源,用对了插件气质立刻对味。

LoadingState:加载态

像素风格的加载动画,三形态可选手式,内置耗时计时与减少动态偏好(prefers-reduced-motion)适配:

<script setup lang="ts">
import { LoadingState } from '@udhold/udhold-ui/components/beautiful'
</script>

<template>
  <LoadingState label="正在解析文件" variant="Dots" />
  <!-- variant: 'Drive'(波浪)| 'Dots'(圆点)| 'Orbit'(环绕) -->
</template>

与 plugin.json 联动:清单里的 loading 字段声明的就是这套视觉——

{ "loading": { "variant": "Drive", "label": "加载中" } }

它解决的是 webview 创建到插件挂载 #app 之间的白屏期:宿主直接注入纯 CSS 版骨架,插件 mount 后自动消失,零接入成本。LoadingState 组件则用于插件运行中的异步等待场景(请求返回前的占位、切换数据源的过渡),两者互补。

SearchList:搜索列表

带搜索框、空态、清空按钮的列表容器,输入即过滤(包含匹配),选中高亮动画:

<script setup lang="ts">
import { ref } from 'vue'
import { SearchList } from '@udhold/udhold-ui/components/beautiful'

const items = ['计算器', '颜色工具', 'JSON 工具', '正则编辑器']
const picked = ref('')
</script>

<template>
  <SearchList
    :items="items"
    placeholder="搜索工具…"
    :preview-count="5"
    empty-title="未找到结果"
    empty-hint="调整关键词重试"
    @select="picked = $event"
  />
</template>
参数说明
items字符串数组(复杂对象先用 weightedSearch 过滤出标签再传入)
previewCount无输入时默认展示的条数
空态自定义 empty-title / empty-hint

CodeBlock:代码块

行号 + 复制按钮的代码展示,支持流式输出(AI 场景):

<script setup lang="ts">
import { ref } from 'vue'
import { CodeBlock } from '@udhold/udhold-ui/components/beautiful'

const code = ref('const answer = 42')
</script>

<template>
  <CodeBlock :code="code" filename="answer.ts" language="ts" />
  <!-- 流式:传 visibleLines 数字,只渲染前 N 行并尾随光标 -->
</template>

SidebarNav:分组侧边导航

分组侧栏(滑动高亮浮层、徽标、可选的工作区行 / 搜索框 / 主操作按钮):

<script setup lang="ts">
import { ref } from 'vue'
import { SidebarNav } from '@udhold/udhold-ui/components/beautiful'

const active = ref('general')
const items = [
  { key: 'general', label: '通用' },
  { key: 'sync', label: '同步', section: '数据' },
  { key: 'backup', label: '备份', section: '数据', badge: '新' }
]
</script>

<template>
  <SidebarNav
    v-model:active="active"
    :items="items"
    workspace-title="当前空间"
    workspace-subtitle="my-workspace"
    new-label="新建"
    search-placeholder="过滤设置项…"
    embedded
    @new="onCreate"
    @search="onSearch"
  />
</template>

items 不带 section 的归入默认组「常用」;embedded 属性去掉卡片外壳,让导航融入你自己的容器。

取材与扩展

组件库的 components/beautiful/raw/ 目录还保留着约 20 个原始参考组件(对话页、思维链状态、任务行、差异对比表、筛选表格等),它们是未受控的源码参考——带演示数据、不能直接 import。想用其中某个:

  1. 从 raw/ 复制到你的插件工程(或提 PR 受控化进组件库);
  2. 剥离演示数据,改造成 props / emits 驱动;
  3. 样式里只消费设计令牌(缺失的令牌补到全局体系,不要在组件内写死色值)。

这套「受控化」流程与官方维护组件库的方式一致,改造后的组件在明暗主题下天然可用。

设计系统小结

到这里,令牌 → 主题 → 样式类 → 图标 → 组件的完整链路就走完了。回到你的插件:先把快速上手的工程骨架搭起来,遇到界面问题再回到对应章节查参考。祝开发顺利!