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

export function SensitiveInputDemo() {
  return (
    <div className="w-80">
      <SensitiveInput
        label="API Key"
        defaultValue="sk_live_abc123xyz789"
        onCopy={() => {}}
      />
    </div>
  );
}

Installation

Barrel

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

Granular

import { SensitiveInput } from "@cloudflare/kumo/components/sensitive-input";

Usage

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

export default function Example() {
  return <SensitiveInput label="Secret" defaultValue="my-secret-key" />;
}

Basic

By default, SensitiveInput renders only a reveal/mask toggle. The value is masked on blur and can be re-masked with Escape.

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

/** SensitiveInput with only the reveal toggle — no copy button. */
export function SensitiveInputBasicDemo() {
  return (
    <div className="w-80">
      <SensitiveInput label="Password" defaultValue="super-secret-password" />
    </div>
  );
}

With Copy Button

Pass onCopy to enable a copy-to-clipboard button. An anchored toast confirms the action.

<SensitiveInput
  label="API Key"
  defaultValue="sk_live_abc123xyz789"
  onCopy={() => {}}
/>
import { SensitiveInput } from "@cloudflare/kumo";

/** SensitiveInput with copy enabled via onCopy. */
export function SensitiveInputWithCopyDemo() {
  return (
    <div className="w-80">
      <SensitiveInput
        label="API Key"
        defaultValue="sk_live_abc123xyz789"
        readOnly
        onCopy={() => {}}
      />
    </div>
  );
}

Sizes

SensitiveInput supports multiple sizes to fit different contexts.

xs
sm
base
lg
import { SensitiveInput } from "@cloudflare/kumo";

export function SensitiveInputSizesDemo() {
  const sizes = ["xs", "sm", "base", "lg"] as const;
  return (
    <div className="flex flex-col gap-4">
      {sizes.map((size) => (
        <div key={size} className="flex items-center gap-2">
          <span className="w-12 text-sm text-kumo-subtle">{size}</span>
          <SensitiveInput
            label={`${size} size`}
            size={size}
            defaultValue="secret-api-key-123"
          />
        </div>
      ))}
    </div>
  );
}

Controlled

Use controlled mode for full control over the input value.

Current value: my-secret-value
import { useState } from "react";
import { SensitiveInput, Button } from "@cloudflare/kumo";

export function SensitiveInputControlledDemo() {
  const [value, setValue] = useState("my-secret-value");

  return (
    <div className="flex w-80 flex-col gap-4">
      <SensitiveInput
        label="Controlled Secret"
        value={value}
        onValueChange={setValue}
      />
      <div className="text-sm text-kumo-subtle">
        Current value: <code className="text-kumo-default">{value}</code>
      </div>
      <div className="flex gap-2">
        <Button
          onClick={() => setValue("new-secret-" + Date.now())}
          variant="primary"
          size="sm"
        >
          Change value
        </Button>
        <Button onClick={() => setValue("")} variant="secondary" size="sm">
          Clear
        </Button>
      </div>
    </div>
  );
}

States

Various input states including error, disabled, read-only, and with description.

This API key is not valid

Keep this value secure and don't share it

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

export function SensitiveInputStatesDemo() {
  return (
    <div className="flex w-80 flex-col gap-4">
      <SensitiveInput
        label="Error State"
        variant="error"
        defaultValue="invalid-key"
        error="This API key is not valid"
      />
      <SensitiveInput label="Disabled" defaultValue="cannot-edit" disabled />
      <SensitiveInput
        label="Read-only"
        defaultValue="view-only-secret-key"
        readOnly
      />
      <SensitiveInput
        label="With Description"
        defaultValue="my-secret-value"
        description="Keep this value secure and don't share it"
      />
    </div>
  );
}

Internationalization

Pass a labels prop to override the default English strings for tooltips, aria labels, and the copy confirmation toast.

<SensitiveInput
  label="Clé API"
  defaultValue="sk_live_abc123xyz789"
  onCopy={() => {}}
  labels={{
    copyAction: "Copier dans le presse-papiers",
    copyTooltip: "Copier",
    copiedToast: "Copié !",
    reveal: "Afficher la valeur",
    revealTooltip: "Afficher",
    hide: "Masquer la valeur",
    hideTooltip: "Masquer",
  }}
/>

API Reference

PropTypeDefaultDescription
altstring--
autoCompleteReact.HTMLInputAutoCompleteAttribute--
checkedboolean--
disabledboolean--
heightnumber | string--
liststring--
namestring--
placeholderstring--
readOnlyboolean--
requiredboolean--
widthnumber | string--
classNamestring--
idstring--
langstring--
titlestring--
childrenReactNode--
valuestring-Controlled value
size"xs" | "sm" | "base" | "lg""base"Size of the input.
variant"default" | "error""default"Style variant of the input.
labelReactNode-Label content for the input
labelTooltipReactNode-Tooltip content to display next to the label
descriptionReactNode-Helper text displayed below the input
errorstring | object-Error message or validation error object
labelsSensitiveInputLabels-Accessible labels for i18n. Pass translated strings to override English defaults.