Components
A controlled text input that validates as you type, crossfading between a hint, an inline error message, and valid/invalid status icons.

"use client";
import { InlineValidation } from "@/components/ui/inline-validation";
import { useState } from "react";
const checkEmail = (v: string) => {
if (v.trim() === "") return "A work email is required.";
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v))
return "That is not a complete email address.";
return null;
};
export default function InviteFormDemo() {
const [email, setEmail] = useState("");
return (
<div className="flex min-h-[280px] w-full items-center justify-center p-6">
<form
className="w-full max-w-sm"
onSubmit={(e) => {
e.preventDefault();
if (checkEmail(email)) return;
alert(`Invite sent to ${email}`);
}}
>
<InlineValidation
label="Work email"
type="email"
value={email}
onChange={setEmail}
validate={checkEmail}
hint="Only used to send the invite."
autoComplete="email"
required
/>
<button
type="submit"
className="mt-3 h-9 rounded-[9px] bg-stone-800 px-3 text-[13px] font-medium text-white dark:bg-stone-100 dark:text-stone-900"
>
Send invite
</button>
</form>
</div>
);
}
Part of interior.dev — browse the full library on 21st.dev.