跳至内容

组合框

从具有完整键盘支持的建议值列表中选择。
vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxAnchor, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxRoot, ComboboxSeparator, ComboboxTrigger, ComboboxViewport } from 'radix-vue'
import { Icon } from '@iconify/vue'

const v = ref('')
const options = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>

<template>
  <ComboboxRoot
    v-model="v"
    class="relative"
  >
    <ComboboxAnchor class="min-w-[160px] inline-flex items-center justify-between rounded px-[15px] text-[13px] leading-none h-[35px] gap-[5px] bg-white text-grass11 shadow-[0_2px_10px] shadow-black/10 hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black data-[placeholder]:text-grass9 outline-none">
      <ComboboxInput
        class="!bg-transparent outline-none text-grass11 h-full selection:bg-grass5 placeholder-mauve8"
        placeholder="Placeholder..."
      />
      <ComboboxTrigger>
        <Icon
          icon="radix-icons:chevron-down"
          class="h-4 w-4 text-grass11"
        />
      </ComboboxTrigger>
    </ComboboxAnchor>

    <ComboboxContent class="absolute z-10 w-full mt-2 min-w-[160px] bg-white overflow-hidden rounded shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade">
      <ComboboxViewport class="p-[5px]">
        <ComboboxEmpty class="text-mauve8 text-xs font-medium text-center py-2" />

        <ComboboxGroup>
          <ComboboxLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
            Fruits
          </ComboboxLabel>

          <ComboboxItem
            v-for="(option, index) in options"
            :key="index"
            class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass9 data-[highlighted]:text-grass1"
            :value="option"
          >
            <ComboboxItemIndicator
              class="absolute left-0 w-[25px] inline-flex items-center justify-center"
            >
              <Icon icon="radix-icons:check" />
            </ComboboxItemIndicator>
            <span>
              {{ option }}
            </span>
          </ComboboxItem>
          <ComboboxSeparator class="h-[1px] bg-grass6 m-[5px]" />
        </ComboboxGroup>

        <ComboboxGroup>
          <ComboboxLabel
            class="px-[25px] text-xs leading-[25px] text-mauve11"
          >
            Vegetables
          </ComboboxLabel>
          <ComboboxItem
            v-for="(option, index) in vegetables"
            :key="index"
            class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass9 data-[highlighted]:text-grass1"
            :value="option"
          >
            <ComboboxItemIndicator
              class="absolute left-0 w-[25px] inline-flex items-center justify-center"
            >
              <Icon icon="radix-icons:check" />
            </ComboboxItemIndicator>
            <span>
              {{ option }}
            </span>
          </ComboboxItem>
        </ComboboxGroup>
      </ComboboxViewport>
    </ComboboxContent>
  </ComboboxRoot>
</template>

特点

  • 可以是受控的或不受控的。
  • 提供 2 种定位模式。
  • 支持项目、标签、项目组。
  • 焦点完全管理。
  • 完整的键盘导航。
  • 支持自定义占位符。
  • 支持从右到左方向。

安装

从命令行安装组件。

sh
$ npm add radix-vue

解剖学

导入所有部分并将它们拼凑在一起。

vue
<script setup lang="ts">
import {
  ComboboxAnchor,
  ComboboxArrow,
  ComboboxCancel,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxItemIndicator,
  ComboboxLabel,
  ComboboxPortal,
  ComboboxRoot,
  ComboboxSeparator,
  ComboboxTrigger,
  ComboboxViewport,
} from 'radix-vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxAnchor>
      <ComboboxInput />
      <ComboboxTrigger />
      <ComboboxCancel />
    </ComboboxAnchor>

    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxViewport>
          <ComboboxEmpty />

          <ComboboxItem>
            <ComboboxItemIndicator />
          </ComboboxItem>

          <ComboboxGroup>
            <ComboboxLabel />
            <ComboboxItem>
              <ComboboxItemIndicator />
            </ComboboxItem>
          </ComboboxGroup>
          <ComboboxSeparator />
        </ComboboxViewport>

        <ComboboxArrow />
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

