InputTags

InputTagsGitHub
一个显示交互式标签的输入元素。

用法

使用 v-model 指令来控制 InputTags 的值。

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" />
</template>

使用 default-value prop 在您不需要控制其状态时设置初始值。

Vue
<template>
  <UInputTags :default-value="['Vue']" />
</template>

占位符

使用 placeholder 属性设置占位文本。

<template>
  <UInputTags placeholder="Enter tags..." />
</template>

最大长度

使用 max-length 属性来设置标签允许的最大字符数。

<template>
  <UInputTags :max-length="4" />
</template>

颜色

使用 color 属性来更改 InputTags 获得焦点时的边框颜色。

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" color="neutral" highlight />
</template>
highlight 属性在此用于显示焦点状态。当发生验证错误时,它会在内部使用。

样式

使用 variant 属性来更改 InputTags 的外观。

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" variant="subtle" color="neutral" />
</template>

尺寸

使用 size 属性来调整 InputTags 的尺寸。

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" size="xl" />
</template>

Icon

使用 icon 属性在 InputTags 内显示一个 Icon

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" icon="i-lucide-search" size="md" variant="outline" />
</template>
使用 leadingtrailing 属性设置图标位置,或者使用 leading-icontrailing-icon 属性为每个位置设置不同的图标。

Avatar

使用 avatar 属性在 InputTags 内显示一个 Avatar

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags
    v-model="value"
    :avatar="{
      src: 'https://github.com/vuejs.png'
    }"
    size="md"
    variant="outline"
  />
</template>

删除图标

使用 delete-icon 属性来自定义标签中的删除 Icon。默认值为 i-lucide-x

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" delete-icon="i-lucide-trash" />
</template>
你可以在 app.config.ts 中的 ui.icons.close 键下全局自定义此图标。
你可以在 vite.config.ts 中的 ui.icons.close 键下全局自定义此图标。

加载中

使用 loading 属性在 InputTags 上显示加载图标。

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" loading />
</template>

加载图标

使用 loading-icon prop 来自定义加载图标。默认为 i-lucide-loader-circle

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" loading loading-icon="i-lucide-loader" />
</template>
你可以在 app.config.ts 中的 ui.icons.loading 键下全局自定义此图标。
你可以在 vite.config.ts 中的 ui.icons.loading 键下全局自定义此图标。

禁用

使用 disabled 属性禁用 InputTags。

Vue
<script setup lang="ts">
const value = ref(['Vue'])
</script>

<template>
  <UInputTags v-model="value" disabled />
</template>

示例

在 FormField 中

您可以在 FormField 组件中使用 InputTags 来显示标签、帮助文本、必填指示器等。

Vue
<script setup lang="ts">
const tags = ref(['Vue'])
</script>

<template>
  <UFormField label="Tags" required>
    <UInputTags v-model="tags" placeholder="Enter tags..." />
  </UFormField>
</template>

API

属性

属性默认值类型
as

'div'

any

此组件应渲染为的元素或组件。

placeholder

string

输入为空时的占位文本。

maxLength

number

允许的最大字符数。

color

'主要'

"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"

variant

'outline'

"outline" | "soft" | "subtle" | "ghost" | "none"

尺寸

'md'

"xs" | "sm" | "md" | "lg" | "xl"

autofocus

boolean

autofocusDelay

0

number

deleteIcon

appConfig.ui.icons.close

字符串 | 对象

用于删除标签的图标。

高亮

boolean

高亮环形颜色,如同焦点状态。

modelValue

null | AcceptableInputValue[]

标签输入的受控值。可以绑定为 v-model

defaultValue

AcceptableInputValue[]

要添加的标签的值。当您不需要控制标签输入的状态时使用。

addOnPaste

boolean

当设置为 true 时,允许粘贴时添加标签。与 delimiter 属性配合使用。

addOnTab

boolean

当设置为 true 时,允许在 tab 键按下时添加标签。

addOnBlur

boolean

当设置为 true 时,允许在输入框失去焦点时添加标签。

duplicate

boolean

当设置为 true 时,允许重复的标签。

disabled

boolean

当设置为 true 时,阻止用户与标签输入进行交互。

delimiter

string | RegExp

用于触发添加新标签的字符或正则表达式。也用于 @paste 事件中分割标签。

max

number

最大标签数量。

id

string

convertValue

(value: string): AcceptableInputValue

将输入值转换为所需的类型。当使用对象作为值并使用 TagsInputInput 时是必需的。

displayValue

(value: AcceptableInputValue): string

显示标签的值。当您想对值进行修改(例如添加后缀)或使用对象作为值时很有用。

