Docs Components Advanced

NotificationCenter

React example follows below.
ts
/**
* NotificationCenter's pinned demo state (CSP-D3).
*
* Two groups with a deliberate read/unread mix: the first group leads with
* two unread rows (so the header badge reads "2", "Mark all read" is enabled,
* and the unread dot + "Unread: " screen-reader prefix + `data-unread` row
* attribute all render) and closes with a read one; the second group is
* entirely read (so the read row styling is visible next to the unread).
* All five `kind`s appear exactly once, which puts every branch of the
* per-kind glyph switch on screen in a single render.
*
* Ids are fixture-supplied and stable — never a counter or `Math.random()`
* so the rendered `key`/dismiss target is identical in all five frameworks
* and across repeat mounts, the same rule the toast batch set.
*/
const notificationCenterFixture = {
id: "notification-center",
title: "Notifications",
items: [
{
id: "notif-deploy-ledger",
group: "Today",
kind: "deploy",
message: "ledger-api v2.4.1 deployed to iad",
time: "12m ago",
unread: true,
},
{
id: "notif-alert-latency",
group: "Today",
kind: "alert",
message: "p99 latency above 400ms on checkout",
time: "34m ago",
unread: true,
},
{
id: "notif-mention-review",
group: "Today",
kind: "mention",
message: "Priya mentioned you in #payments-oncall",
time: "2h ago",
unread: false,
},
{
id: "notif-pr-merged",
group: "Yesterday",
kind: "pr",
message: "Merged: retry budget per tenant",
time: "19h ago",
unread: false,
},
{
id: "notif-error-webhook",
group: "Yesterday",
kind: "error",
message: "Webhook delivery failed 3× for acme-co",
time: "22h ago",
unread: false,
},
],
} satisfies {
id: string;
title: string;
items: {
id: string;
group: string;
kind: "deploy" | "alert" | "mention" | "pr" | "error";
message: string;
time: string;
unread: boolean;
}[];
};
import { NotificationCenter } from "@grassroot/ui-react/advanced";
export default function NotificationCenterDemo() {
return (
<div>
<NotificationCenter
defaultItems={notificationCenterFixture.items}
title={notificationCenterFixture.title}
/>
</div>
);
}
ts
<script setup lang="ts">
/**
* NotificationCenter's pinned demo state (CSP-D3).
*
* Two groups with a deliberate read/unread mix: the first group leads with
* two unread rows (so the header badge reads "2", "Mark all read" is enabled,
* and the unread dot + "Unread: " screen-reader prefix + `data-unread` row
* attribute all render) and closes with a read one; the second group is
* entirely read (so the read row styling is visible next to the unread).
* All five `kind`s appear exactly once, which puts every branch of the
* per-kind glyph switch on screen in a single render.
*
* Ids are fixture-supplied and stable — never a counter or `Math.random()`
* so the rendered `key`/dismiss target is identical in all five frameworks
* and across repeat mounts, the same rule the toast batch set.
*/
const notificationCenterFixture = {
id: "notification-center",
title: "Notifications",
items: [
{
id: "notif-deploy-ledger",
group: "Today",
kind: "deploy",
message: "ledger-api v2.4.1 deployed to iad",
time: "12m ago",
unread: true,
},
{
id: "notif-alert-latency",
group: "Today",
kind: "alert",
message: "p99 latency above 400ms on checkout",
time: "34m ago",
unread: true,
},
{
id: "notif-mention-review",
group: "Today",
kind: "mention",
message: "Priya mentioned you in #payments-oncall",
time: "2h ago",
unread: false,
},
{
id: "notif-pr-merged",
group: "Yesterday",
kind: "pr",
message: "Merged: retry budget per tenant",
time: "19h ago",
unread: false,
},
{
id: "notif-error-webhook",
group: "Yesterday",
kind: "error",
message: "Webhook delivery failed 3× for acme-co",
time: "22h ago",
unread: false,
},
],
} satisfies {
id: string;
title: string;
items: {
id: string;
group: string;
kind: "deploy" | "alert" | "mention" | "pr" | "error";
message: string;
time: string;
unread: boolean;
}[];
};
import { NotificationCenter } from "@grassroot/ui-vue";
</script>
<template>
<div>
<NotificationCenter
:default-items="notificationCenterFixture.items"
:title="notificationCenterFixture.title"
/>
</div>
</template>
ts
import { Component } from "@angular/core";
/**
* NotificationCenter's pinned demo state (CSP-D3).
*
* Two groups with a deliberate read/unread mix: the first group leads with
* two unread rows (so the header badge reads "2", "Mark all read" is enabled,
* and the unread dot + "Unread: " screen-reader prefix + `data-unread` row
* attribute all render) and closes with a read one; the second group is
* entirely read (so the read row styling is visible next to the unread).
* All five `kind`s appear exactly once, which puts every branch of the
* per-kind glyph switch on screen in a single render.
*
* Ids are fixture-supplied and stable — never a counter or `Math.random()`
* so the rendered `key`/dismiss target is identical in all five frameworks
* and across repeat mounts, the same rule the toast batch set.
*/
const notificationCenterFixture = {
id: "notification-center",
title: "Notifications",
items: [
{
id: "notif-deploy-ledger",
group: "Today",
kind: "deploy",
message: "ledger-api v2.4.1 deployed to iad",
time: "12m ago",
unread: true,
},
{
id: "notif-alert-latency",
group: "Today",
kind: "alert",
message: "p99 latency above 400ms on checkout",
time: "34m ago",
unread: true,
},
{
id: "notif-mention-review",
group: "Today",
kind: "mention",
message: "Priya mentioned you in #payments-oncall",
time: "2h ago",
unread: false,
},
{
id: "notif-pr-merged",
group: "Yesterday",
kind: "pr",
message: "Merged: retry budget per tenant",
time: "19h ago",
unread: false,
},
{
id: "notif-error-webhook",
group: "Yesterday",
kind: "error",
message: "Webhook delivery failed 3× for acme-co",
time: "22h ago",
unread: false,
},
],
} satisfies {
id: string;
title: string;
items: {
id: string;
group: string;
kind: "deploy" | "alert" | "mention" | "pr" | "error";
message: string;
time: string;
unread: boolean;
}[];
};
import { GrassrootNotificationCenter } from "@grassroot/ui-angular";
// Every input is a `[property]` binding, never a static attribute. Angular
// leaves static template attributes on the host element in the rendered DOM,
// and `title` is a real global attribute — `title="Notifications"` would ship
// a browser tooltip over the whole panel that React/Vue/Solid/Svelte, which
// consume `title` as a declared prop, never render.
@Component({
selector: "app-notification-center-demo",
standalone: true,
imports: [GrassrootNotificationCenter],
template: `
<div>
<grassroot-notification-center [defaultItems]="items" [title]="title" />
</div>
`,
})
export class NotificationCenterDemoComponent {
protected readonly items = notificationCenterFixture.items;
protected readonly title = notificationCenterFixture.title;
}
export default NotificationCenterDemoComponent;
ts
<script lang="ts">
/**
* NotificationCenter's pinned demo state (CSP-D3).
*
* Two groups with a deliberate read/unread mix: the first group leads with
* two unread rows (so the header badge reads "2", "Mark all read" is enabled,
* and the unread dot + "Unread: " screen-reader prefix + `data-unread` row
* attribute all render) and closes with a read one; the second group is
* entirely read (so the read row styling is visible next to the unread).
* All five `kind`s appear exactly once, which puts every branch of the
* per-kind glyph switch on screen in a single render.
*
* Ids are fixture-supplied and stable — never a counter or `Math.random()`
* so the rendered `key`/dismiss target is identical in all five frameworks
* and across repeat mounts, the same rule the toast batch set.
*/
const notificationCenterFixture = {
id: "notification-center",
title: "Notifications",
items: [
{
id: "notif-deploy-ledger",
group: "Today",
kind: "deploy",
message: "ledger-api v2.4.1 deployed to iad",
time: "12m ago",
unread: true,
},
{
id: "notif-alert-latency",
group: "Today",
kind: "alert",
message: "p99 latency above 400ms on checkout",
time: "34m ago",
unread: true,
},
{
id: "notif-mention-review",
group: "Today",
kind: "mention",
message: "Priya mentioned you in #payments-oncall",
time: "2h ago",
unread: false,
},
{
id: "notif-pr-merged",
group: "Yesterday",
kind: "pr",
message: "Merged: retry budget per tenant",
time: "19h ago",
unread: false,
},
{
id: "notif-error-webhook",
group: "Yesterday",
kind: "error",
message: "Webhook delivery failed 3× for acme-co",
time: "22h ago",
unread: false,
},
],
} satisfies {
id: string;
title: string;
items: {
id: string;
group: string;
kind: "deploy" | "alert" | "mention" | "pr" | "error";
message: string;
time: string;
unread: boolean;
}[];
};
import { NotificationCenter } from "@grassroot/ui-svelte";
</script>
<div>
<NotificationCenter
defaultItems={notificationCenterFixture.items}
title={notificationCenterFixture.title}
/>
</div>
ts
/** @jsxImportSource solid-js */
/**
* NotificationCenter's pinned demo state (CSP-D3).
*
* Two groups with a deliberate read/unread mix: the first group leads with
* two unread rows (so the header badge reads "2", "Mark all read" is enabled,
* and the unread dot + "Unread: " screen-reader prefix + `data-unread` row
* attribute all render) and closes with a read one; the second group is
* entirely read (so the read row styling is visible next to the unread).
* All five `kind`s appear exactly once, which puts every branch of the
* per-kind glyph switch on screen in a single render.
*
* Ids are fixture-supplied and stable — never a counter or `Math.random()`
* so the rendered `key`/dismiss target is identical in all five frameworks
* and across repeat mounts, the same rule the toast batch set.
*/
const notificationCenterFixture = {
id: "notification-center",
title: "Notifications",
items: [
{
id: "notif-deploy-ledger",
group: "Today",
kind: "deploy",
message: "ledger-api v2.4.1 deployed to iad",
time: "12m ago",
unread: true,
},
{
id: "notif-alert-latency",
group: "Today",
kind: "alert",
message: "p99 latency above 400ms on checkout",
time: "34m ago",
unread: true,
},
{
id: "notif-mention-review",
group: "Today",
kind: "mention",
message: "Priya mentioned you in #payments-oncall",
time: "2h ago",
unread: false,
},
{
id: "notif-pr-merged",
group: "Yesterday",
kind: "pr",
message: "Merged: retry budget per tenant",
time: "19h ago",
unread: false,
},
{
id: "notif-error-webhook",
group: "Yesterday",
kind: "error",
message: "Webhook delivery failed 3× for acme-co",
time: "22h ago",
unread: false,
},
],
} satisfies {
id: string;
title: string;
items: {
id: string;
group: string;
kind: "deploy" | "alert" | "mention" | "pr" | "error";
message: string;
time: string;
unread: boolean;
}[];
};
import { NotificationCenter } from "@grassroot/ui-solid";
export default function NotificationCenterDemo() {
return (
<div>
<NotificationCenter
defaultItems={notificationCenterFixture.items}
title={notificationCenterFixture.title}
/>
</div>
);
}

