Skip to content
Corsair UI
Browse the docs

ComponentsNo. 39 of 109

Password Input

Password field with a button that shows what was typed.

Installation

pnpm dlx shadcn@latest add @corsair-ui/password-input

No setup needed: the CLI finds @corsair-ui in the shadcn registry directory. The files land in your project as source: edit them like your own code. More in Installation.

Also adds
utilsbuttoninputinput-group
npm
@radix-ui/react-slotclass-variance-authorityclsxlucide-reacttailwind-merge

Examples

Default

New password

At least 12 characters. A passphrase works well.

Disabled

API

PropTypeDefault
toggleLabel

Name of the reveal button; its pressed state says whether it shows.

string"Show password"

Accessibility

  • The reveal button uses aria-pressed.
  • Set autoComplete to "current-password" or "new-password" for password managers.

Compatibility

Tailwind CSS
3.4 and 4, both checked in CI
React
19
Rendering
Client component ("use client")

Source

1 file, installed as source you own
password-input.tsxView on GitHub
"use client";

import { EyeIcon, EyeOffIcon } from "lucide-react";
import { useState, type ComponentProps } from "react";

import { cn } from "@/registry/default/lib/utils";
import { Button } from "@/registry/default/ui/button";
import { InputGroup, InputGroupAddon, InputGroupInput } from "@/registry/default/ui/input-group";

interface PasswordInputProps extends Omit<ComponentProps<"input">, "type"> {
  /** Accessible name of the reveal button; its pressed state says whether the password shows. */
  toggleLabel?: string;
  /** Classes for the bordered group around the input and the button. */
  groupClassName?: string;
}

/**
 * A password field with a button that shows what was typed. Set
 * `autoComplete` to "current-password" or "new-password" so password
 * managers fill it.
 */
function PasswordInput({
  className,
  groupClassName,
  toggleLabel = "Show password",
  disabled,
  ...props
}: PasswordInputProps) {
  const [visible, setVisible] = useState(false);
  const Icon = visible ? EyeOffIcon : EyeIcon;

  return (
    <InputGroup data-slot="password-input" className={groupClassName}>
      <InputGroupInput
        {...props}
        type={visible ? "text" : "password"}
        disabled={disabled}
        className={className}
      />
      <InputGroupAddon align="inline-end" className="pr-1">
        <Button
          type="button"
          variant="ghost"
          size="icon-sm"
          aria-label={toggleLabel}
          aria-pressed={visible}
          disabled={disabled}
          onClick={() => setVisible((shown) => !shown)}
          className={cn("size-7", visible && "text-foreground")}
        >
          <Icon aria-hidden="true" />
        </Button>
      </InputGroupAddon>
    </InputGroup>
  );
}

export { PasswordInput, type PasswordInputProps };