name

string

字段的名称。作为名称/值对的一部分随其所属表单提交。

required

boolean

当为 true 时,表示用户必须在提交所属表单之前设置值。

图标

字符串 | 对象

根据 leadingtrailing 属性显示图标。

avatar

AvatarProps

在左侧显示头像。

前置

boolean

当为 true 时,图标将显示在左侧。

leadingIcon

字符串 | 对象

在左侧显示图标。

尾部

boolean

当为 true 时,图标将显示在右侧。

trailingIcon

字符串 | 对象

在右侧显示图标。

loading

boolean

当为 true 时,将显示加载图标。

loadingIcon

appConfig.ui.icons.loading

字符串 | 对象

loading prop 为 true 时显示的图标。

ui

{ root?: ClassNameValue; base?: ClassNameValue; leading?: ClassNameValue; leadingIcon?: ClassNameValue; leadingAvatar?: ClassNameValue; leadingAvatarSize?: ClassNameValue; trailing?: ClassNameValue; trailingIcon?: ClassNameValue; item?: ClassNameValue; itemText?: ClassNameValue; itemDelete?: ClassNameValue; itemDeleteIcon?: ClassNameValue; input?: ClassNameValue; }

插槽

插槽类型
前置

{}

default

{}

尾部

{}

item-text

{ item: AcceptableInputValue; index: number; }

item-delete

{ item: AcceptableInputValue; index: number; }

事件

事件类型
change

[event: Event]

blur

[event: FocusEvent]

focus

[event: FocusEvent]

update:modelValue

[payload: AcceptableInputValue]

invalid

[payload: AcceptableInputValue]

addTag

[payload: AcceptableInputValue]

removeTag

[payload: AcceptableInputValue]

可访问属性

通过模板引用访问组件时,您可以使用以下内容:

名称类型
inputRefRef<InstanceType<typeof TagsInputInput> | null>

主题

