Mood check-in
A quick daily or weekly pulse.
Built with
- Alert
- Badge
- Button
- MOODS
- MoodOption
- MoodOptionGroup
- Textarea
Weekly check-in · Week of 5 October
Hi Ayesha, how was your week?
mood-checkin.tsx
"use client";
import { useState, type SyntheticEvent } from "react";
import { LuCheck } from "react-icons/lu";
import {
Alert,
Badge,
Button,
MOODS,
MoodOption,
MoodOptionGroup,
Textarea,
type Mood,
} from "@nexera-ui/react";
const LABELS: Record<Mood, string> = {
"very-bad": "Very bad",
bad: "Bad",
okay: "Okay",
good: "Good",
great: "Great",
};
const TONES = {
"very-bad": "danger",
bad: "warning",
okay: "neutral",
good: "success",
great: "success",
} as const;
const HISTORY: { week: string; mood: Mood }[] = [
{ week: "Week of 28 Sep", mood: "good" },
{ week: "Week of 21 Sep", mood: "okay" },
{ week: "Week of 14 Sep", mood: "bad" },
{ week: "Week of 7 Sep", mood: "great" },
];
/** Mood check-in: a quick weekly pulse with five moods and an optional note, plus the last few check-ins. */
export default function MoodCheckIn() {
const [mood, setMood] = useState<Mood | null>(null);
const [sent, setSent] = useState(false);
const onSubmit = (event: SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
setSent(true); // replace with your check-in request
};
return (
<div className="@container bg-page px-4 py-8 @3xl:px-8">
<div className="mx-auto grid max-w-4xl gap-6 @3xl:grid-cols-[minmax(0,2fr)_minmax(0,1fr)]">
<section
aria-labelledby="checkin-title"
className="grid content-start gap-5 rounded-xl border border-default bg-surface p-5 shadow-sm @3xl:p-8"
>
<header className="grid gap-1">
<p className="text-body-small text-secondary">Weekly check-in · Week of 5 October</p>
<h2 id="checkin-title" className="text-heading-h3 text-primary">
Hi Ayesha, how was your week?
</h2>
</header>
{sent ? (
<Alert
tone="success"
title="Check-in saved"
description={
mood === "bad" || mood === "very-bad"
? "Sorry to hear that. Your manager will offer a 1:1 this week."
: "See you next Friday."
}
politeness="polite"
onDismiss={() => {
setSent(false);
}}
/>
) : (
<form className="grid gap-5" onSubmit={onSubmit}>
<MoodOptionGroup
label="Your mood this week"
name="mood"
value={mood}
onChange={setMood}
isRequired
errorMessage="Choose the mood closest to your week."
>
{MOODS.map((m) => (
<MoodOption key={m} mood={m} label={LABELS[m]} />
))}
</MoodOptionGroup>
<Textarea
label="Anything on your mind?"
name="note"
maxLength={280}
placeholder="For example: the release crunch made Thursday long."
description="Optional. Only your manager can read this."
/>
<div className="flex justify-end">
<Button type="submit" size="md" leadingIcon={<LuCheck />}>
Save check-in
</Button>
</div>
</form>
)}
</section>
<aside
aria-labelledby="history-title"
className="grid content-start gap-3 rounded-xl border border-default bg-surface p-5"
>
<h3 id="history-title" className="text-heading-h4 text-primary">
Your last check-ins
</h3>
<ul className="grid divide-y divide-subtle">
{HISTORY.map((entry) => (
<li
key={entry.week}
className="flex flex-wrap items-center justify-between gap-2 py-2.5"
>
<span className="text-body-small text-secondary">{entry.week}</span>
<Badge label={LABELS[entry.mood]} tone={TONES[entry.mood]} />
</li>
))}
</ul>
</aside>
</div>
</div>
);
}