Open enrolment for 2027 benefits runs from 1 to 30 November.Read more
Company news
Pin one announcement as a banner for everyone at Northwind.
Open enrolment for 2027 benefits runs from 1 to 30 November.
Posted by People Ops · 7 Oct
October payroll closes early on Friday 23 October. Submit expenses by 17:00.
Posted by Finance · 5 Oct
The London office is closed on Monday 12 October for floor works. Work from home.
Posted by Workplace · 2 Oct
announcement.tsx
"use client";
import { useState } from "react";
import { LuMegaphone, LuPin } from "react-icons/lu";
import { Banner, Button } from "@nexera-ui/react";
type Tone = "info" | "warning" | "danger" | "brand";
interface News {
id: string;
tone: Tone;
message: string;
link: string;
posted: string;
}
const NEWS: News[] = [
{
id: "enrolment",
tone: "brand",
message: "Open enrolment for 2027 benefits runs from 1 to 30 November.",
link: "#benefits-guide",
posted: "Posted by People Ops · 7 Oct",
},
{
id: "payroll",
tone: "warning",
message: "October payroll closes early on Friday 23 October. Submit expenses by 17:00.",
link: "#payroll-calendar",
posted: "Posted by Finance · 5 Oct",
},
{
id: "office",
tone: "info",
message: "The London office is closed on Monday 12 October for floor works. Work from home.",
link: "#office-updates",
posted: "Posted by Workplace · 2 Oct",
},
];
/** Announcement: a company-wide banner above the app, dismissible, with a list to choose which news is pinned. */
export default function Announcement() {
const [pinned, setPinned] = useState<string | null>("enrolment");
const current = NEWS.find((n) => n.id === pinned);
return (
<div className="@container bg-page">
{current ? (
<Banner
tone={current.tone}
message={current.message}
action={<a href={current.link}>Read more</a>}
onDismiss={() => {
setPinned(null);
}}
dismissLabel="Dismiss announcement"
/>
) : null}
<div className="mx-auto grid w-full max-w-3xl gap-4 px-4 py-8 @3xl:px-8">
<header className="flex flex-wrap items-end justify-between gap-3">
<div className="grid gap-1">
<h2 className="text-heading-h3 text-primary">Company news</h2>
<p className="text-body-default text-secondary">
Pin one announcement as a banner for everyone at Northwind.
</p>
</div>
{current ? null : (
<Button
variant="secondary"
leadingIcon={<LuMegaphone />}
onPress={() => {
setPinned(NEWS[0]?.id ?? null);
}}
>
Show banner again
</Button>
)}
</header>
<ul className="m-0 grid list-none gap-3 p-0">
{NEWS.map((n) => (
<li
key={n.id}
className="flex flex-col gap-3 rounded-xl border border-default bg-surface p-4 shadow-xs @3xl:flex-row @3xl:items-center"
>
<div className="grid min-w-0 flex-1 gap-1">
<p className="text-body-strong text-primary">{n.message}</p>
<p className="text-body-small text-secondary">{n.posted}</p>
</div>
<Button
variant={pinned === n.id ? "primary" : "secondary"}
leadingIcon={<LuPin />}
aria-pressed={pinned === n.id}
onPress={() => {
setPinned(n.id);
}}
className="self-start @3xl:self-center"
>
{pinned === n.id ? "Pinned" : "Pin as banner"}
</Button>
</li>
))}
</ul>
</div>
</div>
);
}
More messaging and collaboration blocks
- ChatOne conversation with bubbles, reactions and a composer.
- InboxConversation list beside the open chat.
- Helpdesk assistantAsk HR or support a question and get answers.
- Comment threadDiscuss a record with replies and reactions.
- Notification centreUnread notifications in a popover.
- Document editorWrite and format text with links and lists.
- Day separators and system notesShow who joined and where each day starts.