app.config.ts
export default defineAppConfig({
  ui: {
    inputTags: {
      slots: {
        root: [
          'relative inline-flex items-center',
          'flex-wrap'
        ],
        base: [
          'rounded-md',
          'transition-colors'
        ],
        leading: 'absolute inset-y-0 start-0 flex items-center',
        leadingIcon: 'shrink-0 text-dimmed',
        leadingAvatar: 'shrink-0',
        leadingAvatarSize: '',
        trailing: 'absolute inset-y-0 end-0 flex items-center',
        trailingIcon: 'shrink-0 text-dimmed',
        item: 'px-1.5 py-0.5 rounded-sm font-medium inline-flex items-center gap-0.5 ring ring-inset ring-accented bg-elevated text-default data-disabled:cursor-not-allowed data-disabled:opacity-75 wrap-anywhere data-[state="active"]:bg-accented',
        itemText: '',
        itemDelete: [
          'inline-flex items-center rounded-xs text-dimmed hover:text-default hover:bg-accented/75 disabled:pointer-events-none',
          'transition-colors'
        ],
        itemDeleteIcon: 'shrink-0',
        input: 'flex-1 border-0 bg-transparent placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75'
      },
      variants: {
        fieldGroup: {
          horizontal: {
            root: 'group has-focus-visible:z-[1]',
            base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
          },
          vertical: {
            root: 'group has-focus-visible:z-[1]',
            base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
          }
        },
        size: {
          xs: {
            base: 'px-2 py-1 text-xs gap-1',
            leading: 'ps-2',
            trailing: 'pe-2',
            leadingIcon: 'size-4',
            leadingAvatarSize: '3xs',
            trailingIcon: 'size-4',
            item: 'text-[10px]/3',
            itemDeleteIcon: 'size-3'
          },
          sm: {
            base: 'px-2.5 py-1.5 text-xs gap-1.5',
            leading: 'ps-2.5',
            trailing: 'pe-2.5',
            leadingIcon: 'size-4',
            leadingAvatarSize: '3xs',
            trailingIcon: 'size-4',
            item: 'text-[10px]/3',
            itemDeleteIcon: 'size-3'
          },
          md: {
            base: 'px-2.5 py-1.5 text-sm gap-1.5',
            leading: 'ps-2.5',
            trailing: 'pe-2.5',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs',
            trailingIcon: 'size-5',
            item: 'text-xs',
            itemDeleteIcon: 'size-3.5'
          },
          lg: {
            base: 'px-3 py-2 text-sm gap-2',
            leading: 'ps-3',
            trailing: 'pe-3',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs',
            trailingIcon: 'size-5',
            item: 'text-xs',
            itemDeleteIcon: 'size-3.5'
          },
          xl: {
            base: 'px-3 py-2 text-base gap-2',
            leading: 'ps-3',
            trailing: 'pe-3',
            leadingIcon: 'size-6',
            leadingAvatarSize: 'xs',
            trailingIcon: 'size-6',
            item: 'text-sm',
            itemDeleteIcon: 'size-4'
          }
        },
        variant: {
          outline: 'text-highlighted bg-default ring ring-inset ring-accented',
          soft: 'text-highlighted bg-elevated/50 hover:bg-elevated has-focus:bg-elevated disabled:bg-elevated/50',
          subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
          ghost: 'text-highlighted bg-transparent hover:bg-elevated has-focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
          none: 'text-highlighted bg-transparent'
        },
        color: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        leading: {
          true: ''
        },
        trailing: {
          true: ''
        },
        loading: {
          true: ''
        },
        highlight: {
          true: ''
        },
        type: {
          file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none'
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'has-focus-visible:ring-2 has-focus-visible:ring-inset has-focus-visible:ring-primary'
        },
        {
          color: 'primary',
          highlight: true,
          class: 'ring ring-inset ring-primary'
        },
        {
          color: 'neutral',
          variant: [
            'outline',
            'subtle'
          ],
          class: 'has-focus-visible:ring-2 has-focus-visible:ring-inset has-focus-visible:ring-inverted'
        },
        {
          color: 'neutral',
          highlight: true,
          class: 'ring ring-inset ring-inverted'
        },
        {
          leading: true,
          size: 'xs',
          class: 'ps-7'
        },
        {
          leading: true,
          size: 'sm',
          class: 'ps-8'
        },
        {
          leading: true,
          size: 'md',
          class: 'ps-9'
        },
        {
          leading: true,
          size: 'lg',
          class: 'ps-10'
        },
        {
          leading: true,
          size: 'xl',
          class: 'ps-11'
        },
        {
          trailing: true,
          size: 'xs',
          class: 'pe-7'
        },
        {
          trailing: true,
          size: 'sm',
          class: 'pe-8'
        },
        {
          trailing: true,
          size: 'md',
          class: 'pe-9'
        },
        {
          trailing: true,
          size: 'lg',
          class: 'pe-10'
        },
        {
          trailing: true,
          size: 'xl',
          class: 'pe-11'
        },
        {
          loading: true,
          leading: true,
          class: {
            leadingIcon: 'animate-spin'
          }
        },
        {
          loading: true,
          leading: false,
          trailing: true,
          class: {
            trailingIcon: 'animate-spin'
          }
        }
      ],
      defaultVariants: {
        size: 'md',
        color: 'primary',
        variant: 'outline'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        inputTags: {
          slots: {
            root: [
              'relative inline-flex items-center',
              'flex-wrap'
            ],
            base: [
              'rounded-md',
              'transition-colors'
            ],
            leading: 'absolute inset-y-0 start-0 flex items-center',
            leadingIcon: 'shrink-0 text-dimmed',
            leadingAvatar: 'shrink-0',
            leadingAvatarSize: '',
            trailing: 'absolute inset-y-0 end-0 flex items-center',
            trailingIcon: 'shrink-0 text-dimmed',
            item: 'px-1.5 py-0.5 rounded-sm font-medium inline-flex items-center gap-0.5 ring ring-inset ring-accented bg-elevated text-default data-disabled:cursor-not-allowed data-disabled:opacity-75 wrap-anywhere data-[state="active"]:bg-accented',
            itemText: '',
            itemDelete: [
              'inline-flex items-center rounded-xs text-dimmed hover:text-default hover:bg-accented/75 disabled:pointer-events-none',
              'transition-colors'
            ],
            itemDeleteIcon: 'shrink-0',
            input: 'flex-1 border-0 bg-transparent placeholder:text-dimmed focus:outline-none disabled:cursor-not-allowed disabled:opacity-75'
          },
          variants: {
            fieldGroup: {
              horizontal: {
                root: 'group has-focus-visible:z-[1]',
                base: 'group-not-only:group-first:rounded-e-none group-not-only:group-last:rounded-s-none group-not-last:group-not-first:rounded-none'
              },
              vertical: {
                root: 'group has-focus-visible:z-[1]',
                base: 'group-not-only:group-first:rounded-b-none group-not-only:group-last:rounded-t-none group-not-last:group-not-first:rounded-none'
              }
            },
            size: {
              xs: {
                base: 'px-2 py-1 text-xs gap-1',
                leading: 'ps-2',
                trailing: 'pe-2',
                leadingIcon: 'size-4',
                leadingAvatarSize: '3xs',
                trailingIcon: 'size-4',
                item: 'text-[10px]/3',
                itemDeleteIcon: 'size-3'
              },
              sm: {
                base: 'px-2.5 py-1.5 text-xs gap-1.5',
                leading: 'ps-2.5',
                trailing: 'pe-2.5',
                leadingIcon: 'size-4',
                leadingAvatarSize: '3xs',
                trailingIcon: 'size-4',
                item: 'text-[10px]/3',
                itemDeleteIcon: 'size-3'
              },
              md: {
                base: 'px-2.5 py-1.5 text-sm gap-1.5',
                leading: 'ps-2.5',
                trailing: 'pe-2.5',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs',
                trailingIcon: 'size-5',
                item: 'text-xs',
                itemDeleteIcon: 'size-3.5'
              },
              lg: {
                base: 'px-3 py-2 text-sm gap-2',
                leading: 'ps-3',
                trailing: 'pe-3',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs',
                trailingIcon: 'size-5',
                item: 'text-xs',
                itemDeleteIcon: 'size-3.5'
              },
              xl: {
                base: 'px-3 py-2 text-base gap-2',
                leading: 'ps-3',
                trailing: 'pe-3',
                leadingIcon: 'size-6',
                leadingAvatarSize: 'xs',
                trailingIcon: 'size-6',
                item: 'text-sm',
                itemDeleteIcon: 'size-4'
              }
            },
            variant: {
              outline: 'text-highlighted bg-default ring ring-inset ring-accented',
              soft: 'text-highlighted bg-elevated/50 hover:bg-elevated has-focus:bg-elevated disabled:bg-elevated/50',
              subtle: 'text-highlighted bg-elevated ring ring-inset ring-accented',
              ghost: 'text-highlighted bg-transparent hover:bg-elevated has-focus:bg-elevated disabled:bg-transparent dark:disabled:bg-transparent',
              none: 'text-highlighted bg-transparent'
            },
            color: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            leading: {
              true: ''
            },
            trailing: {
              true: ''
            },
            loading: {
              true: ''
            },
            highlight: {
              true: ''
            },
            type: {
              file: 'file:me-1.5 file:font-medium file:text-muted file:outline-none'
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'has-focus-visible:ring-2 has-focus-visible:ring-inset has-focus-visible:ring-primary'
            },
            {
              color: 'primary',
              highlight: true,
              class: 'ring ring-inset ring-primary'
            },
            {
              color: 'neutral',
              variant: [
                'outline',
                'subtle'
              ],
              class: 'has-focus-visible:ring-2 has-focus-visible:ring-inset has-focus-visible:ring-inverted'
            },
            {
              color: 'neutral',
              highlight: true,
              class: 'ring ring-inset ring-inverted'
            },
            {
              leading: true,
              size: 'xs',
              class: 'ps-7'
            },
            {
              leading: true,
              size: 'sm',
              class: 'ps-8'
            },
            {
              leading: true,
              size: 'md',
              class: 'ps-9'
            },
            {
              leading: true,
              size: 'lg',
              class: 'ps-10'
            },
            {
              leading: true,
              size: 'xl',
              class: 'ps-11'
            },
            {
              trailing: true,
              size: 'xs',
              class: 'pe-7'
            },
            {
              trailing: true,
              size: 'sm',
              class: 'pe-8'
            },
            {
              trailing: true,
              size: 'md',
              class: 'pe-9'
            },
            {
              trailing: true,
              size: 'lg',
              class: 'pe-10'
            },
            {
              trailing: true,
              size: 'xl',
              class: 'pe-11'
            },
            {
              loading: true,
              leading: true,
              class: {
                leadingIcon: 'animate-spin'
              }
            },
            {
              loading: true,
              leading: false,
              trailing: true,
              class: {
                trailingIcon: 'animate-spin'
              }
            }
          ],
          defaultVariants: {
            size: 'md',
            color: 'primary',
            variant: 'outline'
          }
        }
      }
    })
  ]
})
为便于阅读,compoundVariants 中的某些颜色已省略。请在 GitHub 上查看源代码。

更新日志

3fd26— fix: 在 input 上添加 blur 和 focus 事件处理程序 (#5007)

61b60— 功能:允许传递组件而不是名称 (#4766)

a0963— feat!: 重命名 ButtonGroup (#4596)

5cb65— 特性:导入 @nuxt/ui-pro 组件

b96a1— feat: 添加 max-length 属性

8781a— fix: 扩展 emits 接口

54bb2— 功能:新组件 (#4261)