BlockDex

Components

Registries

Free blocks

Method

BlockDex

Components

Registries

Free blocks

Method

Open API

BlockDex

Components

Registries

Free blocks

Method

Open API

Components/moumenlab/otp-segmented-input

OTP Segmented Input

moumenlab/otp-segmented-input
FreeComponent

Six cells that are secretly one real input, with native selection driving the active cell.

Live preview

live · rendered by the registry
Rendered by moumenlab on their own page — this is the component running, not a screenshot of it.

Install it

npx shadcn@latest add https://lab.moumen.dev/r/otp-segmented-input.json

Source

registry/lab/otp-segmented-input/otp-segmented-input.tsxlab.moumen.dev/r/otp-segmented-input.json · first 6 KB
1"use client";
2
3import { useEffect, useMemo, useRef, useState, type CSSProperties } from "react";
4import { MotionConfig, motion } from "motion/react";
5
6// OTP segmented input - N boxes, secretly ONE real input.
7//
8// The version everyone demos is six <input>s wired together with JS focus
9// hops. It looks right and behaves wrong: SMS autofill can't fill it (iOS
10// offers the code to ONE field), paste needs bespoke splitting, screen
11// readers announce six unlabeled boxes, and half the keyboard is re-invented.
12//
13// This is the hard version: one real <input> stretched invisibly over the
14// whole row (color and caret transparent - NOT display:none, it must stay
15// focusable and autofillable), with the cells painted underneath from its
16// value. Everything hard becomes free:
17//
18// · SMS autofill just works - autocomplete="one-time-code" on a real,
19// visible-to-the-browser input.
20// · Paste just works - "246 810" lands in the input, one normalize pass
21// strips the junk, the cells repaint.
22// · Backspace walks backwards and ←/→ move the caret because they are the
23// NATIVE caret - the active cell is derived from selectionStart, never
24// stored beside it. Select-all paints all cells selected, because a
25// selection range maps to a cell range.
26// · The input's own glyphs are letter-spaced to sit under the cells, so the
27// blueprint toggle can simply tint them red and you SEE the real input
28// lying over the fake one.
29//
30// Verification is yours: pass `verify` (sync or async - hit your API) and a
31// full code drives the little state machine: right → the cells cascade green
32// left to right; wrong → the row shakes, the digits drop out one by one, then
33// the field clears and hands the caret back. Without `verify` it compares
34// against the `code` prop, so the component demos out of the box.
35//
36// Animation via motion/react; honours prefers-reduced-motion. Requires the
37// lab-theme tokens. Fully Tailwind, no CSS files.
38
39const EASE = [0.22, 1, 0.36, 1] as const;
40const SHAKE_S = 0.38; // wrong code: the row shake
41const DROP_S = 0.24; // each digit's fall-out
42const STAGGER_S = 0.045; // per-digit clear offset
43const FILL_S = 0.055; // per-cell success cascade offset
44
45const OTP_VARS = {
46 "--otp-cell-w": "2.75rem",
47 "--otp-cell-h": "3.25rem",
48 "--otp-gap": "0.5rem",
49} as CSSProperties;
50
51export interface OtpInputState {
52 length: number;
53 caret: { start: number; end: number };
54 state: "idle" | "success" | "error";
55// … truncated

What it pulls in

npm packages

  • motion

Other registry items

  • https://lab.moumen.dev/r/lab-theme.json

Files it writes

  • registry/lab/otp-segmented-input/otp-segmented-input.tsx

Facts

Registry
moumenlab
Type
registry:component
Access
Free
Files written
1
Licence
MIT
First indexed
2026-08-11
Last confirmed
today

Go to the source

Docs on moumenlab lab.moumen.dev moumen-soliman/lab on GitHub Raw registry item This item as JSON

More from moumenlab

All 14 items
Same registry, same kind — the ones you would have found next
ComponentRegistryKindAccessInstallsCommand
Caret-Anchored Mention Popovercaret-mention-popovermoumenlabComponentsFree1 dep
Command Palette with Argument Chipscommand-palettemoumenlabComponentsFree1 dep
Drag-to-Reorder Listdrag-to-reorder-listmoumenlabComponentsFree1 dep
File Upload Staging Areafile-upload-stagingmoumenlabComponentsFree1 dep
Hover-Expand Icon Striphover-expand-icon-stripmoumenlabComponentsFree1 dep
Inertial Wheel Listinertial-wheel-listmoumenlabComponentsFree1 dep
Morphing Checkout Flowmorphing-checkoutmoumenlabComponentsFree1 dep
Schedule Builderschedule-buildermoumenlabComponentsFree1 dep
BlockDex

Built by

Kynth Studios

the studio behind StoreReady, ToolDrift and BreachProbe

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

© 2026 BlockDex. A Kynth Studios product.

BlockDex

BlockDex

Built by

Kynth Studios

the studio behind StoreReady, ToolDrift and BreachProbe

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

© 2026 BlockDex. A Kynth Studios product.

BlockDex

BlockDex

Built by

Kynth Studios

the studio behind StoreReady, ToolDrift and BreachProbe

Index

Components
Registries
Method
Open API

Guides

shadcn component libraries
Best shadcn registries
Free shadcn blocks

Reference

Corpus counts
Crawl health
hello@kynth.studio
Privacy
Terms

© 2026 BlockDex. A Kynth Studios product.

BlockDex