(Feat) Init WebSite
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"use client";
|
||||
|
||||
import { useActionState } from "react";
|
||||
import { useFormStatus } from "react-dom";
|
||||
import { subscribe, type SubscribeState } from "@/app/actions/subscribe";
|
||||
|
||||
const initialState: SubscribeState = { status: "idle", message: "" };
|
||||
|
||||
function SubmitButton() {
|
||||
const { pending } = useFormStatus();
|
||||
return (
|
||||
<button
|
||||
type="submit"
|
||||
disabled={pending}
|
||||
className="px-6 py-3 bg-accent text-background font-display tracking-widest text-sm hover:bg-foreground hover:scale-[1.03] transition duration-200 disabled:opacity-60 disabled:cursor-not-allowed disabled:hover:scale-100"
|
||||
>
|
||||
{pending ? "SENDING…" : "SUBSCRIBE"}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
type Props = {
|
||||
variant?: "default" | "compact";
|
||||
};
|
||||
|
||||
export function Newsletter({ variant = "default" }: Props) {
|
||||
const [state, formAction] = useActionState(subscribe, initialState);
|
||||
|
||||
const wrapperClass =
|
||||
variant === "compact"
|
||||
? "w-full max-w-lg"
|
||||
: "w-full max-w-lg mx-auto";
|
||||
|
||||
return (
|
||||
<form
|
||||
action={formAction}
|
||||
className={wrapperClass}
|
||||
aria-describedby="newsletter-status"
|
||||
>
|
||||
{/* honeypot for bots */}
|
||||
<input
|
||||
type="text"
|
||||
name="website"
|
||||
tabIndex={-1}
|
||||
autoComplete="off"
|
||||
className="hidden"
|
||||
aria-hidden
|
||||
/>
|
||||
<label htmlFor="newsletter-email" className="sr-only">
|
||||
Email address
|
||||
</label>
|
||||
<div className="flex flex-col sm:flex-row gap-3">
|
||||
<input
|
||||
id="newsletter-email"
|
||||
type="email"
|
||||
name="email"
|
||||
required
|
||||
placeholder="your@email.com"
|
||||
className="flex-1 min-w-0 bg-surface border border-border px-4 py-3 text-sm text-foreground placeholder:text-foreground-muted focus:outline-none focus:border-accent transition-colors"
|
||||
/>
|
||||
<SubmitButton />
|
||||
</div>
|
||||
|
||||
<p
|
||||
id="newsletter-status"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
className={`text-xs tracking-widest mt-3 ${
|
||||
variant === "compact" ? "" : "text-center"
|
||||
} ${
|
||||
state.status === "success"
|
||||
? "text-accent"
|
||||
: state.status === "error"
|
||||
? "text-red-400"
|
||||
: "text-foreground-muted"
|
||||
}`}
|
||||
>
|
||||
{state.message ||
|
||||
"No spam. One devblog email per major update. Unsubscribe anytime."}
|
||||
</p>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user