Newsletter signup form example
This is a simple newsletter signup form example. It has client side validation and displays a success message after a successful submission.
Subscribe to our newsletter
newsletter-signup-form.tsx
'use client';
import { Button } from '@/ui/components/button/button';
import { Checkbox } from '@/ui/components/forms/checkbox';
import { Form, FormRoot } from '@/ui/components/forms/form';
import {
FormServerError,
FormStatus,
FormSuccessMessage,
} from '@/ui/components/forms/form-status';
import { useForm } from '@/ui/components/forms/hooks/use-form';
import { TextField } from '@/ui/components/forms/text-field';
import { validators } from '@/ui/components/forms/util';
import { newsletterSignupAction } from './action';
import { LoginFormValues } from './types';
export const NewsletterSignupForm = () => {
const form = useForm<LoginFormValues>({
onSubmit: async ({ values, reset }) => {
await newsletterSignupAction(values);
reset(); // on success clear form values
},
});
return (
<FormRoot context={form}>
<h2 id="login-form-heading" className="mb-4 text-3xl font-bold">
Subscribe to our newsletter
</h2>
<FormStatus>
{form.serverError && (
<FormServerError
title="Something went wrong!"
className="animate-in fade-in-90 slide-in-from-bottom-10 duration-300"
/>
)}
{form.status === 'success' && (
<FormSuccessMessage
title="Success!"
message="You are now subscribed to our newsletter"
className="animate-in fade-in-90 slide-in-from-bottom-10 duration-300"
/>
)}
</FormStatus>
{form.status !== 'success' && (
<Form
className="flex flex-row gap-2 rounded-lg border-2 border-gray-200 p-4 shadow-xl"
aria-labelledby="login-form-heading"
>
<div className="flex flex-1 flex-col gap-2">
<TextField
id="email"
name="email"
label="Email"
type="email"
autoComplete="email"
validate={(value) => {
if (!value) {
return 'Please enter your email address';
}
if (!validators.email(value)) {
return 'Please enter a valid email address';
}
}}
isRequired
/>
<Checkbox
id="privacyPolicy"
name="privacyPolicy"
label="I agree to the privacy policy"
isRequired
validate={(value) => {
if (!value) {
return 'You must agree to the privacy policy';
}
}}
/>
</div>
<div className="pt-6">
<Button
type="submit"
className="h-11"
disabled={form.isPending}
loading={form.isPending}
>
Subscribe
</Button>
</div>
</Form>
)}
</FormRoot>
);
};