Shadcn Password Input for React and Tailwind
A field for entering secure text.
Installation
bunx --bun shadcn@latest add https://kit.dev/r/password-input.jsonpnpm dlx shadcn@latest add https://kit.dev/r/password-input.jsonnpx shadcn@latest add https://kit.dev/r/password-input.jsonyarn shadcn@latest add https://kit.dev/r/password-input.json<Step>This component depends on Input Group. Install them first if you haven't already.</Step>
Install the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactCopy and paste the following code into your project.
"use client";
import {
PasswordInput as ArkPasswordInput,
usePasswordInputContext,
} from "@ark-ui/react/password-input";
import { EyeIcon, EyeOffIcon } from "lucide-react";
import type React from "react";
import { cn } from "@/lib/utils";
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
type InputGroupProps,
} from "@/components/ui/input-group";
export const usePasswordInput = usePasswordInputContext;
interface PasswordInputProps
extends React.ComponentProps<typeof ArkPasswordInput.Root>,
Pick<InputGroupProps, "size"> {}
export const PasswordInput = (props: PasswordInputProps) => {
const { size = "md", className, ...rest } = props;
return (
<ArkPasswordInput.Root
className={cn(
"group/password-input",
"w-full",
"flex flex-col items-start gap-2",
className
)}
data-size={size}
data-slot="password-input"
{...rest}
/>
);
};
export const PasswordInputGroup = (
props: React.ComponentProps<typeof ArkPasswordInput.Control>
) => {
const { className, ...rest } = props;
return (
<ArkPasswordInput.Control asChild data-slot="password-input-control">
<InputGroup
className={cn(
"in-data-[size=lg]:h-9 in-data-[size=sm]:h-7",
"data-disabled:pointer-events-none data-disabled:opacity-64",
className
)}
{...rest}
/>
</ArkPasswordInput.Control>
);
};
export const PasswordInputInput = (
props: React.ComponentProps<typeof ArkPasswordInput.Input>
) => (
<ArkPasswordInput.Input asChild data-slot="password-input-input" {...props}>
<InputGroupInput />
</ArkPasswordInput.Input>
);
export const PasswordInputTrigger = (
props: React.ComponentProps<typeof ArkPasswordInput.VisibilityTrigger>
) => {
const { children, ...rest } = props;
return (
<InputGroupAddon align="inline-end">
<ArkPasswordInput.VisibilityTrigger
asChild
data-slot="password-input-visibility-trigger"
>
<InputGroupButton size="icon-xs" variant="ghost" {...rest}>
{children ?? <PasswordInputIndicator />}
</InputGroupButton>
</ArkPasswordInput.VisibilityTrigger>
</InputGroupAddon>
);
};
export const PasswordInputIndicator = (
props: React.ComponentProps<typeof ArkPasswordInput.Indicator>
) => {
const { children, ...rest } = props;
return (
<ArkPasswordInput.Indicator
data-slot="password-input-indicator"
fallback={<EyeOffIcon />}
{...rest}
>
{children ?? <EyeIcon />}
</ArkPasswordInput.Indicator>
);
};Update the import paths to match your project setup.
Anatomy
PasswordInput
└── PasswordInputGroup
├── PasswordInputInput
└── PasswordInputTriggerUsage
import {
PasswordInput,
PasswordInputGroup,
PasswordInputInput,
PasswordInputTrigger,
} from "@/components/ui/password-input";<PasswordInput>
<PasswordInputGroup>
<PasswordInputInput placeholder="Enter password" />
<PasswordInputTrigger />
</PasswordInputGroup>
</PasswordInput>Controlled
Use value and onChange on PasswordInputInput to control the password value.
States
Disabled
Use the disabled prop to disable the password input.
Invalid
Use the invalid prop to mark the password input as invalid.
Sizes
Use the size prop to change the input height.
Small
Medium
Large
Examples
Autocomplete
Use the autoComplete prop to hint autofill behavior to the browser.
current-password— signing in with an existing passwordnew-password— creating or resetting a password
Controlled Visibility
Use visible and onVisibilityChange to control whether the value is shown.
Auto Hide
Use visible, onVisibilityChange, and a timer to hide the password again after it is revealed.
Custom Indicator
With Field
Combine with Field components, for labeled password fields with helper text.
API Reference
PasswordInput
Root component. Manages visibility and input state.
| Prop | Type | Default |
|---|---|---|
size | "sm" | "md" | "lg" | "md" |
autoComplete | "current-password" | "new-password" | "current-password" |
defaultVisible | boolean | false |
visible | boolean | - |
disabled | boolean | - |
invalid | boolean | - |
readOnly | boolean | - |
required | boolean | - |
name | string | - |
ignorePasswordManagers | boolean | - |
onVisibilityChange | (details: VisibilityChangeDetails) => void | - |
className | string | - |
asChild | boolean | false |
PasswordInputGroup
Wraps the input and visibility trigger.
| Prop | Type | Default |
|---|---|---|
className | string | - |
asChild | boolean | false |
PasswordInputInput
Password field.
| Prop | Type | Default |
|---|---|---|
size | "sm" | "md" | "lg" | "md" |
className | string | - |
asChild | boolean | false |
PasswordInputTrigger
Button that toggles visibility.
| Prop | Type | Default |
|---|---|---|
className | string | - |
PasswordInputIndicator
Renders different icons based on visibility. Use fallback for the hidden state and pass the visible-state icon as children.
| Prop | Type | Default |
|---|---|---|
fallback | React.ReactNode | <EyeOffIcon /> |
children | React.ReactNode | <EyeIcon /> |
className | string | - |
For a complete list of props, see the Ark UI documentation.