Preview
Installation
CLI
npx shadcn@latest add https://kelvinmai.io/r/password-input.json
Manual
Install the following dependencies
npm install clsx tailwind-merge
Add a classname utility function
import { clsx, type ClassValue } from 'clsx';import { twMerge } from 'tailwind-merge';export const cn = (...inputs: ClassValue[]) => {return twMerge(clsx(inputs));};
Copy and paste the following code into your project
components/password-input.tsx
'use client';import * as React from 'react';import { Eye, EyeOff } from 'lucide-react';import { useBoolean } from '@/hooks/use-boolean';import { Input } from '@/components/ui/input';export const PasswordInput: React.FC<React.ComponentProps<typeof Input>> = ({...props}) => {const visible = useBoolean();return (<div className='relative'><Input type={visible.value ? 'text' : 'password'} {...props} /><buttonclassName='text-muted-foreground/80 hover:text-foreground focus-visible:outline-ring/70 absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center rounded-e-lg outline-offset-2 transition-colors focus:z-10 focus-visible:outline focus-visible:outline-2 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50'type='button'onClick={visible.toggle}aria-label={visible.value ? 'Hide password' : 'Show password'}aria-pressed={visible.value}aria-controls='password'>{visible.value ? (<EyeOff className='size-4' aria-hidden='true' />) : (<Eye className='size-4' aria-hidden='true' />)}</button></div>);};
Update the import paths to match your project setup
Usage
import { PasswordInput } from '@/components/ui/password-input';export default function PasswordInputDemo() {return <PasswordInput id='password' />;}