Preview Updated 2026-05-10

Tag input

Multi-tag input — Enter to add, Backspace to delete, paste to bulk-import.

Basic usage

v-model binds a string[]. Press Enter to commit a tag; with an empty input, Backspace removes the last tag; clicking the × on a tag also removes it.

背景
vuereact
<script setup lang="ts">
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const tags = ref<string[]>(['vue', 'react']);
</script>

<template>
  <CfTagInput v-model="tags" placeholder="输入后按回车添加" />
</template>
<script setup>
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const tags = ref<string[]>(['vue', 'react']);
</script>

<template>
  <CfTagInput v-model="tags" placeholder="输入后按回车添加" />
</template>
import { useState } from 'react';
import { CfTagInput } from '@chufix-design/react';

export default function Demo() {
const [tags, setTags] = useState<string[]>(['vue', 'react']);
return <CfTagInput value={tags} placeholder="Type and press Enter" onChange={setTags} />;
}
import { useState } from 'react';
import { CfTagInput } from '@chufix-design/react';

export default function Demo() {
const [tags, setTags] = useState<string[]>(['vue', 'react']);
return <CfTagInput value={tags} placeholder="Type and press Enter" onChange={setTags} />;
}

Tones

tone controls the tag background, mapping to Tag’s semantic colors one to one.

背景
neutral
accenthighlight
ok
warn
error
<script setup lang="ts">
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const a = ref<string[]>(['neutral']);
const b = ref<string[]>(['accent', 'highlight']);
const c = ref<string[]>(['ok']);
const d = ref<string[]>(['warn']);
const e = ref<string[]>(['error']);
</script>

<template>
  <div style="display:flex; flex-direction: column; gap: 8px;">
    <CfTagInput v-model="a" tone="neutral" placeholder="neutral" />
    <CfTagInput v-model="b" tone="accent" placeholder="accent" />
    <CfTagInput v-model="c" tone="success" placeholder="success" />
    <CfTagInput v-model="d" tone="warning" placeholder="warning" />
    <CfTagInput v-model="e" tone="danger" placeholder="danger" />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const a = ref<string[]>(['neutral']);
const b = ref<string[]>(['accent', 'highlight']);
const c = ref<string[]>(['ok']);
const d = ref<string[]>(['warn']);
const e = ref<string[]>(['error']);
</script>

<template>
  <div style="display:flex; flex-direction: column; gap: 8px;">
    <CfTagInput v-model="a" tone="neutral" placeholder="neutral" />
    <CfTagInput v-model="b" tone="accent" placeholder="accent" />
    <CfTagInput v-model="c" tone="success" placeholder="success" />
    <CfTagInput v-model="d" tone="warning" placeholder="warning" />
    <CfTagInput v-model="e" tone="danger" placeholder="danger" />
  </div>
</template>
<CfTagInput value={a} tone="neutral" onChange={setA} />
<CfTagInput value={b} tone="accent"  onChange={setB} />
<CfTagInput value={c} tone="success" onChange={setC} />
<CfTagInput value={d} tone="warning" onChange={setD} />
<CfTagInput value={e} tone="danger"  onChange={setE} />
<CfTagInput value={a} tone="neutral" onChange={setA} />
<CfTagInput value={b} tone="accent"  onChange={setB} />
<CfTagInput value={c} tone="success" onChange={setC} />
<CfTagInput value={d} tone="warning" onChange={setD} />
<CfTagInput value={e} tone="danger"  onChange={setE} />

Custom separators

separators is an array of key names; pressing any of them commits the current draft as a tag. Comma / space / Tab can all be added. Pasting splits on ,, \\n, and \\t.

背景
<script setup lang="ts">
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const tags = ref<string[]>([]);
</script>

<template>
  <CfTagInput
    v-model="tags"
    :separators="['Enter', ',', ' ']"
    placeholder="回车 / 逗号 / 空格 都能分隔"
  />
</template>
<script setup>
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const tags = ref<string[]>([]);
</script>

<template>
  <CfTagInput
    v-model="tags"
    :separators="['Enter', ',', ' ']"
    placeholder="回车 / 逗号 / 空格 都能分隔"
  />
</template>
<CfTagInput
value={tags}
separators={['Enter', ',', ' ']}
placeholder="Enter / comma / space all separate"
onChange={setTags}
/>
<CfTagInput
value={tags}
separators={['Enter', ',', ' ']}
placeholder="Enter / comma / space all separate"
onChange={setTags}
/>

Max count and validation

max caps the total count; validate is a function returning boolean — invalid entries are silently dropped.

背景
已添加 0 / 5;非法格式不会被加入。
<script setup lang="ts">
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const tags = ref<string[]>([]);

function isEmail(t: string) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);
}
</script>

<template>
  <div style="display:flex; flex-direction:column; gap:6px;">
    <CfTagInput
      v-model="tags"
      :max="5"
      :validate="isEmail"
      :separators="['Enter', ',', ' ']"
      placeholder="最多 5 个邮箱地址"
    />
    <small style="color: var(--fg-3); font-size: 12px;">
      已添加 {{ tags.length }} / 5;非法格式不会被加入。
    </small>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfTagInput } from '@chufix-design/vue';

const tags = ref<string[]>([]);

function isEmail(t) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);
}
</script>

<template>
  <div style="display:flex; flex-direction:column; gap:6px;">
    <CfTagInput
      v-model="tags"
      :max="5"
      :validate="isEmail"
      :separators="['Enter', ',', ' ']"
      placeholder="最多 5 个邮箱地址"
    />
    <small style="color: var(--fg-3); font-size: 12px;">
      已添加 {{ tags.length }} / 5;非法格式不会被加入。
    </small>
  </div>
</template>
import { useState } from 'react';
import { CfTagInput } from '@chufix-design/react';

const isEmail = (t: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);

export default function Demo() {
const [tags, setTags] = useState<string[]>([]);
return (
  <CfTagInput
    value={tags}
    max={5}
    validate={isEmail}
    separators={['Enter', ',', ' ']}
    placeholder="Up to 5 email addresses"
    onChange={setTags}
  />
);
}
import { useState } from 'react';
import { CfTagInput } from '@chufix-design/react';

const isEmail = (t) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);

export default function Demo() {
const [tags, setTags] = useState<string[]>([]);
return (
  <CfTagInput
    value={tags}
    max={5}
    validate={isEmail}
    separators={['Enter', ',', ' ']}
    placeholder="Up to 5 email addresses"
    onChange={setTags}
  />
);
}

API

PropTypeDefaultDescription
modelValue (Vue) / value (React)string[][]Current tag array
placeholderstring'Type and press Enter'Placeholder, shown only when empty
variant'outline' | 'filled' | 'ghost''outline'Visual mode
size'sm' | 'md' | 'lg''md'Size
tone'neutral' | 'accent' | 'success' | 'warning' | 'danger''neutral'Tag background
disabledbooleanfalseDisabled
errorbooleanfalseError state
maxnumberMaximum tag count
separatorsstring[]['Enter']Keys that commit, may include 'Enter', ',', ' ', 'Tab', or any single char
uniquebooleantrueDeduplicate; repeated entries are ignored
trimbooleantrueTrim before commit
validate(tag) => booleanEntries returning false are dropped

Events: update:modelValue / add / remove (React: onChange / onAdd / onRemove).

反馈与讨论

Tag input · Discussion

0
0 / 600
一键发送
正在加载评论...