Skip to content

Combobox 组合框 ​

新粗野主义风格的可搜索选择组件。通过 multiple 属性切换单选和多选模式。

预览 ​

Preview

加载状态

点击按钮触发 loading,列表底部显示 Spinner。

创建选项(单选)

输入无匹配项时显示「创建」选项,创建后关闭下拉。

创建选项(多选)

创建后不关闭下拉,可继续创建多项。

安装 ​

pnpm dlx brutx-vue@latest add combobox

用法 ​

单选模式 ​

vue
<script setup>
import { ref } from 'vue'
import { Combobox } from 'brutx-ui-vue'

const selected = ref(undefined)

const options = [
    { value: 'vue', label: 'Vue' },
    { value: 'react', label: 'React' },
    { value: 'angular', label: 'Angular' },
    { value: 'svelte', label: 'Svelte' },
]
</script>

<template>
    <Combobox
        v-model="selected"
        :options="options"
        placeholder="Select a framework..."
        search-placeholder="Search frameworks..."
    />
</template>

多选模式 ​

vue
<script setup>
import { ref } from 'vue'
import { Combobox } from 'brutx-ui-vue'

const selected = ref([])

const options = [
    { value: 'vue', label: 'Vue' },
    { value: 'react', label: 'React' },
    { value: 'angular', label: 'Angular' },
    { value: 'svelte', label: 'Svelte' },
]
</script>

<template>
    <Combobox
        v-model="selected"
        :options="options"
        multiple
        placeholder="Select frameworks..."
        :max-display="3"
    />
</template>

加载状态 ​

设置 loading 为 true 时,下拉列表底部显示 Spinner,适用于异步加载选项的场景。

vue
<script setup>
import { ref } from 'vue'
import { Combobox } from 'brutx-ui-vue'

const loading = ref(false)
const options = ref([])

async function handleOpen() {
    loading.value = true
    options.value = await fetchOptions()
    loading.value = false
}
</script>

<template>
    <Combobox v-model="selected" :options="options" :loading="loading" />
</template>

创建选项 ​

设置 creative 为 true 时,若搜索无匹配项且输入框非空,列表顶部显示「创建 '{query}'」选项(文本取自 locale combobox.create)。点击该项触发 create 事件,参数为去除首尾空格后的搜索文本(显示与事件参数均使用 trim 后的查询,避免创建出带脏空格的 value/label)。

  • Combobox(单选):创建后关闭下拉。
  • Combobox(multiple):创建后不关闭下拉,便于继续选择或创建多项。
vue
<script setup>
import { ref } from 'vue'
import { Combobox } from 'brutx-ui-vue'

const selected = ref(undefined)
const options = ref([
    { value: 'vue', label: 'Vue' },
    { value: 'react', label: 'React' },
])

function handleCreate(value) {
    options.value.push({ value: value.toLowerCase(), label: value })
    selected.value = value.toLowerCase()
}
</script>

<template>
    <Combobox
        v-model="selected"
        :options="options"
        creative
        @create="handleCreate"
    />
</template>

数据类型 ​

ts
interface ComboboxOption {
    value: string
    label: string
    disabled?: boolean
}

API 参考 ​

Combobox — 属性
名称类型默认值说明
options
必填
ComboboxOption[]
—
可供选择的选项列表;每项含字符串 value、显示 label 和可选 disabled。
详情

声明类型

ComboboxOption[]

关联类型

ComboboxOption
类型定义 — ComboboxOption
export interface ComboboxOption {
    value: string
    label: string
    disabled?: boolean
}

默认值详情

未声明默认值
—

来源

Combobox.vue:24

packages/ui/src/components/combobox/Combobox.vue

modelValue
string | string[] | undefined
undefined
当前选中的字符串值或值数组,通过 v-model 绑定;多选时使用字符串数组。
详情

声明类型

string | string[] | undefined

默认值详情

解析值
undefined

来源

Combobox.vue:25

packages/ui/src/components/combobox/Combobox.vue

multiple
boolean | undefined
false
启用多选模式后,用户可同时选择多个选项。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

Combobox.vue:26

packages/ui/src/components/combobox/Combobox.vue

open
boolean | undefined
undefined
下拉面板展开状态;传入后组件处于受控模式,父组件需回写 update:open 才能应用切换。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
undefined

来源

Combobox.vue:27

packages/ui/src/components/combobox/Combobox.vue

placeholder
string | undefined
undefined
触发器未选择内容时的占位文本;未提供时按单选或多选模式读取本地化文案。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

Combobox.vue:28

packages/ui/src/components/combobox/Combobox.vue

searchPlaceholder
string | undefined
undefined
下拉面板内搜索输入框的占位文本;未提供时读取本地化文案。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

Combobox.vue:29

packages/ui/src/components/combobox/Combobox.vue

emptyText
string | undefined
undefined
搜索没有匹配选项时显示的文本;未提供时读取本地化文案。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

Combobox.vue:30

packages/ui/src/components/combobox/Combobox.vue

disabled
boolean | undefined
false
禁用触发器以及选项交互。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

Combobox.vue:31

packages/ui/src/components/combobox/Combobox.vue

loading
boolean | undefined
false
显示加载状态,用于异步准备或刷新选项时反馈等待。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

Combobox.vue:32

packages/ui/src/components/combobox/Combobox.vue

creative
boolean | undefined
false
没有匹配项且搜索文本非空时显示创建选项;组件仅发出 create,不会自行写入 modelValue。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

