registry:component
Input OTP
v1.0.0ga
One-time-code input primitive with slot rendering.
Registry Endpoint
Open JSONhttps://registry.aavya.com/r/ui-input-otp.json
npx shadcn@latest add https://registry.aavya.com/r/ui-input-otp.json
Live Preview
Verification code
1
2
3
4
5
6
Usage Snippet
import InputOtp from '@/components/ui/input-otp.tsx'
export default function Example() {
return (
<div className="p-6">
<InputOtp />
</div>
)
}
Source Preview
'use client'
import * as React from 'react'
import { OTPInput, OTPInputContext } from 'input-otp'
import { MinusIcon } from 'lucide-react'
import { cn } from '@/lib/utils'
function InputOTP({
className,
containerClassName,
...props
}: React.ComponentProps<typeof OTPInput> & {
containerClassName?: string
}) {
return (
<OTPInput
data-slot='input-otp'
containerClassName={cn('flex items-center gap-2 has-disabled:opacity-50', containerClassName)}
className={cn('disabled:cursor-not-allowed', className)}
{...props}
/>
)
}
function InputOTPGroup({ className, ...props }: React.ComponentProps<'div'>) {
return <div data-slot='input-otp-group' className={cn('flex items-center', className)} {...props} />
}
function InputOTPSlot({
index,
className,
...props
}: React.ComponentProps<'div'> & {
index: number
}) {
const inputOTPContext = React.useContext(OTPInputContext)
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}
return (
<div
data-slot='input-otp-slot'
data-active={isActive}
className={cn(
'data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-i