An AI startup's waitlist hero. The whole email pill is the magnet: the field loops out from it, parts around the headline, and bends toward the pointer. Join, and every hairline swings to north with `aligned`; Undo lets the field take them back.
@keyframeui
registry/demos/lodestone-demo.tsx
"use client";
import * as React from "react";
import { Lodestone, LodestoneQuiet, LodestoneTarget } from "@/components/ui/lodestone";
export function LodestoneDemo() {
const [joined, setJoined] = React.useState(false);
const [email, setEmail] = React.useState("");
return (
<Lodestone
aligned={joined}
className="flex h-[var(--demo-height,36rem)] w-full flex-col items-center justify-center rounded-2xl border border-border bg-background px-6 text-center text-foreground"
>
<LodestoneQuiet className="flex flex-col items-center">
<span className="rounded-full border border-border bg-background px-3 py-1 text-xs font-medium text-muted-foreground">
Private beta · 2,480 teams waiting
</span>
<h2 className="mt-6 max-w-[15ch] text-4xl/[1.05] font-semibold tracking-tight text-balance sm:text-6xl/[1.02]">
Agents that pull in one direction
</h2>
<p className="mt-5 max-w-md text-base/7 text-pretty text-muted-foreground">
Meridian lines up every agent in your stack behind one goal, one plan and one log you
can read.
</p>
</LodestoneQuiet>
<LodestoneTarget className="mt-10 h-12">
{joined ? (
<div className="flex h-12 items-center gap-3 rounded-full border border-border bg-background pr-2 pl-5 text-sm">
<span className="font-medium">You're in. Number 2,481.</span>
<button
type="button"
onClick={() => {
setJoined(false);
setEmail("");
}}
className="rounded-full px-3 py-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
>
Undo
</button>
</div>
) : (
<form
onSubmit={(e) => {
e.preventDefault();
setJoined(true);
}}
className="flex h-12 items-center rounded-full border border-border bg-background p-1 shadow-sm"
>
<label htmlFor="lodestone-email" className="sr-only">
Work email
</label>
<input
id="lodestone-email"
type="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@company.com"
className="h-full w-44 bg-transparent px-4 text-sm outline-none placeholder:text-muted-foreground sm:w-56"
/>
<button
type="submit"
className="h-10 rounded-full bg-foreground px-5 text-sm font-medium text-background transition-transform active:scale-[0.97]"
>
Join the waitlist
</button>
</form>
)}
</LodestoneTarget>
</Lodestone>
);
}
Live preview, examples and props: https://keyframeui.com/components/lodestone#lodestone-demo















