Skip to content
weftGitHub

NotificationPreferences

A grid of what to be told about, and how.

SourcePackage @weft-js/warp

Preview

tsx
import { NotificationPreferences } from '@weft-js/warp'import type { PrefGroup } from '@weft-js/warp-core'export function Weft() {  return (    <NotificationPreferences groups={PREF_GROUPS} channels={CHANNELS} value={PREFS} offered={PREF_OFFERED} locked={PREF_LOCKED} defaults={{ value: PREFS }} onChange={() => pause(400)} onDigest={() => pause(400)} />  )}const CHANNELS = [{ id: 'inapp', label: 'In-app' }, { id: 'email', label: 'Email' }, { id: 'push', label: 'Push' }, { id: 'sms', label: 'SMS' }]const PREF_GROUPS: PrefGroup[] = [  { id: 'deploys', label: 'Deploys', events: [{ id: 'failed', label: 'Failed deploys', hint: 'A deploy you own fails a check' }, { id: 'live', label: 'Deploys gone live', hint: 'On projects you watch' }, { id: 'approve', label: 'Approvals', hint: 'A release needs your yes' }] },  { id: 'team', label: 'Team', events: [{ id: 'mention', label: 'Mentions', hint: 'Someone @-mentions you' }, { id: 'invite', label: 'Invitations', hint: 'New events and changes' }] },  { id: 'account', label: 'Account', events: [{ id: 'security', label: 'Security alerts', hint: 'New sign-in or API key', instant: true }, { id: 'billing', label: 'Billing', hint: 'Invoices and failed payments' }] },]const PREFS = {  failed: { inapp: true, email: true, push: true, sms: true }, live: { inapp: true, email: false, push: false }, approve: { inapp: true, email: true, push: true },  mention: { inapp: true, email: true, push: true, sms: false }, invite: { inapp: true, email: true },  security: { inapp: true, email: true, push: true, sms: true }, billing: { inapp: false, email: true },}const PREF_OFFERED = { live: ['inapp', 'email', 'push'], approve: ['inapp', 'email', 'push'], invite: ['inapp', 'email'], billing: ['inapp', 'email'] }const PREF_LOCKED = { security: ['email'] }const pause = (ms: number) => new Promise(done => { setTimeout(done, ms) })

Installation

npm install @weft-js/warp

Usage

tsx
import { NotificationPreferences } from '@weft-js/warp'<NotificationPreferences groups={PREF_GROUPS} channels={CHANNELS} value={PREFS} offered={PREF_OFFERED} locked={PREF_LOCKED} defaults={{ value: PREFS }} onChange={() => pause(400)} onDigest={() => pause(400)} />

Accessibility

Arrowkeys
Move between cells
Space
Toggles a cell
  • It is one grid with one tab stop. A channel an event cannot use still takes focus and says so.
  • Below 560px the same rows restack.

API Reference

PropTypeDefaultDescription
titlestring'Notification preferences'The grid's name: the id of a heading, else this text is rendered in a visually hidden one.
groupsPrefGroup[]—The events, grouped.
channelsPrefChannel[]—The columns.
valuePrefValues | { value: PrefValues; } | (() => PrefValues)—What is on: event, then channel.
offeredRecord<string, string[]>—Which channels an event can use. Unlisted events can use all.
lockedRecord<string, string[]>—Which channels an event must use.
lockReasonstring'Required: this alert always goes to your account.'Why a box is locked.
digeststring'instant'How often the digest channel sends.
digestChannelstring'email'The channel the digest applies to.
digests{ value: string; label: string; }[]DIGESTSThe email delivery choices, such as instant, hourly or daily.
defaults{ value: PrefValues; digest?: string | undefined; }—Enables Reset to defaults.
EventTypeDefaultDescription
onChange((changes: PrefChange[]) => void | Promise<unknown>)—A rejected promise flips the cells back and says why.
onDigest((digest: string) => void | Promise<unknown>)—Called with the delivery picked. A rejected promise puts the old one back.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="prefs-matrix"] [data-part="sr-only"]

sr-onlych-namenagridheadcornerch-headrowsgrouplockfooterstatus

RelatedInboxPush soft ask