NotificationListener
A headless SSE listener that fires a callback on each incoming notification and renders no DOM.
01 Usage
Basic
onNotification fires on each message from the stream, and the connection reconnects on
drop with exponential backoff (1s–30s, up to 5 attempts).<script lang="ts">
import { NotificationListener } from '@urbicon-ui/auth';
// `store` is your own notification state — the listener only delivers.
const store = { add: (notification: unknown) => console.log('New notification:', notification) };
</script>
<NotificationListener
onNotification={(n) => store.add(n)}
onReconnect={(attempt) => console.log('Reconnecting…', attempt)}
/>
02 Accessibility
It renders no DOM at all
The component reads the stream off fetch and renders
no markup, so it adds nothing to the accessibility tree and cannot be focused or reached by
a screen reader. It can sit anywhere in the page.
Announcing an arrival is the consumer’s job
Because it renders nothing, a notification arriving over the stream is completely silent
for assistive tech. If arrival should be announced, route onNotification somewhere that speaks: a live region
of your own, a toast, or the NotificationBadge and NotificationCenter this component feeds.
Reconnection is silent
Dropped connections retry with exponential backoff and give up after maxReconnectAttempts, calling the onError and onReconnect callbacks rather than showing any UI. A
stream the server refuses arrives as onRefused with
the machine code, and the code decides what follows: a 429 connection_limit (too many tabs hold one open)
is final, a rate limit waits out Retry-After, a
missing session is retried every 30 seconds, a 5xx keeps the backoff. If a stalled or
refused stream should be visible to the user, building that indicator is your job;
silently missing notifications is the failure mode worth designing against.
03 API Reference
Prop | Type | Default | Description | |
|---|---|---|---|---|
apiPath | string | '/api/notifications/stream' | SSE stream endpoint. Read once when the component mounts; to switch endpoints (e.g. after a user change), unmount and remount the listener. | |
maxReconnectAttempts | number | 5 | Consecutive failed reconnects (a dropped stream, a 5xx) before the listener gives up; a connection that stayed open for 10s starts the count over. Rate limits and a missing session are not counted. Read once at mount. | |
onError | (error: Error) => void | — | Called when the stream drops or cannot be reached at all (network
failure, server closed it) — a reconnect with backoff follows, up to
maxReconnectAttempts in a row. | |
onNotification | (
notification: import('../../../server/adapters/types.js').NotificationRecord
) => void | — | Called when a new notification arrives via SSE. | |
onReconnect | (attempt: number) => void | — | Called when a reconnection attempt starts. Receives current attempt number. | |
onRefused | (code: string | undefined, status: number) => void | — | Called when the server answers the stream request with a non-2xx status,
or with a 2xx that is not text/event-stream (code is then
undefined). code is the machine code from the JSON body; map it
through errorMessageFromCode for the localized sentence. What follows
depends on it: rate_limited waits out Retry-After, not_authenticated
retries every 30s, a 5xx keeps the backoff; everything else —
connection_limit (the per-user cap on concurrent streams, cleared only
by closing a tab), 403, 404, a body without a code — is final. |
04 Types
Local type definitions used by this component.
Name | Kind | Category | Used by | Description | |
|---|---|---|---|---|---|
NotificationListenerProps | interface | props | 0 | — |
05 Installation
Import
import { NotificationListener } from '@urbicon-ui/auth';