Magic Input
A 3D layered text input that lifts on focus with an optional rainbow edge animation.
Variants
The variant tints the 3D edge. It shows when rainbow={false} (the rainbow
gradient otherwise overrides the edge while focused).
Depth
depth="focus" (default) stays flat until focused. depth="always" keeps the
raised 3D look at rest.
Sizes
Submit button
Pass onSubmit to render an arrow button on the right. It fires with the
current value on click or when Enter is pressed. Without onSubmit,
set submitButton to render a type="submit" button for an enclosing form.
Submit lifecycle
status and progress are fully controlled. While status="loading" the
rainbow hides, the 3D depth locks in, and a progress bar runs along the bottom —
determinate when you pass progress, otherwise an indeterminate segment bounces
end to end. The arrow turns into a circular progress / spinner. success and
error flash a green / red sweep with a check / X icon.
You drive it from your submit handler:
const [status, setStatus] = useState<MagicInputStatus>("idle");
const [progress, setProgress] = useState(0);
async function handleSubmit(value: string) {
setStatus("loading");
try {
await upload(value, setProgress); // call setProgress(0..100) as it runs
setStatus("success");
} catch {
setStatus("error");
}
setTimeout(() => setStatus("idle"), 1600);
}
<MagicInput
status={status}
progress={status === "loading" ? progress : undefined}
onSubmit={handleSubmit}
/>;Installation
pnpm dlx shadcn@latest add @godui/magic-inputRequires the @godui namespace in your components.json (one-time setup):
{ "registries": { "@godui": "https://godui.design/r/{name}.json" }}Usage
import { MagicInput } from "@/components/godui/magic-input";<MagicInput placeholder="Focus me" />By default the input is flat and lifts into the 3D effect only while focused.
Set depth="always" to keep the raised look at rest, and rainbow={false} to
disable the animated rainbow edge.
<MagicInput depth="always" rainbow={false} placeholder="Always raised" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "primary" | "secondary" | "primary" | 3D edge color scheme (visible when rainbow={false}) |
size | "sm" | "md" | "lg" | "md" | Input padding and text size |
depth | "focus" | "always" | "focus" | Show the 3D depth only on focus, or always |
rainbow | boolean | true | Animate the edge and shadow with a rainbow gradient while focused |
submitButton | boolean | false | Show the arrow submit button (type="submit") |
onSubmit | (value: string) => void | — | Fires with the value on click / Enter; also shows the button |
submitLabel | string | "Submit" | Accessible label for the submit button |
status | "idle" | "loading" | "success" | "error" | "idle" | Submit lifecycle state |
progress | number | — | 0–100; makes loading determinate (omit for indeterminate) |