@cloudflare/kumo
Press Enter or Space to reveal.Value hidden
import { SensitiveInput } from "@cloudflare/kumo";

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

Sizes

SensitiveInput supports multiple sizes to fit different contexts.

xs
Press Enter or Space to reveal.Value hidden
sm
Press Enter or Space to reveal.Value hidden
base
Press Enter or Space to reveal.Value hidden
lg
Press Enter or Space to reveal.Value hidden
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.

Press Enter or Space to reveal.Value hidden
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.

Press Enter or Space to reveal.Value hidden
This API key is not valid
Press Enter or Space to reveal.Value hidden
Press Enter or Space to reveal.Value hidden
Press Enter or Space to reveal.Value hidden

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>
  );
}

Accessibility and localization

SensitiveInput uses native buttons for revealing, hiding, and copying the value. Provide a visible label, aria-label, or aria-labelledby so assistive technologies can identify the sensitive value. SensitiveInput does not add a generic fallback field name; missing names warn in development. Use aria-labelledby when the label is rich content that should stay associated with the reveal and hide controls.

Use the labels prop to localize secondary controls and statuses: reveal/hide button actions, copy button text, masked-state helper text, and live-region status messages. These English defaults are overrideable and do not replace the field’s required accessible name.

Pressione Enter ou Espaço para revelar.Valor oculto
import { SensitiveInput } from "@cloudflare/kumo";

export function SensitiveInputLocalizationDemo() {
  return (
    <div className="w-80">
      <SensitiveInput
        label="Chave de API"
        defaultValue="sk_live_abc123xyz789"
        labels={{
          clickToReveal: "Clique para revelar",
          revealValue: "Revelar valor",
          hideValue: "Ocultar valor",
          copy: "Copiar",
          copyToClipboard: "Copiar para a área de transferência",
          copied: "Copiado",
          valueRevealed: "Valor revelado",
          valueHidden: "Valor oculto",
          copiedToClipboard: "Copiado para a área de transferência",
          revealInstruction: "Pressione Enter ou Espaço para revelar.",
        }}
      />
    </div>
  );
}
<SensitiveInput
  label="Chave de API"
  defaultValue="sk_live_abc123xyz789"
  labels={{
    clickToReveal: "Clique para revelar",
    revealValue: "Revelar valor",
    hideValue: "Ocultar valor",
    copy: "Copiar",
    copyToClipboard: "Copiar para a área de transferência",
    copied: "Copiado",
    valueRevealed: "Valor revelado",
    valueHidden: "Valor oculto",
    copiedToClipboard: "Copiado para a área de transferência",
    revealInstruction: "Pressione Enter ou Espaço para revelar.",
  }}
/>
<span id="token-label">
  Production <strong>API token</strong>
</span>
<SensitiveInput aria-labelledby="token-label" defaultValue="sk_live_abc123" />

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. - `"xs"` — Extra small for compact UIs - `"sm"` — Small for secondary fields - `"base"` — Default input size - `"lg"` — Large for prominent fields
variant"default" | "error""default"Style variant of the input. - `"default"` — Default input appearance - `"error"` — Error state for validation failures
labelReactNode-Label content for the input (enables Field wrapper and sets masked state label) - 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
labelsSensitiveInputLabels-Localizable secondary control labels and live-region status text.