We'll never share your email

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

export function InputBasicDemo() {
  return (
    <Input
      label="Email"
      placeholder="[email protected]"
      description="We'll never share your email"
    />
  );
}

安装

桶式导入

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

子路径导入

import { Input } from "@cloudflare/kumo/components/input";

用法

使用内置 Field(推荐)

使用 label 属性启用内置 Field 包装器,支持标签、描述和错误提示。

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

export default function Example() {
  return (
    <Input
      label="Email"
      placeholder="[email protected]"
      description="We'll never share your email"
    />
  );
}

裸 Input(自定义布局)

对于自定义表单布局,可在不带 label 的情况下使用 Input,但必须提供 aria-labelaria-labelledby 以保证无障碍访问。

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

export default function Example() {
  return <Input placeholder="Search..." aria-label="Search products" />;
}

示例

带标签与描述

label 属性启用内置 Field 包装器,并自动采用垂直布局(标签在输入框上方)。

3-20 characters, alphanumeric only

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

export function InputWithLabelDemo() {
  return (
    <Input
      label="Username"
      placeholder="Choose a username"
      description="3-20 characters, alphanumeric only"
    />
  );
}

带错误(字符串)

对于简单的错误提示,可将 error 以字符串形式传入。当 error 属性为真时, 会自动应用错误样式。

Please enter a valid email address
import { Input } from "@cloudflare/kumo";

export function InputErrorStringDemo() {
  return (
    <Input
      label="Email"
      placeholder="[email protected]"
      value="invalid-email"
      error="Please enter a valid email address"
    />
  );
}

带错误(校验对象)

可将 error 以包含 messagematch 的对象形式传入,用于 HTML5 校验。 当字段有效性匹配时显示错误。

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

export function InputErrorObjectDemo() {
  return (
    <Input
      label="Password"
      type="password"
      value="short"
      error={{
        message: "Password must be at least 8 characters",
        match: "tooShort",
      }}
      minLength={8}
    />
  );
}

Input 尺寸

四种尺寸可选:xssmbase(默认)、lg

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

export function InputSizesDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Input size="xs" label="Extra Small" placeholder="Extra small input" />
      <Input size="sm" label="Small" placeholder="Small input" />
      <Input label="Base" placeholder="Base input (default)" />
      <Input size="lg" label="Large" placeholder="Large input" />
    </div>
  );
}

禁用

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

export function InputDisabledDemo() {
  return <Input label="Disabled field" placeholder="Cannot edit" disabled />;
}

可选字段

设置 required={false} 会在标签后显示“(可选)”文本。

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

export function InputOptionalFieldDemo() {
  return (
    <Input
      label="Phone Number"
      required={false}
      placeholder="+1 (555) 000-0000"
    />
  );
}

带标签提示

使用 labelTooltip 添加一个信息图标,悬停时可显示更多上下文说明。

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

export function InputLabelTooltipDemo() {
  return (
    <Input
      label="API Key"
      labelTooltip="Find this in your dashboard under Settings > API Keys"
      placeholder="sk_live_..."
    />
  );
}

ReactNode 标签

label 属性接受 ReactNode,支持富文本格式。

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

export function InputReactNodeLabelDemo() {
  return (
    <Input
      label={
        <span>
          Email for <strong>billing</strong>
        </span>
      }
      required
      placeholder="[email protected]"
      type="email"
    />
  );
}

使用 onChange 受控

标准 React onChange 处理函数会接收到完整的事件对象。通过 e.target.value 获取值。

Uses e.target.value

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