API 参考

包含组合框的所有部分

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

defaultOpen
布尔值

组合框在最初渲染时的打开状态。
当您不需要控制其打开状态时使用。

defaultValue
AcceptableValue | AcceptableValue[]

组合框在最初渲染时的值。当您不需要控制组合框的状态时使用

dir
'ltr' | 'rtl'

组合框适用的阅读方向。
如果省略,则从ConfigProvider全局继承或假设 LTR(从左到右)阅读模式。

disabled
布尔值

true时,阻止用户与组合框交互

displayValue
((val: AcceptableValue) => string)

所选项目的输入显示值。不适用于multiple

filterFunction
((val: string[] | number[] | false[] | true[] | Record<string, any>[], term: string) => string[] | number[] | false[] | true[] | Record<string, any>[])

用于过滤ComboboxItem的自定义过滤函数。

modelValue
AcceptableValue | AcceptableValue[]

组合框的受控值。可以使用v-model绑定。

multiple
布尔值

是否可以选择多个选项。

name
字符串

组合框的名称。作为名称/值对的一部分,与拥有它的表单一起提交。

open
布尔值

组合框的受控打开状态。可以使用v-model:open绑定。

resetSearchTermOnBlur
真的
布尔值

组合框输入失焦时是否重置 searchTerm

searchTerm
字符串

组合框的受控搜索词。可以使用 v-model:searchTerm 绑定。

selectedValue
AcceptableValue

组合框当前突出显示的值。可以使用v-model:selectedValue绑定。

发射有效载荷
update:modelValue
[value: AcceptableValue]

值更改时调用的事件处理程序。

update:open
[value: 布尔值]

组合框的打开状态更改时调用的事件处理程序。

update:searchTerm
[value: 字符串]

组合框的 searchTerm 更改时调用的事件处理程序。

update:selectedValue
[value: AcceptableValue]

组合框的突出显示值更改时调用的事件处理程序

插槽 (默认)有效载荷
open
布尔值

当前打开状态

modelValue
AcceptableValue | AcceptableValue[]

当前活动值

锚点

如果将ComboboxContent的 position 设置为popper,则用作锚点。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

输入

用于搜索组合框项目的输入组件。

道具默认类型
as
'输入'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

autoFocus
布尔值

在挂载时将焦点设置到元素上。

disabled
布尔值

true时,阻止用户与项目交互

type
'文本'
字符串

本机输入类型

触发器

用于切换组合框内容的按钮。

道具默认类型
as
'按钮'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

disabled
布尔值

true时,阻止用户与项目交互

数据属性价值
[data-state]"打开" | "关闭"
[data-disabled]禁用时出现

取消

用于清除搜索词的按钮。

道具默认类型
as
'按钮'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

当没有项目匹配查询时显示。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

传送门

使用时,会将内容部分传送到body中。

您需要将ComboboxContentposition设置为popper,以确保位置的自动计算类似于PopoverDropdownMenu

道具默认类型
disabled
布尔值

禁用传送门并内联渲染组件

参考

forceMount
布尔值

用于在需要更多控制时强制挂载。当使用 Vue 动画库控制动画时很有用。

to
字符串 | HTMLElement

Vue 原生传送门组件属性:to

参考

内容

组合框打开时弹出的组件。

道具默认类型
对齐
'开始' | '中心' | '结束'

相对于触发器的首选对齐方式。在发生冲突时可能会更改。

alignOffset
号码

startend对齐选项的像素偏移。

arrowPadding
号码

箭头与内容边缘之间的填充。如果您的内容具有边框半径,这将防止它溢出角。

as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

avoidCollisions
布尔值

true时,会覆盖侧面和对齐首选项以防止与边界边缘发生冲突。

bodyLock
布尔值

文档.body 将被锁定,并且滚动将被禁用。

collisionBoundary
元素 | (元素 | 空)[] | 空

用作碰撞边界的元素。默认情况下,这是视窗,但您可以提供要包含在此检查中的其他元素。

