Paste comma- or newline-separated email addresses.

import { useState } from "react";
import { TagInput } from "@cloudflare/kumo";

export function TagInputDemo() {
  const [recipients, setRecipients] = useState(["[email protected]"]);
  return (
    <TagInput
      label="Recipients"
      description="Paste comma- or newline-separated email addresses."
      placeholder="[email protected]"
      autoComplete="off"
      value={recipients}
      onValueChange={setRecipients}
      validateValue={(value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)}
    />
  );
}

安装

import { TagInput } from "@cloudflare/kumo";

用法

使用 value 配合 onValueChange 控制标签;非受控用法则使用 defaultValue。

const [tags, setTags] = useState<string[]>([]);

<TagInput
  label="Labels"
  value={tags}
  onValueChange={setTags}
  placeholder="Add a label"
/>

示例

不限值

frontendpriority

Accepts any non-empty value.

import { TagInput } from "@cloudflare/kumo";

export function TagInputUnrestrictedDemo() {
  return (
    <TagInput
      defaultValue={["frontend", "priority"]}
      label="Labels"
      description="Accepts any non-empty value."
      placeholder="Add a label"
    />
  );
}

最大数量

alpha

A maximum of three groups.

import { TagInput } from "@cloudflare/kumo";

export function TagInputLimitedDemo() {
  return (
    <TagInput
      defaultValue={["alpha"]}
      label="Access groups"
      maxValues={3}
      description="A maximum of three groups."
      placeholder="Type a group name"
    />
  );
}

表单

设置 name,即可将每个标签作为独立的表单值提交,使 FormData.getAll(name) 返回所有标签。当焦点离开输入框时,仍留在输入框中的文本会转为一个标签,因此点击提交按钮时也会包含它。只要至少有一个标签,required 即可通过校验。

Add at least one topic, then submit.

import { useState } from "react";
import { Button, TagInput } from "@cloudflare/kumo";

/** Each tag is submitted as its own form value, and `required` follows the tags. */
export function TagInputFormDemo() {
  const [submitted, setSubmitted] = useState<string[] | null>(null);

  return (
    <form
      className="flex w-full max-w-md flex-col gap-3"
      onSubmit={(event) => {
        event.preventDefault();
        const data = new FormData(event.currentTarget);
        setSubmitted(data.getAll("topics").map(String));
      }}
    >
      <TagInput
        name="topics"
        required
        label="Topics"
        description="Add at least one topic, then submit."
        placeholder="Add a topic"
      />
      <div className="flex items-center gap-3">
        <Button type="submit" variant="primary">
          Submit
        </Button>
        {submitted ? (
          <code className="text-sm text-kumo-subtle">
            topics: {JSON.stringify(submitted)}
          </code>
        ) : null}
      </div>
    </form>
  );
}

只读

readOnly 会显示标签并保持输入框可聚焦,但无法添加或移除标签。与原生只读输入框一样,即使设置了 required,它也会被表单校验跳过。

billingdnsworkers

Managed by your organization's administrator.

import { TagInput } from "@cloudflare/kumo";

export function TagInputReadOnlyDemo() {
  return (
    <TagInput
      readOnly
      defaultValue={["billing", "dns", "workers"]}
      label="Assigned teams"
      description="Managed by your organization's administrator."
    />
  );
}

本地化

uno
import { TagInput } from "@cloudflare/kumo";

export function TagInputLocalizationDemo() {
  return (
    <TagInput
      defaultValue={["uno"]}
      label="Etiquetas"
      labels={{
        input: "Agregar etiqueta",
        removeValue: (value) => `Eliminar ${value}`,
        invalidValue: (value) => `${value} no es valido.`,
        maxValuesReached: (maxValues) => `Maximo de ${maxValues} etiquetas.`,
      }}
      maxValues={3}
      placeholder="Agregar una etiqueta"
    />
  );
}

行为

按 Enter、逗号或 Tab 即可创建标签。失焦时也会提交当前值。粘贴以逗号或换行分隔的文本时,会将其插入到光标处的当前文本中,然后同步创建每个值。粘贴不含分隔符的文本时,行为与普通粘贴相同。重复值会被忽略。

本地化

通过 labels 可以翻译 TagInput 生成的所有文本:回退输入名称、标签移除操作、无效值提示和达到最大数量提示。

<TagInput
  label="Etiquetas"
  labels={{
    input: "Agregar etiqueta",
    removeValue: (value) => `Eliminar ${value}`,
    invalidValue: (value) => `${value} no es valido.`,
    maxValuesReached: (maxValues) => `Maximo de ${maxValues} etiquetas.`,
  }}
/>

API 参考

PropTypeDefaultDescription
altstring--
autoCompleteReact.HTMLInputAutoCompleteAttribute--
checkedboolean--
heightnumber | string--
liststring--
namestring-

在该名称下将每个被接受的标签作为独立的表单值提交。

placeholderstring--
readOnlyboolean-

阻止添加或移除标签,同时保持输入框可聚焦。

requiredboolean-

要求至少有一个被接受的标签才能通过原生表单校验。与原生输入框一样,readOnly 的 TagInput 会被校验跳过。

typeReact.HTMLInputTypeAttribute--
widthnumber | string--
classNamestring--
idstring--
langstring--
titlestring--
childrenReactNode--
valuestring[]--
validateValueobject--
maxValuesnumber--
labelsTagInputLabels-

生成的输入、操作和验证文本的翻译标签。

labelReactNode--
labelTooltipReactNode--
descriptionReactNode--
errorstring | object--
variant"default" | "error""default"-
disabledboolean--