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-input

Requires 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

PropTypeDefaultDescription
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
rainbowbooleantrueAnimate the edge and shadow with a rainbow gradient while focused
submitButtonbooleanfalseShow the arrow submit button (type="submit")
onSubmit(value: string) => voidFires with the value on click / Enter; also shows the button
submitLabelstring"Submit"Accessible label for the submit button
status"idle" | "loading" | "success" | "error""idle"Submit lifecycle state
progressnumber0–100; makes loading determinate (omit for indeterminate)

On this page