Primitives
Input OTP
One-time-code field with grouped, focus-aware slots.
Composition
The preferred shape for composing the installed primitive from its exported parts.
Parts
Exported compound parts from the installed source.
InputOTPSlot├── InputOTPSeparator└── InputOTPThe refined source installs this primitive from src/registry/sources/refined/ui/input-otp.tsx. Install it on its own with the command above, or inspect the source below.
npx shadcn@latest add http://127.0.0.1:3000/r/refined/input-otp.jsonRaw code
Primary installed primitive source
Base UI OtpField slot
src/registry/sources/refined/ui/input-otp.tsx
"use client";import { OTPField as OTPFieldPrimitive } from "@base-ui/react/otp-field";import { Fragment } from "react";import type { InputOTPProps, InputOTPSeparatorProps, InputOTPSlotProps } from "@/components/refined-ui/contracts";import { cn } from "@/components/refined-ui/lib/cn";import { skinSlot } from "@/components/refined-ui/skin";// Refined skin slot, 100% Base UI OtpField: each slot a control-shaped box sharing --radius-control/card+ring surface w/ Input & Select trigger.// Code reads as a row of the same control family; focused slot lifts ring in pure CSS.const slotClasses = "relative flex size-[var(--control-h-md)] items-center justify-center rounded-[var(--radius-control)] bg-card/72 text-center text-body font-medium tabular-nums text-foreground shadow-sm ring-1 ring-inset ring-border outline-none transition placeholder:text-muted-foreground focus:z-[1] focus:ring-2 focus:ring-foreground/20 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50";export function InputOTPSlot({ index, length, className, ...props }: InputOTPSlotProps) { return ( <OTPFieldPrimitive.Input data-ui="agent" data-slot="input-otp-slot" data-control="true" aria-label={length ? `Character ${index + 1} of ${length}` : `Character ${index + 1}`} className={cn(slotClasses, skinSlot("input-otp-slot", {}), className)} {...props} /> );}export function InputOTPSeparator({ className, ...props }: InputOTPSeparatorProps) { return ( <OTPFieldPrimitive.Separator data-ui="agent" data-slot="input-otp-separator" className={cn("h-px w-2.5 shrink-0 rounded-full bg-border", skinSlot("input-otp-separator", {}), className)} {...props} /> );}export function InputOTP({ length = 6, separator = false, className, children, ...props }: InputOTPProps) { return ( <OTPFieldPrimitive.Root data-ui="agent" data-slot="input-otp" length={length} className={cn("flex items-center gap-2", skinSlot("input-otp", {}), className)} {...props} > {children ?? Array.from({ length }, (_, index) => `input-otp-slot-${index}`).map((slotKey, index) => ( <Fragment key={slotKey}> {separator && index === Math.ceil(length / 2) ? <InputOTPSeparator /> : null} <InputOTPSlot index={index} length={length} /> </Fragment> ))} </OTPFieldPrimitive.Root> );}