Combobox.vue:33

packages/ui/src/components/combobox/Combobox.vue

maxDisplay
number | undefined
3
多选时触发器最多展示的选中标签数;超出部分汇总为数量提示。
详情

声明类型

number | undefined

默认值详情

解析值
3

来源

Combobox.vue:34

packages/ui/src/components/combobox/Combobox.vue

ariaLabel
string | undefined
undefined
设置组合框触发器的无障碍名称。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

Combobox.vue:35

packages/ui/src/components/combobox/Combobox.vue

class
string | undefined
undefined
追加到组合框根容器的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

Combobox.vue:36

packages/ui/src/components/combobox/Combobox.vue

iconSize
IconSize | undefined
"md"
设置触发器下拉指示图标的尺寸。
详情

声明类型

IconSize | undefined

字面量

  • "2xl"
  • "lg"
  • "md"
  • "sm"
  • "xl"
  • "xs"

关联类型

IconSize
类型定义 — IconSize
export type IconSize = NonNullable<VariantProps<typeof iconSizeVariants>['size']>

默认值详情

解析值
"md"

来源

Combobox.vue:37

packages/ui/src/components/combobox/Combobox.vue

Combobox — 事件
名称签名或类型说明
@update:modelValue
[value: string | string[] | undefined]
选择值变化时发出新值;多选模式发出字符串数组,单选再次选择当前项时发出 undefined。
详情

声明类型

[value: string | string[] | undefined]

来源

Combobox.vue

packages/ui/src/components/combobox/Combobox.vue

@update:open
[value: boolean]
下拉面板请求展开或关闭时发出目标布尔状态。
详情

声明类型

[value: boolean]

字面量

  • false
  • true

来源

Combobox.vue

packages/ui/src/components/combobox/Combobox.vue

@create
[value: string]
用户选择创建操作时发出去除首尾空白的搜索文本;新选项和值由调用方写入。
详情

声明类型

[value: string]

来源

Combobox.vue

packages/ui/src/components/combobox/Combobox.vue

Combobox — 暴露成员
名称签名或类型说明
searchQuery
string
当前搜索输入文本;面板关闭或单选完成后会清空。
详情

声明类型

string

来源

Combobox.vue:194

packages/ui/src/components/combobox/Combobox.vue

selectedValue
string | string[] | undefined
当前 modelValue 的只读计算值。
详情

声明类型

string | string[] | undefined

来源

Combobox.vue:195

packages/ui/src/components/combobox/Combobox.vue

focus
() => void | undefined
将键盘焦点移动到组合框触发器。
详情

声明类型

() => void | undefined

来源

Combobox.vue:196

packages/ui/src/components/combobox/Combobox.vue

open
WritableComputedRef<boolean, boolean>
可读写的下拉展开状态;设置为 true 可打开面板,受控模式仍需父组件回写更新。
详情

声明类型

WritableComputedRef<boolean, boolean>

字面量

  • false
  • true

来源

Combobox.vue

packages/ui/src/components/combobox/Combobox.vue

交互 ​

选项遵循 Neo-Brutalist 视觉语言:

  • 高亮上浮:鼠标悬停或键盘 ↑ / ↓ 导航聚焦选项时,选项向左上方偏移(-translate-x-0.5 -translate-y-0.5)并显示大阴影(shadow-brutal-lg),形成「浮起」效果。两种触发方式共享同一视觉反馈,确保键盘用户与鼠标用户获得一致体验。
  • 按下盖影:点击选项时向右下位移(--brutal-shadow-offset-*)并去除阴影,落回阴影位置形成「按压」反馈。

上浮样式由共享变体 brutalHighlightLift 提供,与 Select 选项的 brutalHoverLift 保持视觉一致;区别在于触发机制——Combobox 绑定 data-[highlighted=true](兼容键盘高亮),Select 绑定 hover:。

可访问性 ​

  • 键盘操作:支持 ↑ / ↓ 上下移动焦点,Enter 选中当前项,Escape 关闭下拉
  • ARIA 属性:通过 ariaLabel 属性提供无障碍标签

程序化控制 ​

通过 ref 获取组件实例后,可读取 API 参考中列出的状态,并调用焦点方法。

vue
<script setup>
import { ref } from 'vue'
import { Combobox } from 'brutx-ui-vue'

const comboboxRef = ref(null)

function openDropdown() {
    comboboxRef.value?.open = true
}
</script>

<template>
    <Combobox ref="comboboxRef" v-model="selected" :options="options" />
    <button @click="openDropdown">Open</button>
</template>

常见问题 ​

Q: 单选模式下再次点击已选中的选项为什么没有反应?

A: 在 Combobox 单选模式下,再次点击已选中的选项会取消选中(值变为 undefined)。这是设计行为,用于支持清除选择。如果不需要此行为,可以在父组件中监听 update:modelValue 事件,当值变为 undefined 时恢复为之前的值。

Q: 如何实现异步加载选项?

A: 将 loading 设为 true 显示加载状态,在数据加载完成后更新 options 并将 loading 设为 false。可以结合下拉展开事件来触发数据加载,避免一次性加载所有数据。

Q: creative 模式下创建的新选项如何持久化?

A: 组件本身不持久化创建的选项。需要在 create 事件的处理函数中手动将新选项添加到 options 数组中,并同步更新 modelValue。如需持久化存储,可在事件处理中调用后端接口或写入本地存储。

蛮力铸就。