Subscribe
Installation
Add the following Soul components
The subscribe component uses the inline-email-form component. Make sure you have added it to your project.
Install the following dependencies
npm install clsx
Copy and paste the following code into your project
sections/subscribe/index.tsx
import { SubmissionResult } from '@conform-to/react';import { clsx } from 'clsx';import Image from 'next/image';import { InlineEmailForm } from '@/vibes/soul/sections/inline-email-form';type Action<State, Payload> = (state: Awaited<State>, payload: Payload) => State | Promise<State>;type SubscribeAction = Action< { lastResult: SubmissionResult | null; successMessage?: string }, FormData>;export interface SubscribeProps { action: SubscribeAction; image?: { src: string; alt: string }; title: string; description?: string; placeholder?: string;}/** * This component supports various CSS variables for theming. Here's a comprehensive list, along * with their default values: * * ```css * :root { * --subscribe-font-family: var(--font-family-body); * --subscribe-title-font-family: var(--font-family-heading); * --subscribe-background: color-mix(in oklab, hsl(var(--primary)), black 75%); * --subscribe-title: color-mix(in oklab, hsl(var(--primary)), white 75%); * --subscribe-description: color-mix(in oklab, hsl(var(--primary)), white 75%); * } * ``` */export function Subscribe({ action, image, title, description, placeholder }: SubscribeProps) { return ( <section className="bg-[var(--subscribe-background,color-mix(in_oklab,hsl(var(--primary)),black_75%))] font-[family-name:var(--subscribe-font-family,var(--font-family-body))] @container"> <div className="flex flex-col items-start @4xl:flex-row @4xl:items-stretch"> {image && ( <div className="relative min-h-96 w-full bg-primary/10 @4xl:flex-1"> <Image alt={image.alt} className="object-cover" fill sizes="(min-width: 56rem) 50vw, 100vw" src={image.src} /> </div> )} <div className="w-full flex-1"> <div className={clsx( 'flex w-full flex-col gap-10 px-4 py-10 @xl:px-6 @xl:py-14 @4xl:gap-16 @4xl:px-8 @4xl:py-20', Boolean(image) ? '@4xl:max-w-4xl' : 'mx-auto max-w-screen-2xl @4xl:flex-row', )} > <header className="flex-1"> <h2 className="mb-4 font-[family-name:var(--subscribe-title-font-family,var(--font-family-heading))] text-2xl font-medium leading-none text-[var(--subscribe-title,color-mix(in_oklab,hsl(var(--primary)),white_75%))] @xl:text-3xl @4xl:text-4xl"> {title} </h2> <p className="text-[var(--subscribe-description,color-mix(in_oklab,hsl(var(--primary)),white_75%))] opacity-75"> {description} </p> </header> <InlineEmailForm action={action} className="flex-1" placeholder={placeholder} /> </div> </div> </div> </section> );}
Usage
function Usage() { return ( <Subscribe action={action} description="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor." image={image} title="Sign up for our newsletter" /> );} const image = { src: 'https://rstr.in/monogram/vibes/m12FEyfnuDl', alt: 'Lady with plant',};async function action( _lastResult: { lastResult: SubmissionResult | null }, formData: FormData,) { 'use server'; const submission = parseWithZod(formData, { schema }); if (submission.status !== 'success') { return { lastResult: submission.reply({ formErrors: ['Boom!'] }) }; } // Simulate subscribing a user await new Promise((resolve) => setTimeout(resolve, 1000)); return { lastResult: submission.reply(), successMessage: 'Subscribed!' };}
API Reference
SubscribeProps
Prop | Type | Default |
---|---|---|
action* | SubscribeAction | |
image | Image | |
title* | string | |
description | string | |
placeholder | string |
ForgotPasswordAction
type Action<State, Payload> = (state: Awaited<State>, payload: Payload) => State | Promise<State>;type SubscribeAction = Action< { lastResult: SubmissionResult | null; successMessage?: string }, FormData>;
This component uses Confom to handle form submissions. Refer to the Conform docs for more details.
Here's an example of an action function that does validation and simulates subscribe a user:
async function action(_lastResult: { lastResult: SubmissionResult | null }, formData: FormData) { 'use server'; const submission = parseWithZod(formData, { schema }); if (submission.status !== 'success') { return { lastResult: submission.reply({ formErrors: ['Boom!'] }) }; } // Simulate subscribing a user await new Promise((resolve) => setTimeout(resolve, 1000)); return { lastResult: submission.reply(), successMessage: 'Subscribed!' };}
Image
Prop | Type | Default |
---|---|---|
src* | string | |
alt* | string |
CSS Variables
This component supports various CSS variables for theming. Here's a comprehensive list.
:root { --subscribe-font-family: var(--font-family-body); --subscribe-title-font-family: var(--font-family-heading); --subscribe-background: color-mix(in oklab, hsl(var(--primary)), black 75%); --subscribe-title: color-mix(in oklab, hsl(var(--primary)), white 75%); --subscribe-description: color-mix(in oklab, hsl(var(--primary)), white 75%);}