Installation

API Reference

Import

import { NotificationCenter } from "@grassroot/ui-react/advanced";

Props

Prop
Type
Default
Requirement
items
NotificationItem[] | undefined
optional
defaultItems
NotificationItem[] | undefined
optional
onItemsChange
((next: NotificationItem[]) => void) | undefined
optional
onOpen
((id: string) => void) | undefined
optional
title
string | undefined
optional
Prop
items
Type
NotificationItem[] | undefined
Default
Requirement
optional
Prop
defaultItems
Type
NotificationItem[] | undefined
Default
Requirement
optional
Prop
onItemsChange
Type
((next: NotificationItem[]) => void) | undefined
Default
Requirement
optional
Prop
onOpen
Type
((id: string) => void) | undefined
Default
Requirement
optional
Prop
title
Type
string | undefined
Default
Requirement
optional

Events

EventPayload
onItemsChange((next: NotificationItem[]) => void) | undefined
onOpen((id: string) => void) | undefined

Native attributes

Standard DOM and ARIA attributes not listed above spread onto the root element.

Import

import { NotificationCenter } from "@grassroot/ui-vue";

Props

Prop
Type
Default
Requirement
items
NotificationItem<string>[] | undefined
optional
defaultItems
NotificationItem<string>[] | undefined
() => []
optional
title
string | undefined
"Notifications"
optional
Prop
items
Type
NotificationItem<string>[] | undefined
Default
Requirement
optional
Prop
defaultItems
Type
NotificationItem<string>[] | undefined
Default
() => []
Requirement
optional
Prop
title
Type
string | undefined
Default
"Notifications"
Requirement
optional

