Smooth Caret Input
An input with a spring-physics smooth caret — the custom caret glides to the text position on a spring, in bar, block, or underline shapes.
Bring this into your project
Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.
npx webberui@latest add smooth-caret-input.enPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<SmoothCaretInput/>
The complete example includes the preview layout and data. Install the component first, then paste this file into your project.
Installation
npx webberui@latest add https://webberui.com/r/smooth-caret-input.en.jsonThe install also writes the --wb-duration-fast and --wb-ease-out CSS variables into your global stylesheet.
Usage
import { SmoothCaretInput } from "@/components/ui/smooth-caret-input";
<SmoothCaretInput
placeholder="Start typing⋯"
onChange={(value) => console.log(value)}
/>Controlled mode:
const [value, setValue] = React.useState("");
<SmoothCaretInput value={value} onChange={setValue} caretShape="block" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled value; when omitted, the component manages it internally (uncontrolled mode) |
defaultValue | string | "" | Initial value in uncontrolled mode |
onChange | (value: string) => void | — | Fires when the value changes |
placeholder | string | — | Placeholder text |
disabled | boolean | false | Disables input |
caretShape | "bar" | "block" | "underline" | "bar" | Caret shape |
caretColor | string | text colour | Caret colour (any CSS colour) |
stiffness | number | 650 | Spring stiffness; higher settles faster |
damping | number | 42 | Spring damping; higher springs back less |
name | string | — | The input's name, for form submission |
id | string | — | The input's id, for binding a label |
aria-label | string | placeholder | Accessible label |
How it works
- Spring following: a hidden mirror span measures the width of the text before the caret to convert it into a pixel position, which
useSpringthen glides smoothly toward - Caret movement detection: it listens to
selectionchange, so arrow keys, clicks, and selections all recompute the position immediately and pause the blink, which resumes once the glide finishes - Overflow handling: when the text exceeds the width and scrolls horizontally,
scrollLeftis subtracted so the caret stays inside the visible area - IME safe: during Bopomofo (Zhuyin) or Pinyin composition, the mirror includes the composing text, so the caret keeps following the correct position
Accessibility
- The custom caret carries
aria-hiddenso it does not interfere with screen reading; theinputtakes thearia-label/name/id - When the user has "reduce motion" enabled at the system level, the native caret is restored after mount and the spring and blink animations are disabled
- When no
aria-labelis provided, theplaceholderis used automatically, guaranteeing a readable name
Test Results Panel
A test results panel whose pass, fail and skip counts roll digit by digit over a smoothly growing ratio bar, with failed tests expanding to show an expected-versus-actual diff.
OTP Input
A segmented verification-code input — a single invisible input sits over the visual cells, with paste support, an error shake, and a success ripple that turns the cells green.