collisionPadding
数字 | 部分<记录<'顶部' | '右侧' | '底部' | '左侧', 数字>>

从边界边缘开始,发生碰撞检测的像素距离。接受一个数字(所有侧面的相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。

disableOutsidePointerEvents
布尔值

true时,将禁用DismissableLayer外部元素上的悬停/焦点/点击交互。用户需要在外部元素上双击才能与它们交互:一次关闭DismissableLayer,另一次触发元素。

可关闭
布尔值

允许组件成为可关闭层。

forceMount
布尔值

用于在需要更多控制时强制挂载。当使用 Vue 动画库控制动画时很有用。

hideWhenDetached
布尔值

当触发器完全被遮挡时是否隐藏内容。

位置
'内联' | 'popper'

要使用的定位模式,
inline 是默认值,您可以使用 CSS 控制位置。
popper 以与我们的其他基元相同的方式定位内容,例如PopoverDropdownMenu

prioritizePosition
布尔值

强制内容在视窗内定位。

可能会与参考元素重叠,这可能不是想要的。

'顶部' | '右侧' | '底部' | '左侧'

打开时渲染的触发器首选侧。当发生冲突并启用 avoidCollisions 时将被反转。

sideOffset
号码

与触发器之间的像素距离。

粘性
'部分' | '总是'

对齐轴上的粘性行为。部分将在触发器至少部分在边界内时将内容保留在边界内,而“总是”将始终将内容保留在边界内。

updatePositionStrategy
'总是' | '优化'

在每个动画帧更新浮动元素位置的策略。

发射有效载荷
escapeKeyDown
[事件: KeyboardEvent]

按下 Escape 键时调用的事件处理程序。可以阻止。

focusOutside
[事件: FocusOutsideEvent]

焦点移出 DismissableLayer 时调用的事件处理程序。可以阻止。

interactOutside
[事件: PointerDownOutsideEvent | FocusOutsideEvent]

DismissableLayer 外部发生交互时调用的事件处理程序。具体来说,当 pointerdown 事件发生在外部或焦点移出其外部时。可以阻止。

pointerDownOutside
[事件: PointerDownOutsideEvent]

pointerdown 事件发生在 DismissableLayer 外部时调用的事件处理程序。可以阻止。

数据属性价值
[data-state]"打开" | "关闭"
[data-side]"left" | "right" | "bottom" | "top"
[data-align]"start" | "end" | "center"
CSS 变量描述
--radix-combobox-content-transform-origin
从内容和箭头位置/偏移量计算出的 transform-origin。仅在 position="popper" 时存在。
--radix-combobox-content-available-width
触发器和边界边缘之间的剩余宽度。仅在 position="popper" 时存在。
--radix-combobox-content-available-height
触发器和边界边缘之间的剩余高度。仅在 position="popper" 时存在。
--radix-combobox-trigger-width
触发器的宽度。仅在 position="popper" 时存在。
--radix-combobox-trigger-height
触发器的高度。仅在 position="popper" 时存在。

视窗

包含所有项目的滚动视窗。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

nonce
字符串

nonce 属性添加到样式标签,可供内容安全策略使用。
如果省略,将从 ConfigProvider 中全局继承。

项目

包含下拉框项目的组件。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

disabled
布尔值

当为 true 时,阻止用户与项目交互。

value*
AcceptableValue

使用 name 提交时作为数据给定的值。

发射有效载荷
select
[事件: SelectEvent<AcceptableValue>]

选择项目时调用的事件处理程序。
可以通过调用 event.preventDefault 来阻止它。

数据属性价值
[data-state]"checked" | "unchecked"
[data-highlighted]高亮显示时存在
[data-disabled]禁用时出现

项目指示器

在项目被选中时渲染。你可以直接为这个元素设置样式,或者你可以将它用作包装器,将一个图标放在里面,或者两者兼而有之。

道具默认类型
as
'span'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

用于对多个项目进行分组。与 ComboboxLabel 结合使用,以确保通过自动标记实现良好的可访问性。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

标签

用于渲染组的标签。它不能使用箭头键获得焦点。

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

for
字符串

分隔符

用于在下拉框中视觉上分隔项目

道具默认类型
as
'div'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

箭头

一个可选的箭头元素,用于与内容一起渲染。这可以用来帮助视觉上将触发器与 ComboboxContent 连接起来。必须在 ComboboxContent 内部渲染。仅在 position 设置为 popper 时可用。

道具默认类型
as
'svg'
AsTag | 组件

此组件应渲染的元素或组件。可以通过asChild覆盖

asChild
布尔值

将默认渲染的元素更改为作为子元素传递的元素,合并它们的属性和行为。

阅读我们的组合指南以了解更多详细信息。

高度
5
号码

箭头的像素高度。

宽度
10
号码

箭头的像素宽度。

示例

将对象绑定为值

与只能提供字符串作为值的原生 HTML 表单控件不同,radix-vue 也支持绑定复杂对象。

确保设置 displayValue 属性,以便在项目选择时设置输入值。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
</script>

<template>
  <ComboboxRoot
    v-model="selectedPeople"
    :display-value="(v) => v.name"
  >
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          v-for="person in people"
          :key="person.id"
          :value="person"
          :disabled="person.unavailable"
        >
          {{ person.name }}
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

选择多个值

Combobox 组件允许你选择多个值。你可以通过提供一个值数组而不是单个值来启用此功能。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref([people[0], people[1]])
</script>

<template>
  <ComboboxRoot
    v-model="selectedPeople"
    multiple
  >
    ...
  </ComboboxRoot>
</template>

自定义过滤

在内部,ComboboxRoot 将应用默认的 过滤器函数 来过滤相关的 ComboboxItem(仅在 modelValue 类型为 string 时应用)。

但是,可以使用两种不同的方法来替换此行为。

1. 提供 filter-function 属性。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])