/** Controlled input using `onChange` (native React event). */
export function InputControlledOnChangeDemo() {
  const [value, setValue] = useState("");
  return (
    <Input
      label="With onChange"
      placeholder="Type something..."
      description={value ? `Value: ${value}` : "Uses e.target.value"}
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}

使用 onValueChange 受控

onValueChange 是 Base UI 提供的便捷处理函数,让你直接拿到字符串值, 无需解包事件对象。SelectComboboxRadio.Group 也使用同样的模式。

Receives the value directly

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

/** Controlled input using `onValueChange` (Base UI convenience — gives you the string directly). */
export function InputControlledOnValueChangeDemo() {
  const [value, setValue] = useState("");
  return (
    <Input
      label="With onValueChange"
      placeholder="Type something..."
      description={value ? `Value: ${value}` : "Receives the value directly"}
      value={value}
      onValueChange={(v) => setValue(v)}
    />
  );
}

裸 Input(无标签)

不带 label 的 Input 会渲染为裸输入框,必须提供 aria-label 以保证无障碍访问。

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

export function InputBareDemo() {
  return <Input placeholder="Search..." aria-label="Search products" />;
}

无标签时的错误

即使没有可见的 label,错误信息和描述仍会渲染。可使用 aria-label 保持输入框的无障碍访问。

Please enter a valid hostname
Path must start with /
import { Input } from "@cloudflare/kumo";

/** Input without a visible label, showing error and description via `aria-label`. */
export function InputErrorWithoutLabelDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Input
        aria-label="Hostname"
        placeholder="example.com"
        value="not a host"
        error="Please enter a valid hostname"
      />
      <Input
        aria-label="Path"
        placeholder="/api/v1/users"
        value="missing-slash"
        error={{ message: "Path must start with /", match: true }}
      />
    </div>
  );
}

输入类型

支持所有 HTML input 类型:textemailpasswordnumbertelurl 等。

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

export function InputTypesDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Input type="email" label="Email" placeholder="[email protected]" />
      <Input type="password" label="Password" placeholder="••••••••" />
      <Input type="number" label="Age" placeholder="18" />
      <Input type="tel" label="Phone" placeholder="+1 (555) 000-0000" />
    </div>
  );
}

密码管理器覆盖层

在密码管理器可能误判为登录字段的非凭据输入框上设置 passwordManagerIgnore

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

/** Side-by-side comparison: Keeper shows its icon on the default input but not the ignored one. */
export function InputPasswordManagerIgnoreDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Input
        label="API Key (default)"
        type="password"
        placeholder="sk_live_..."
      />
      <Input
        label="API Key (passwordManagerIgnore)"
        type="password"
        placeholder="sk_live_..."
        passwordManagerIgnore
      />
    </div>
  );
}

API 参考

Input 接受所有标准 HTML input 属性,以及以下属性:

PropTypeDefaultDescription
labelReactNode-Label content for the input (enables Field wrapper) - can be a string or any React node
labelTooltipReactNode-Tooltip content to display next to the label via an info icon
descriptionReactNode-Helper text displayed below the input
errorstring | object-Error message or validation error object
passwordManagerIgnoreboolean-Suppress browser extension password manager overlays on non-credential inputs.
size"xs" | "sm" | "base" | "lg""base"Input size. - `"xs"` — Extra small for compact UIs - `"sm"` — Small for secondary fields - `"base"` — Default size - `"lg"` — Large for prominent fields
variant"default" | "error""default"Visual variant. - `"default"` — Standard input - `"error"` — Error state for validation failures

校验错误类型

error 以对象形式使用时,match 属性对应 HTML5 ValidityState 值:

匹配描述
valueMissing必填字段为空
typeMismatch值不符合类型(例如邮箱无效)
patternMismatch值不符合 pattern 属性
tooShort值短于 minLength
tooLong值长于 maxLength
rangeUnderflow值小于 min
rangeOverflow值大于 max
true始终显示错误(用于服务端校验)

无障碍

标签要求

Input 需要满足以下任一方式提供可访问名称:

  • label 属性(推荐)
  • 对于裸输入框,使用 placeholder + aria-label
  • 使用 aria-labelledby 进行自定义标签关联

开发环境下,缺少可访问名称会触发控制台警告。

错误关联

错误信息会通过 ARIA 属性自动关联到输入框,供屏幕阅读器播报。