Events

EventPayload
itemsChange[next: NotificationItem[]]
open[id: string]

Import

import { Component } from "@angular/core";
import { GrassrootNotificationCenter } from "@grassroot/ui-angular";

Props

Prop
Type
Default
Requirement
items
NotificationItem[]
optional
defaultItems
NotificationItem[]
[]
optional
title
string
"Notifications"
optional
Prop
items
Type
NotificationItem[]
Default
Requirement
optional
Prop
defaultItems
Type
NotificationItem[]
Default
[]
Requirement
optional
Prop
title
Type
string
Default
"Notifications"
Requirement
optional

Events

EventPayload
itemsChangeNotificationItem[]
openstring

Import

import { NotificationCenter } from "@grassroot/ui-svelte";

Props

Prop
Type
Default
Requirement
items
NotificationItem[]
optional
defaultItems
NotificationItem[]
optional
onItemsChange
(next: NotificationItem[]) => void
optional
onOpen
(id: string) => void
optional
title
string
"Notifications"
optional
className
string
optional
Prop
items
Type
NotificationItem[]
Default
Requirement
optional
Prop
defaultItems
Type
NotificationItem[]
Default
Requirement
optional
Prop
onItemsChange
Type
(next: NotificationItem[]) => void
Default
Requirement
optional
Prop
onOpen
Type
(id: string) => void
Default
Requirement
optional
Prop
title
Type
string
Default
"Notifications"
Requirement
optional
Prop
className
Type
string
Default
Requirement
optional

Events

EventPayload
onItemsChange(next: NotificationItem[]) => void
onOpen(id: string) => void

Import

import { NotificationCenter } from "@grassroot/ui-solid";

Props

Prop
Type
Default
Requirement
items
NotificationItem[]
optional
defaultItems
NotificationItem[]
optional
onItemsChange
(next: NotificationItem[]) => void
optional
onOpen
(id: string) => void
optional
title
string
"Notifications"
optional
className
string
optional
Prop
items
Type
NotificationItem[]
Default
Requirement
optional
Prop
defaultItems
Type
NotificationItem[]
Default
Requirement
optional
Prop
onItemsChange
Type
(next: NotificationItem[]) => void
Default
Requirement
optional
Prop
onOpen
Type
(id: string) => void
Default
Requirement
optional
Prop
title
Type
string
Default
"Notifications"
Requirement
optional
Prop
className
Type
string
Default
Requirement
optional

Events

EventPayload
onItemsChange(next: NotificationItem[]) => void
onOpen(id: string) => void