Helpdesk assistant
Ask HR or support a question and get answers.
HR helpdesk
Questions from employees, answered by People Ops. System notes track every status change.
Ayesha Khan
Ticket #1042 · Leave · Open
Ayesha Khan
Hi Sara, can I take Friday 17 Oct off for a family event?
Ayesha Khan:
I have 12 days of annual leave left.
Sara Malik assigned this ticket to herself
Sara Malik:
Ayesha KhanCan I take Friday 17 Oct off?
Approved. Enjoy the long weekend.
Read
Sara Malik:
I have added it to the team calendar.
Read
Ayesha is typing
Enter sends the message. Shift+Enter adds a new line.
helpdesk-assistant.tsx
"use client";
import { useState } from "react";
import { LuCircleCheck, LuEllipsis, LuSearch, LuUserCheck } from "react-icons/lu";
import {
Avatar,
Badge,
Button,
ChatHeader,
Composer,
DateSeparator,
IconButton,
Menu,
MenuItem,
MessageBubble,
Presence,
SystemMessage,
Tooltip,
TooltipTrigger,
TypingIndicator,
} from "@nexera-ui/react";
/** HR helpdesk: an employee's question as a ticket, the People Ops answer, status notes and the ticket details. */
export default function HelpdeskAssistant() {
const [resolved, setResolved] = useState(false);
const [log, setLog] = useState<{ kind: "message" | "system"; text: string }[]>([]);
const toggle = () => {
setLog((l) => [
...l,
{ kind: "system", text: `Sara Malik ${resolved ? "reopened" : "resolved"} this ticket` },
]);
setResolved((r) => !r);
};
const ayesha = <Avatar size="md" initials="AK" isDecorative />;
const status = resolved ? "Resolved" : "Open";
return (
<div className="@container bg-page px-4 py-8 @3xl:px-8">
<header className="mb-4 grid gap-1">
<h2 className="text-heading-h3 text-primary">HR helpdesk</h2>
<p className="text-body-default text-secondary">
Questions from employees, answered by People Ops. System notes track every status change.
</p>
</header>
<div className="flex flex-col overflow-hidden rounded-xl border border-default bg-surface shadow-sm @5xl:flex-row">
<section
aria-label="Conversation with Ayesha Khan"
className="flex h-[600px] min-w-0 flex-1 flex-col"
>
<ChatHeader
name="Ayesha Khan"
headingLevel={3}
status={`Ticket #1042 · Leave · ${status}`}
avatar={
<Avatar size="md" initials="AK" isDecorative presence={<Presence isDecorative />} />
}
actions={
<>
<TooltipTrigger delay={200}>
<IconButton
variant="ghost"
aria-label="Search in conversation"
icon={<LuSearch />}
/>
<Tooltip>Search in conversation</Tooltip>
</TooltipTrigger>
<Menu
trigger={
<IconButton variant="ghost" aria-label="More options" icon={<LuEllipsis />} />
}
>
<MenuItem
id="resolve"
label={resolved ? "Reopen ticket" : "Resolve ticket"}
onAction={toggle}
/>
</Menu>
</>
}
/>
<div
role="log"
aria-label="Messages"
className="flex min-h-0 flex-1 flex-col gap-1.5 overflow-y-auto p-4"
>
<DateSeparator label="Today" dateTime="2026-10-14" />
<MessageBubble
name="Ayesha Khan"
avatar={ayesha}
time="10:24"
dateTime="2026-10-14T10:24"
>
Hi Sara, can I take Friday 17 Oct off for a family event?
</MessageBubble>
<MessageBubble
name="Ayesha Khan"
avatar={ayesha}
group="continued"
time="10:24"
dateTime="2026-10-14T10:24"
>
I have 12 days of annual leave left.
</MessageBubble>
<SystemMessage icon={<LuUserCheck />} className="self-start">
Sara Malik assigned this ticket to herself
</SystemMessage>
<MessageBubble
direction="outgoing"
type="reply"
quote="Can I take Friday 17 Oct off?"
quoteAuthor="Ayesha Khan"
name="Sara Malik"
time="10:31"
dateTime="2026-10-14T10:31"
status="read"
>
Approved. Enjoy the long weekend.
</MessageBubble>
<MessageBubble
direction="outgoing"
group="continued"
name="Sara Malik"
time="10:31"
dateTime="2026-10-14T10:31"
status="read"
>
I have added it to the team calendar.
</MessageBubble>
{log.map((item, i) =>
item.kind === "system" ? (
<SystemMessage key={i} icon={<LuCircleCheck />} className="self-start">
{item.text}
</SystemMessage>
) : (
<MessageBubble
key={i}
direction="outgoing"
name="Sara Malik"
time="Now"
status="sent"
>
{item.text}
</MessageBubble>
),
)}
{resolved ? null : <TypingIndicator>Ayesha is typing</TypingIndicator>}
</div>
<div className="border-t border-default">
<Composer
aria-label="Reply to Ayesha Khan"
placeholder="Reply to Ayesha Khan"
onSend={(text) => {
setLog((l) => [...l, { kind: "message", text }]);
}}
onAttach={() => {
setLog((l) => [...l, { kind: "message", text: "Attachment: Leave request.pdf" }]);
}}
/>
</div>
</section>
<aside
aria-labelledby="ticket-title"
className="grid content-start gap-4 border-t border-default p-4 @5xl:w-72 @5xl:shrink-0 @5xl:border-s @5xl:border-t-0"
>
<h3 id="ticket-title" className="text-body-strong text-primary">
Ticket #1042
</h3>
<dl className="m-0 grid gap-3 text-body-small">
<div className="flex items-center gap-4">
<dt className="w-20 text-muted">Status</dt>
<dd className="m-0">
<Badge tone={resolved ? "neutral" : "success"} label={status} />
</dd>
</div>
{[
["Category", "Leave"],
["Priority", "Normal"],
["Assignee", "Sara Malik"],
["SLA", "Reply within 4 h"],
].map(([label, value]) => (
<div key={label} className="flex items-center gap-4">
<dt className="w-20 text-muted">{label}</dt>
<dd className="m-0 text-body-strong text-primary">{value}</dd>
</div>
))}
</dl>
<Button variant="secondary" onPress={toggle}>
{resolved ? "Reopen ticket" : "Resolve ticket"}
</Button>
</aside>
</div>
</div>
);
}
More messaging and collaboration blocks
- ChatOne conversation with bubbles, reactions and a composer.
- InboxConversation list beside the open chat.
- Comment threadDiscuss a record with replies and reactions.
- Notification centreUnread notifications in a popover.
- AnnouncementA banner for news that affects everyone.
- Document editorWrite and format text with links and lists.
- Day separators and system notesShow who joined and where each day starts.