The inputs shadcn/ui does not ship. Every field below is live — type in them, paste into them, break them. The readout underneath shows the value onChange actually emits.
Paste +44 20 7123 4567 — the country switches with it.
value = "" · E.164
Digits fill from the right, like a register.
value = 0 · minor units
Shows 12.5, emits 0.125.
value = 0 · fraction
The caret holds position mid-string. Paste normalises. Separators and zero-decimal currencies come from Intl, not from a hardcoded 100.
Only shadcn CSS variables. Your palette, your radius, your focus ring, your dark mode — inherited, never overridden.
Installed through the registry: the source lands in your repo. Edit it, fork it, delete half of it. The headless hooks ship too.
Keyboard complete and axe-core in CI, with the four ARIA bugs it caught written up. Screen readers are not verified yet, and the audit says so.
Every card below is a working input, not a screenshot. The readout under each one is the value onChange actually emits.
Paste +44 20 7123 4567 — the country switches with it.
value = "" · E.164
Digits fill from the right, like a register.
value = 0 · minor units
Click into the middle and type — the caret holds.
value = "" · raw, no mask characters
Shows 12.5, emits 0.125.
value = 0 · fraction
Try 4242… then 3782… — the grouping reflows to 4-6-5.
value = "" · digits only
90m, 1:30 and 1.5h all land on the same number.
value = 0 · seconds
1.28:1below AA against #FFFFFF
Paste rgb(205, 242, 92) — it converts.
value = #CDF25C · hex
At 09:00, Monday through Friday
Try */15 * * * * or @daily.
value = "0 9 * * 1-5"
1 MB and 1 MiB differ by 4.9%. Try both.
value = 0 · bytes
Try 10.0.0.0/24, or paste a whole log line.
value = ""
Type @ then a letter. Delete a mention and its id goes with it.
value = "" · ids []
So the library tells the agent what to do, rather than hoping it read the docs. Agents are not bad at finding components — they are bad at value semantics.
Checkout, onboarding, scheduler. Live, with the source and a one-click prompt.
Browse →Every component page builds a prompt carrying the real props and the traps, then opens your agent with it typed in.
Try one →npx skills add 42aditya31/inputcnThree skills and an MCP server, so the agent looks up the real prop list instead of inventing one.
Set up →npx inputcn generateAsk the model for a 20-line spec, not for React. A prop that does not exist fails instead of shipping.
How it works →And with none of it. The field detects whether something else owns its error state and gets out of the way.
import { useForm, Controller } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { moneySchema } from "@inputcn/currency/schema"
import { z } from "zod"
// The companion schema validates the CANONICAL value, so the resolver and the
// field can never disagree about what "valid" means.
const schema = z.object({ price: moneySchema({ positive: true, max: 100000 }) })
const { control } = useForm({ resolver: zodResolver(schema) })
<Controller
name="price"
control={control}
render={({ field, fieldState }) => (
<CurrencyInput label="Price" {...field} aria-invalid={fieldState.invalid} />
)}
/>// Or none of that. No schema, no resolver, no onBlur handler,
// no useState for the error message.
<CurrencyInput
label="Budget"
required
positive
max={100000}
currency="GBP"
/>The display string is a view. This column is what you store, validate and send over the wire.
Silent until the first blur, then live. The message is generated from the rule, and the rule name is on the element for your tests.
Full detail in Constraint props, and the complete generated list on each component page.