- Accordion
- Agent Thinking
- Alert
- Alert Dialog
- Announcement
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Checkbox
- Checkbox Card
- Code Block
- Collapsible
- Color Picker
- Combobox
- Command
- Composer
- Composer Loader
- Context Menu
- Data Grid
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- File Upload
- Hover Card
- Input
- Input Group
- Input Otp
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Meter
- Native Select
- Navigation Menu
- Number Field
- Pagination
- Period Switcher
- Popover
- Progress
- Questionnaire
- Radio Card
- Radio Group
- Resizable
- Reveal
- Scroll Area
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Social Button
- Sonner
- Spinner
- Status Dot
- Switch
- Switch Card
- Table
- Tabs
- Tag Group
- Textarea
- Theme Toggle
- Time Field
- Toggle
- Toggle Group
- Tooltip
- Trace
- Tree View
- Agent Creator 01
- Agent Limits Card 01
- Agent Progress 01
- AI Chat 01
- AI Image Generation 01
- AI Profile 01
- Alerts Card 01
- Auth Card 01
- Calendar 01
- Composer 01
- Composer Attachments 01
- Composer Panel 01
- Finance Dashboard 01
- Home Dashboard 01
- Marketing Dashboard 01
- Medical Profile 01
- Meeting Scheduler 01
- Multi Agent Chat 01
- Notification Center 01
- Patient Info Card 01
- Project Board 01
- Questionnaire 01
- Settings Modal 01
- Sidebar 01
- Stat Cards 01
- Task List 01
- Web Search 01
- Activity Rings Card 01
- Area Chart Card 01
- Bar List Card 01
- Combo Chart Card 01
- Contributions Card 01
- Earnings Chart Card 01
- Funnel Chart Card 01
- Heatmap Chart Card 01
- Line Chart Card 01
- Most Active Days Card 01
- Orders Chart Card 01
- Radar Chart Card 01
- Radial Chart Card 01
- Revenue Chart Card 01
- Sankey Chart Card 01
- Scatter Chart Card 01
- Sleep Score Card 01
- Stage Bars Card 01
- Steps Card 01
Verification code
Invalid code
4
8
2
1
Unavailable
1
2
Installation
$ pnpm dlx shadcn@latest add @cobalt/input-otp
Source
"use client";
import { RiSubtractLine } from "@remixicon/react";
import { cn } from "cn";
import { OTPInput, OTPInputContext } from "input-otp";
import * as React from "react";
const InputOTPStateContext = React.createContext({
disabled: false,
invalid: false,
});
function InputOTP({
className,
containerClassName,
...props
}: React.ComponentProps<typeof OTPInput> & { containerClassName?: string }) {
return (
<InputOTPStateContext.Provider
value={{
disabled: !!props.disabled,
invalid:
props["aria-invalid"] === true || props["aria-invalid"] === "true",
}}
>
<OTPInput
data-slot="input-otp"
containerClassName={cn("flex items-center gap-2", containerClassName)}
spellCheck={false}
className={cn("disabled:cursor-not-allowed", className)}
{...props}
/>
</InputOTPStateContext.Provider>
);
}
function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="input-otp-group"
className={cn("flex items-center gap-2", className)}
{...props}
/>
);
}
function InputOTPSlot({
index,
className,
...props
}: React.ComponentProps<"div"> & { index: number }) {
const inputOTPContext = React.useContext(OTPInputContext);
const { disabled, invalid } = React.useContext(InputOTPStateContext);
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
return (
<div
data-slot="input-otp-slot"
data-active={isActive}
data-disabled={disabled || undefined}
data-invalid={invalid || undefined}
className={cn(
"relative flex size-12 items-center justify-center rounded-[10px] border border-border bg-popover font-mono text-[18px] leading-[26px] font-medium tracking-normal text-foreground tabular-nums shadow-[shadow:var(--shadow-control,0_1px_2px_0_rgb(0_0_0/0.05))] outline-none transition-[background-color,border-color,box-shadow] duration-150 ease-[ease] motion-reduce:transition-none",
"hover:border-[var(--border-hover,var(--border))] data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-2 data-[active=true]:ring-ring",
"data-invalid:border-[var(--field-invalid,var(--destructive))] data-invalid:bg-[var(--input-invalid-surface,color-mix(in_srgb,var(--destructive)_15%,transparent))] data-invalid:text-destructive data-invalid:hover:border-[var(--field-invalid,var(--destructive))]",
"data-disabled:cursor-not-allowed data-disabled:bg-muted data-disabled:text-[color:var(--foreground-subtle,var(--muted-foreground))] data-disabled:shadow-none",
className
)}
{...props}
>
{char}
{hasFakeCaret && (
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
<div className="h-4 w-px animate-caret-blink bg-foreground duration-1000 motion-reduce:animate-none" />
</div>
)}
</div>
);
}
function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="input-otp-separator"
className="flex items-center [&_svg:not([class*='size-'])]:size-4"
role="separator"
{...props}
>
<RiSubtractLine />
</div>
);
}
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; On this page