Send a message
contact-form.tsx
"use client";
import { useState, type SyntheticEvent } from "react";
import { LuClock, LuMail, LuMapPin, LuSend, LuUser } from "react-icons/lu";
import { Alert, Button, Input, Select, SelectOption, Textarea } from "@nexera-ui/react";
const TOPICS = [
{ id: "payroll", label: "Payroll and payslips" },
{ id: "leave", label: "Leave and time off" },
{ id: "benefits", label: "Benefits and pension" },
{ id: "access", label: "Laptop and system access" },
{ id: "other", label: "Something else" },
];
/** Contact form: ask People Ops a question with name, email, topic and message, validated on submit. */
export default function ContactForm() {
const [sent, setSent] = useState(false);
const onSubmit = (event: SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
setSent(true); // replace with your request to the help desk
};
return (
<div className="@container bg-page px-4 py-8 @3xl:px-8">
<div className="mx-auto grid max-w-5xl gap-8 @3xl:grid-cols-[1fr_2fr]">
<aside className="grid content-start gap-4">
<header className="grid gap-1">
<h2 className="text-heading-h3 text-primary">Contact People Ops</h2>
<p className="text-body-default text-secondary">
Questions about pay, leave or benefits go straight to the Northwind People Ops team.
</p>
</header>
<ul className="grid gap-3 text-body-small text-secondary">
<li className="flex items-start gap-2">
<LuClock aria-hidden className="mt-0.5 shrink-0 text-muted" />
We reply within one working day, Monday to Friday.
</li>
<li className="flex items-start gap-2">
<LuMail aria-hidden className="mt-0.5 shrink-0 text-muted" />
<a href="#people-ops-email" className="text-brand-text underline underline-offset-4">
peopleops@northwind.io
</a>
</li>
<li className="flex items-start gap-2">
<LuMapPin aria-hidden className="mt-0.5 shrink-0 text-muted" />
Desk 4.12, Northwind London office
</li>
</ul>
</aside>
<section
aria-labelledby="contact-form-title"
className="grid gap-5 rounded-xl border border-default bg-surface p-5 shadow-sm @3xl:p-8"
>
<h3 id="contact-form-title" className="text-heading-h4 text-primary">
Send a message
</h3>
{sent ? (
<Alert
tone="success"
title="Message sent"
description="Ticket PO-2148 is open. You will get a copy by email."
politeness="polite"
onDismiss={() => {
setSent(false);
}}
/>
) : null}
<form className="grid gap-4" onSubmit={onSubmit}>
<div className="grid gap-4 @3xl:grid-cols-2">
<Input
label="Full name"
name="name"
autoComplete="name"
leadingIcon={<LuUser />}
isRequired
errorMessage="Enter your name so we know who to reply to."
/>
<Input
label="Work email"
type="email"
name="email"
autoComplete="email"
leadingIcon={<LuMail />}
placeholder="you@northwind.io"
isRequired
errorMessage="Enter an email address like you@northwind.io."
/>
</div>
<Select
label="Topic"
name="topic"
placeholder="Choose a topic"
isRequired
errorMessage="Choose the topic closest to your question."
>
{TOPICS.map((topic) => (
<SelectOption key={topic.id} id={topic.id} label={topic.label} />
))}
</Select>
<Textarea
label="Message"
name="message"
maxLength={1000}
placeholder="For example: my September payslip is missing the overtime from the 12th."
description="Do not include bank details or passwords."
isRequired
errorMessage="Tell us what you need help with."
/>
<div className="flex flex-wrap items-center justify-between gap-3">
<p className="text-body-small text-muted">All fields are required.</p>
<Button type="submit" size="md" trailingIcon={<LuSend />}>
Send message
</Button>
</div>
</form>
</section>
</div>
</div>
);
}
More forms and data entry blocks
- Add a personCreate a record in a modal.
- Multi-step formLong forms split into steps you can go back to.
- Address and phoneCountry, address lookup and phone with dialling code.
- File uploadDrag files in and watch each one upload.
- Date range pickerChoose a start and end date on a calendar.
- Search with suggestionsType ahead and pick from matching results.
- Terms and consentScrollable terms with a required checkbox.
- Choose an optionPick one option from a short list in a dialog.
- Pick a colourBrand or label colour from swatches or a picker.