Notification preferences

Pro

What reaches you, and where: one row per kind of event, one column per channel. A cell the service requires (an approval that waits on you, by email) is locked on and says why; a channel that isn't connected is locked off and says how to connect it.

Markdown

Preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/notification-preferences

Brings in: locale, locked, terms, utils

Usage

TSX · The example above
"use client"

import * as React from "react"
import { NotificationPreferences, type NoticePrefs } from "@/components/notification-preferences"

export default function Example() {
  const [prefs, setPrefs] = React.useState<NoticePrefs>({
    approval: { app: true, email: true },
    finished: { app: true },
    failed: { app: true, email: true },
  })
  return (
    <NotificationPreferences
      className="max-w-2xl"
      events={[
        { id: "approval", label: "An approval waits on me" },
        { id: "finished", label: "A run I started finishes" },
        { id: "failed", label: "A run I started fails", detail: "Including migrations that stop part way" },
      ]}
      channels={["app", "email", "slack"]}
      value={prefs}
      onChange={(e, c, on) => setPrefs((p) => ({ ...p, [e]: { ...p[e], [c]: on } }))}
      locked={{
        approval: { email: "Approvals that wait on you always email, so none expire unseen.", slack: "Connect Slack in Settings › Channels first." },
        finished: { slack: "Connect Slack in Settings › Channels first." },
        failed: { slack: "Connect Slack in Settings › Channels first." },
      }}
    />
  )
}

<NotificationPreferences>

PropTypeDefaultDescription
eventsrequiredNoticeEvent[]—The kinds of event, one row each.
channelsrequiredNoticeChannel[]—The channels, one column each.
valuerequiredNoticePrefs—Which cells are on, by event id and channel; a missing cell is off.
onChangerequired(eventId: string, channel: NoticeChannel, on: boolean) => void—Called with the event id, channel and new state when a cell is toggled.
lockedRecord<string, Partial<Record<NoticeChannel, string | undefined>>> | undefined{}Reasons a cell can't be changed, by event id and channel.
classNamestring | undefined—Extra classes for the outer element.

Strings

The fixed words, in English by default. Change any of them under notificationPreferences in <LocaleProvider strings={{ … }}>; the table is exported as notificationPreferencesStrings.

KeyEnglish
labelNotification preferences
tellMeWhenTell me when…
inProductIn {product}
emailEmail
cell{event}: {channel}

Types

NoticeChannel
"app" | "email" | "slack"
NoticeEvent
{ id: string; label: string; detail?: string | undefined }
NoticePrefs
Record<string, Partial<Record<NoticeChannel, boolean>>>