function filterFunction(list: typeof people[number], searchTerm: string) {
  return list.filter((person) => {
    return person.name.toLowerCase().includes(searchTerm.toLowerCase())
  })
}
</script>

<template>
  <ComboboxRoot
    v-model="selectedPeople"
    :filter-function="filterFunction"
  >
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          v-for="person in people"
          :key="person.id"
          :value="person"
          :disabled="person.unavailable"
        >
          {{ person.name }}
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

2. 过滤后的 v-for 选项

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } from 'radix-vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
const searchTerm = ref('')

const filteredPeople = computed(() =>
  searchTerm.value === ''
    ? people
    : people.filter((person) => {
      return person.name.toLowerCase().includes(searchTerm.value.toLowerCase())
    })
)
</script>

<template>
  <ComboboxRoot
    v-model="selectedPeople"
    v-model:searchTerm="searchTerm"
  >
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          v-for="person in filteredPeople"
          :key="person.id"
          :value="person"
          :disabled="person.unavailable"
        >
          {{ person.name }}
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

自定义标签

默认情况下,Combobox 将使用输入内容作为屏幕阅读器的标签。如果你想要更详细地控制向辅助技术宣布的内容,请使用 Label 组件。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxInput, ComboboxRoot, Label } from 'radix-vue'
</script>

<template>
  <ComboboxRoot v-model="selectedPeople">
    <Label for="person">Person: </Label>
    <ComboboxInput
      id="person"
      placeholder="Select a person"
    />
    ...
  </ComboboxRoot>
</template>

包含禁用项目

你可以使用 data-disabled 属性为禁用项目添加特殊样式。

vue
<script setup lang="ts">
import { ref } from 'vue'
import {
  ComboboxContent,
  ComboboxInput,
  ComboboxItem,
  ComboboxPortal,
  ComboboxRoot,
} from 'radix-vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          class="ComboboxItem"
          disabled
        >
          ...
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
css
/* styles.css */
.ComboboxItem[data-disabled] {
  color: "gainsboro";
}

包含分隔符

使用 Separator 部分在项目之间添加分隔符。

