20260720172840

This commit is contained in:
oneao committed 2026-07-20 17:28:47 +08:00
1 parent cda7f16d3a
commit 94207c77ff
3117 files changed
+201407 -1236

No files matched your search

@@ -0,0 +1,55 @@
# _semantic
## Source
```vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { SemanticPreview } from '@/components/semantic'
import { useComponentLocale } from '@/composables/use-locale'
import { locales } from '../locales'
const { t } = useComponentLocale(locales)
const semantics = computed(() => [
{ name: 'root', desc: t('root') },
{ name: 'prefix', desc: t('prefix') },
{ name: 'input', desc: t('input') },
{ name: 'placeholder', desc: t('placeholder') },
{ name: 'content', desc: t('content') },
{ name: 'clear', desc: t('clear') },
{ name: 'popup.root', desc: t('popup.root') },
{ name: 'popup.list', desc: t('popup.list') },
{ name: 'popup.listItem', desc: t('popup.listItem') },
])
const options = ref([
{ value: 'aojunhao123', label: 'aojunhao123' },
{ value: 'thinkasany', label: 'thinkasany' },
{ value: 'meet-student', label: 'meet-student' },
])
const divRef = ref<HTMLDivElement | null>(null)
</script>
<template>
<SemanticPreview
component-name="AutoComplete"
:semantics="semantics"
>
<template #default="{ classes }">
<div ref="divRef" :style="{ position: 'absolute', height: '200px' }">
<a-auto-complete
prefix="prefix"
:style="{ width: '200px' }"
:options="options"
placeholder="input here"
open
:get-popup-container="() => divRef!"
:classes="classes"
/>
</div>
</template>
</SemanticPreview>
</template>
```
@@ -0,0 +1,49 @@
# Customize clear button
## Description (en-US)
Customize clear button
## Source
```vue
<script setup lang="ts">
import { CloseSquareFilled } from '@antdv-next/icons'
import { h, ref } from 'vue'
const options = ref<{ value: string }[]>([])
const mockVal = (str: string, repeat = 1) => ({ value: str.repeat(repeat) })
function getPanelValue(searchText: string) {
return searchText
? [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)]
: []
}
function handleSearch(text: string) {
options.value = getPanelValue(text)
}
const clearIcon = h(CloseSquareFilled)
</script>
<template>
<a-flex vertical gap="middle">
<a-auto-complete
:options="options"
style="width: 200px"
:show-search="{ onSearch: handleSearch }"
placeholder="UnClearable"
:allow-clear="false"
/>
<a-auto-complete
:options="options"
style="width: 200px"
:show-search="{ onSearch: handleSearch }"
placeholder="Customized clear icon"
:allow-clear="{ clearIcon }"
/>
</a-flex>
</template>
```
@@ -0,0 +1,57 @@
# Basic Usage
## Description (en-US)
Basic Usage, set data source of autocomplete with `options` property.
## Source
```vue
<script setup lang="ts">
import { ref } from 'vue'
const value = ref('')
const options = ref<{ value: string }[]>([])
const anotherOptions = ref<{ value: string }[]>([])
const mockVal = (str: string, repeat = 1) => ({ value: str.repeat(repeat) })
function getPanelValue(searchText: string) {
return searchText
? [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)]
: []
}
function handleSearch(text: string) {
options.value = getPanelValue(text)
}
function handleAnotherSearch(text: string) {
anotherOptions.value = getPanelValue(text)
}
function handleSelect(data: string) {
console.log('onSelect', data)
}
</script>
<template>
<a-flex vertical gap="middle">
<a-auto-complete
:options="options"
style="width: 200px"
placeholder="input here"
:show-search="{ onSearch: handleSearch }"
@select="handleSelect"
/>
<a-auto-complete
v-model:value="value"
:options="anotherOptions"
style="width: 200px"
placeholder="control mode"
:show-search="{ onSearch: handleAnotherSearch }"
@select="handleSelect"
/>
</a-flex>
</template>
```
@@ -0,0 +1,120 @@
# Lookup-Patterns - Certain Category
## Description (en-US)
Demonstration of [Lookup Patterns: Certain Category](https://ant.design/docs/spec/reaction#lookup-patterns). Basic Usage, set options of autocomplete with `options` property.
## Source
```vue
<script setup lang="ts">
import { UserOutlined } from '@antdv-next/icons'
import { h } from 'vue'
function renderTitle(title: string) {
return h(
'div',
{
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
},
},
[
title,
h(
'a',
{
href: 'https://www.google.com/search?q=antd',
target: '_blank',
rel: 'noopener noreferrer',
},
'more',
),
],
)
}
function renderItem(title: string, count: number) {
return {
value: title,
label: h(
'div',
{
style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
},
},
[
title,
h(
'span',
{
style: {
display: 'inline-flex',
alignItems: 'center',
gap: '4px',
},
},
[h(UserOutlined), String(count)],
),
],
),
}
}
const options = [
{
label: renderTitle('Libraries'),
options: [renderItem('AntDesign', 10000), renderItem('AntDesign UI', 10600)],
},
{
label: renderTitle('Solutions'),
options: [renderItem('AntDesign UI FAQ', 60100), renderItem('AntDesign FAQ', 30010)],
},
{
label: renderTitle('Articles'),
options: [renderItem('AntDesign design language', 100000)],
},
]
</script>
<template>
<a-auto-complete
:classes="{ popup: { root: 'certain-category-search-dropdown' } }"
:popup-match-select-width="500"
style="width: 250px"
placeholder="input here"
:options="options"
>
<a-input-search size="large" placeholder="input here" />
</a-auto-complete>
</template>
<style>
.certain-category-search-dropdown .ant-select-item-group {
color: #666;
font-weight: bold;
}
.certain-category-search-dropdown .ant-select-item-group:not(:last-child) {
border-bottom: 1px solid #f6f6f6;
}
.certain-category-search-dropdown .ant-select-item-option-grouped {
padding-inline-start: 16px;
}
.certain-category-search-dropdown .ant-select-item-option.show-all {
text-align: center;
cursor: default;
}
.certain-category-search-dropdown .rc-virtual-list-holder {
max-height: 300px;
}
</style>
```
@@ -0,0 +1,45 @@
# Custom Input Component
## Description (en-US)
Customize Input Component
## Source
```vue
<script setup lang="ts">
import { ref } from 'vue'
const options = ref<{ value: string }[]>([])
function handleSearch(value: string) {
options.value = value
? [{ value }, { value: value + value }, { value: value + value + value }]
: []
}
function handleKeyPress(ev: KeyboardEvent) {
console.log('handleKeyPress', ev.key)
}
function handleSelect(value: string) {
console.log('onSelect', value)
}
</script>
<template>
<a-auto-complete
:options="options"
style="width: 220px"
:show-search="{ onSearch: handleSearch }"
@select="handleSelect"
>
<a-textarea
placeholder="input here"
class="custom"
style="height: 50px"
@keypress="handleKeyPress"
/>
</a-auto-complete>
</template>
```
@@ -0,0 +1,22 @@
# Disabled custom input debug
## Description (en-US)
Disabled custom input debug.
## Source
```vue
<script setup lang="ts">
</script>
<template>
<a-flex :gap="12" wrap>
<a-input disabled placeholder="Regular Input" />
<a-auto-complete disabled>
<a-textarea disabled />
</a-auto-complete>
<a-select disabled :options="[]" />
</a-flex>
</template>
```
@@ -0,0 +1,32 @@
# Non-case-sensitive AutoComplete
## Description (en-US)
A non-case-sensitive AutoComplete
## Source
```vue
<script setup lang="ts">
const options = [
{ value: 'Burns Bay Road' },
{ value: 'Downing Street' },
{ value: 'Wall Street' },
]
const showSearch = {
filterOption: (inputValue: string, option?: { value?: string }) => {
return (option?.value ?? '').toUpperCase().includes(inputValue.toUpperCase())
},
}
</script>
<template>
<a-auto-complete
style="width: 200px"
:options="options"
placeholder="try to type `b`"
:show-search="showSearch"
/>
</template>
```
@@ -0,0 +1,35 @@
# Customized Options
## Description (en-US)
You could set custom `Option` label
## Source
```vue
<script setup lang="ts">
import { ref } from 'vue'
const options = ref<{ label: string, value: string }[]>([])
function handleSearch(value: string) {
if (!value || value.includes('@')) {
options.value = []
return
}
options.value = ['gmail.com', '163.com', 'qq.com'].map(domain => ({
label: `${value}@${domain}`,
value: `${value}@${domain}`,
}))
}
</script>
<template>
<a-auto-complete
style="width: 200px"
placeholder="input here"
:show-search="{ onSearch: handleSearch }"
:options="options"
/>
</template>
```
@@ -0,0 +1,49 @@
# Status
## Description (en-US)
Add status to AutoComplete with `status`, which could be `error` or `warning`.
## Source
```vue
<script setup lang="ts">
import { ref } from 'vue'
const options = ref<{ value: string }[]>([])
const anotherOptions = ref<{ value: string }[]>([])
const mockVal = (str: string, repeat = 1) => ({ value: str.repeat(repeat) })
function getPanelValue(searchText: string) {
return searchText
? [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)]
: []
}
function handleSearch(text: string) {
options.value = getPanelValue(text)
}
function handleAnotherSearch(text: string) {
anotherOptions.value = getPanelValue(text)
}
</script>
<template>
<a-space direction="vertical" style="width: 100%">
<a-auto-complete
:options="options"
:show-search="{ onSearch: handleSearch }"
status="error"
style="width: 200px"
/>
<a-auto-complete
:options="anotherOptions"
:show-search="{ onSearch: handleAnotherSearch }"
status="warning"
style="width: 200px"
/>
</a-space>
</template>
```
@@ -0,0 +1,85 @@
# Custom semantic dom styling
## Description (en-US)
## Source
```vue
<script setup lang="ts">
import { ref } from 'vue'
const stylesObject = {
popup: {
root: {
borderWidth: '1px',
borderStyle: 'solid',
borderColor: '#1890ff',
},
list: {
backgroundColor: 'rgba(240, 240, 240, 0.85)',
},
listItem: {
color: '#272727',
},
},
}
function stylesFn({ props }: { props: { variant?: string } }) {
if (props.variant === 'filled') {
return {
popup: {
root: {
borderWidth: '1px',
borderStyle: 'solid',
borderColor: '#ccc',
},
list: {
backgroundColor: 'rgba(240, 240, 240, 0.85)',
},
listItem: {
color: '#272727',
},
},
}
}
return {}
}
const options = [
{ value: 'Burnaby' },
{ value: 'Seattle' },
{ value: 'Los Angeles' },
{ value: 'San Francisco' },
{ value: 'Meet student' },
]
const sharedProps = {
options,
classes: {
root: 'auto-complete-style-root',
},
style: { width: '200px' },
}
const value = ref('')
</script>
<template>
<a-flex vertical gap="middle">
<a-auto-complete v-model:value="value" v-bind="sharedProps" placeholder="object styles" :styles="stylesObject" />
<a-auto-complete
v-model:value="value"
v-bind="sharedProps"
placeholder="function styles"
:styles="stylesFn"
variant="filled"
/>
</a-flex>
</template>
<style>
.auto-complete-style-root {
border-radius: 4px;
}
</style>
```
@@ -0,0 +1,71 @@
# Lookup-Patterns - Uncertain Category
## Description (en-US)
Demonstration of [Lookup Patterns: Uncertain Category](https://ant.design/docs/spec/reaction#lookup-patterns).
## Source
```vue
<script setup lang="ts">
import { h, ref } from 'vue'
const getRandomInt = (max: number, min = 0) => Math.floor(Math.random() * (max - min + 1)) + min
function searchResult(query: string) {
return Array.from({ length: getRandomInt(5) }).map((_, idx) => {
const category = `${query}${idx}`
return {
value: category,
label: h(
'div',
{
style: {
display: 'flex',
justifyContent: 'space-between',
},
},
[
h('span', [
`Found ${query} on `,
h(
'a',
{
href: `https://s.taobao.com/search?q=${query}`,
target: '_blank',
rel: 'noopener noreferrer',
},
category,
),
]),
h('span', `${getRandomInt(200, 100)} results`),
],
),
}
})
}
const options = ref<{ value: string, label: any }[]>([])
function handleSearch(value: string) {
options.value = value ? searchResult(value) : []
}
function handleSelect(value: string) {
console.log('onSelect', value)
}
</script>
<template>
<a-auto-complete
:popup-match-select-width="252"
style="width: 300px"
:options="options"
placeholder="input here"
:show-search="{ onSearch: handleSearch }"
@select="handleSelect"
>
<a-input-search size="large" placeholder="input here" enter-button />
</a-auto-complete>
</template>
```
@@ -0,0 +1,67 @@
# Variants
## Description (en-US)
There are `outlined`, `filled`, `borderless`, and `underlined` variants to choose from.
## Source
```vue
<script setup lang="ts">
import { ref } from 'vue'
const options = ref<{ value: string }[]>([])
const mockVal = (str: string, repeat = 1) => ({ value: str.repeat(repeat) })
function getPanelValue(searchText: string) {
return searchText
? [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)]
: []
}
function handleSearch(text: string) {
options.value = getPanelValue(text)
}
function handleSelect(value: string) {
console.log('onSelect', value)
}
</script>
<template>
<a-flex vertical gap="middle">
<a-auto-complete
:options="options"
style="width: 200px"
placeholder="Outlined"
:show-search="{ onSearch: handleSearch }"
@select="handleSelect"
/>
<a-auto-complete
:options="options"
style="width: 200px"
placeholder="Filled"
:show-search="{ onSearch: handleSearch }"
variant="filled"
@select="handleSelect"
/>
<a-auto-complete
:options="options"
style="width: 200px"
placeholder="Borderless"
:show-search="{ onSearch: handleSearch }"
variant="borderless"
@select="handleSelect"
/>
<a-auto-complete
:options="options"
style="width: 200px"
placeholder="Underlined"
:show-search="{ onSearch: handleSearch }"
variant="underlined"
@select="handleSelect"
/>
</a-flex>
</template>
```
@@ -0,0 +1,106 @@
---
title: AutoComplete
description: Autocomplete function of input field.
---
## When To Use
- When you need an input box instead of a selector.
- When you need input suggestions or helping text.
The differences with Select are:
- AutoComplete is an input box with text hints, and users can type freely. The keyword is aiding **input**.
- Select is selecting among given choices. The keyword is **select**.
## Demos
| Demo | Path |
| --- | --- |
| Basic Usage | demo/basic.md |
| Customized Options | demo/options.md |
| Custom Input Component | demo/custom.md |
| Non-case-sensitive AutoComplete | demo/non-case-sensitive.md |
| Lookup-Patterns - Certain Category | demo/certain-category.md |
| Lookup-Patterns - Uncertain Category | demo/uncertain-category.md |
| Status | demo/status.md |
| Variants | demo/variant.md |
| Customize clear button | demo/allowClear.md |
| Custom semantic dom styling | demo/style-class.md |
| Disabled custom input debug | demo/disabled-custom-debug.md |
## API
### Props
Common props ref:[Common props](../../docs/vue/common-props.md)
| Property | Description | Type | Default | Version | [Global Config](../config-provider/docs.md#component-config) |
| --- | --- | --- | --- | --- | --- |
| allowClear | Show clear button | boolean \| &#123; clearIcon?: VueNode &#125; | false | - | × |
| backfill | If backfill selected item the input when using keyboard | boolean | false | - | × |
| defaultActiveFirstOption | Whether active first option by default | boolean | true | - | × |
| disabled | Whether disabled select | boolean | false | - | × |
| getPopupContainer | Parent node of the dropdown. Default to body, if you encountered positioning problems during scroll, try changing to the scrollable area and position relative to it | (triggerNode: HTMLElement) =&gt; HTMLElement | () =&gt; document.body | - | × |
| labelRender | Customize selected label render | (props: LabelInValueType) =&gt; VueNode | - | - | × |
| notFoundContent | Specify content to show when no result matches | VueNode | - | - | × |
| open | Controlled open state of dropdown | boolean | - | - | × |
| options | Select options. Will get better perf than jsx definition | &#123; label: VueNode; value: string &#125;[] | - | - | × |
| optionRender | Customize the rendering dropdown options | (option: FlattenOptionData&lt;BaseOptionType&gt;, info: &#123; index: number &#125;) =&gt; VueNode | - | - | × |
| placeholder | The placeholder of input | string | - | - | × |
| popupMatchSelectWidth | Determine whether the dropdown menu and the select input are the same width. Default set `min-width` same as input. Will ignore when value less than select width. `false` will disable virtual scroll | boolean \| number | true | - | × |
| popupRender | Customize dropdown content | (menu: VueNode) =&gt; VueNode | - | - | × |
| showSearch | Search configuration | boolean \| [SearchConfig](#showsearch) | true | - | × |
| size | The size of the input box | `large` \| `middle` \| `small` | - | - | × |
| status | Set validation status | `error` \| `warning` | - | - | × |
| value | Selected option, support `v-model:value` | string | - | - | × |
| variant | Variants of input | `outlined` \| `borderless` \| `filled` \| `underlined` | `outlined` | - | × |
| virtual | Disable virtual scroll when set to false | boolean | true | - | × |
### Events
| Event | Description | Type | Version |
| --- | --- | --- | --- |
| blur | Called when blur | (e: FocusEvent) =&gt; void | - |
| change | Called when selecting an option or changing input value | (value: string) =&gt; void | - |
| clear | Called when clear | () =&gt; void | - |
| focus | Called when focus | (e: FocusEvent) =&gt; void | - |
| inputKeydown | Called when key pressed | (e: KeyboardEvent) =&gt; void | - |
| openChange | Called when dropdown open | (open: boolean) =&gt; void | - |
| popupScroll | Called when dropdown scrolls | (e: UIEvent) =&gt; void | - |
| search | Called when searching items | (value: string) =&gt; void | - |
| select | Called when an option is selected, the params are option's value (or key) and option instance | (value: string, option: Option) =&gt; void | - |
### Slots
| Slot | Description | Type | Version |
| --- | --- | --- | --- |
| default | Customize input element, or provide `AutoComplete.Option` children | () =&gt; VueNode | - |
| labelRender | Customize selected label render | (props: LabelInValueType) =&gt; VueNode | - |
| notFoundContent | Specify content to show when no result matches | () =&gt; VueNode | - |
| optionRender | Customize the rendering dropdown options | (option: FlattenOptionData&lt;BaseOptionType&gt;, info: &#123; index: number &#125;) =&gt; VueNode | - |
| popupRender | Customize dropdown content | (menu: VueNode) =&gt; VueNode | - |
| prefix | The custom prefix | () =&gt; VueNode | - |
| suffixIcon | The custom suffix icon | () =&gt; VueNode | - |
## Types
### showSearch
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns true, the option will be included in the filtered set; Otherwise, it will be excluded | boolean \| (inputValue: string, option?: Option) =&gt; boolean | true | - |
| onSearch | Called when searching items | (value: string) =&gt; void | - | - |
## Semantic DOM
| _semantic | demo/_semantic.md |
## FAQ
### Why doesn't the text composition system work well with onSearch in controlled mode?
Please use `onChange` to manage control state. `onSearch` is used for searching input which is not the same as `onChange`. Besides, clicking on the option will not trigger the `onSearch` event.
Related issue: [#18230](https://github.com/ant-design/ant-design/issues/18230) [#17916](https://github.com/ant-design/ant-design/issues/17916)
### Why won't a controlled open AutoComplete display a drop-down menu when options are empty?
The AutoComplete component is essentially an extension of the Input form element. When the `options` property is empty, displaying empty text could mislead the user into believing the component is not operational, when in fact they are still able to input text. To avoid confusion, the `open` property will not display the drop-down menu when set to `true` and in combination with an empty `options` property. The `open` property must be used in conjunction with the `options` property.
@@ -0,0 +1,51 @@
# auto-complete Token
Use these variables through `theme.components.Select`. This document lists definitions only and does not include values.
This directory reuses the `Select` component theme configuration.
```vue
<a-config-provider
:theme="{
token: {
// Global token configuration
},
components: {
Select: {
// Token name: value
},
},
}"
>
...
</a-config-provider>
```
## Token List
| Token | Type | Description |
| --- | --- | --- |
| `zIndexPopup` | `number` | z-index of dropdown |
| `optionSelectedColor` | `string` | Text color when option is selected |
| `optionSelectedFontWeight` | `CSSProperties` | Font weight when option is selected |
| `optionSelectedBg` | `string` | Background color when option is selected |
| `optionActiveBg` | `string` | Background color when option is active |
| `optionPadding` | `CSSProperties` | Padding of option |
| `optionFontSize` | `number` | Font size of option |
| `optionLineHeight` | `CSSProperties` | Line height of option |
| `optionHeight` | `number` | Height of option |
| `selectorBg` | `string` | Background color of selector |
| `clearBg` | `string` | Background color of clear button |
| `singleItemHeightLG` | `number` | Height of single selected item with large size |
| `showArrowPaddingInlineEnd` | `number` | Inline end padding of arrow |
| `hoverBorderColor` | `string` | Hover border color |
| `activeBorderColor` | `string` | Active border color |
| `activeOutlineColor` | `string` | Active outline color |
| `multipleItemBg` | `string` | Background color of multiple tag |
| `multipleItemBorderColor` | `string` | Border color of multiple tag |
| `multipleItemHeight` | `number` | Height of multiple tag |
| `multipleItemHeightSM` | `number` | Height of multiple tag with small size |
| `multipleItemHeightLG` | `number` | Height of multiple tag with large size |
| `multipleSelectorBgDisabled` | `string` | Background color of multiple selector when disabled |
| `multipleItemColorDisabled` | `string` | Text color of multiple tag when disabled |
| `multipleItemBorderColorDisabled` | `string` | Border color of multiple tag when disabled |