vue
<script setup lang="ts">
import { ref } from 'vue'
import {
  ComboboxContent,
  ComboboxInput,
  ComboboxItem,
  ComboboxPortal,
  ComboboxRoot,
  ComboboxSeparator
} from 'radix-vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem></ComboboxItem>
        <ComboboxItem></ComboboxItem>
        <ComboboxItem></ComboboxItem>
        <ComboboxSeparator />
        <ComboboxItem></ComboboxItem>
        <ComboboxItem></ComboboxItem>
        <ComboboxItem></ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

包含分组项目

使用 GroupLabel 部分将项目分组在一个部分中。

vue
<script setup lang="ts">
import { ref } from 'vue'
import {
  ComboboxContent,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxLabel,
  ComboboxPortal,
  ComboboxRoot
} from 'radix-vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxGroup>
          <ComboboxLabel>Label</ComboboxLabel>
          <ComboboxItem></ComboboxItem>
          <ComboboxItem></ComboboxItem>
          <ComboboxItem></ComboboxItem>
        </ComboboxGroup>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

包含复杂项目

你可以在项目中使用自定义内容。

vue
<script setup lang="ts">
import { ref } from 'vue'
import {
  ComboboxContent,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxItemIndicator,
  ComboboxLabel,
  ComboboxPortal,
  ComboboxRoot
} from 'radix-vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem>
          <img src="">
          Adolfo Hess
          <ComboboxItemIndicator />
        </ComboboxItem>

      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

阻止选择行为

默认情况下,选择 ComboboxItem 将关闭内容,并使用提供的值更新 modelValue。你可以通过阻止默认的 @select.prevent 来阻止此行为。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxPortal, ComboboxRoot } from 'radix-vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem @select.prevent>
          Item A
        </ComboboxItem>

      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>

可访问性

遵循 下拉框 WAI-ARIA 设计模式

有关更多信息,请参阅 W3C 下拉框自动完成列表 示例。

键盘交互

描述
Enter
ComboboxItem 获得焦点时,选择获得焦点的项目。
ArrowDown
ComboboxInput 获得焦点时,打开下拉框内容。
当项目获得焦点时,将焦点移至下一个项目。
ArrowUp
ComboboxInput 获得焦点时,打开下拉框内容。
当项目获得焦点时,将焦点移至上一个项目。
Esc
关闭下拉框,并恢复 ComboboxInput 字段中的所选项目。

自定义 API

通过将基本部分抽象到自己的组件中来创建自己的 API。

命令菜单

下拉框可用于构建自己的命令菜单。

用法

vue
<script setup lang="ts">
import { Command, CommandItem } from './your-command'
</script>

<template>
  <Command>
    <CommandItem value="1">
      Item 1
    </CommandItem>
    <CommandItem value="2">
      Item 2
    </CommandItem>
    <CommandItem value="3">
      Item 3
    </CommandItem>
  </Command>
</template>

实现

ts
// your-command.ts
export { default as Command } from 'Command.vue'
export { default as CommandItem } from 'CommandItem.vue'
vue
<!-- Command.vue -->
<script setup lang="ts">
import { CheckIcon, ChevronDownIcon, ChevronUpIcon, } from '@radix-icons/vue'
import { ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxPortal, ComboboxRoot, useForwardPropsEmits } from 'radix-vue'
import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue'

const props = defineProps<ComboboxRootProps>()
const emits = defineEmits<ComboboxRootEmits>()

const forward = useForwardPropsEmits(props, emits)
</script>

<template>
  <ComboboxRoot
    v-bind="forward"
    :open="true"
    model-value=""
  >
    <ComboboxInput placeholder="Type a command or search..." />

    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxEmpty />
        <ComboboxViewport>
          <slot />
        </ComboboxViewport>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
vue
<!-- ComboboxItem.vue -->
<script setup lang="ts">
import { CheckIcon } from '@radix-icons/vue'
import { ComboboxItem, type ComboboxItemProps } from 'radix-vue'

const props = defineProps<ComboboxItemProps>()
</script>

<template>
  <ComboboxItem
    v-bind="props"
    @select.prevent
  >
    <slot />
  </ComboboxItem>
</template>