Theming

Match the bell, drawer and inbox to your brand from the dashboard, in code or with CSS variables.

The SDK UIs are themed with a ThemeConfig. You can set it in the dashboard (project Settings), pass it in code, or override the resulting CSS variables.

ThemeConfig

Every field is optional.

FieldTypeDefault
colorScheme"light" | "dark" | "system""system"system follows the OS or browser setting live.
primaryColorCSS color#2563ebAccent for unread dots, links, focus rings and buttons.
radiusnumber (px), 0 to 3212Corner radius of the panel, items and buttons.
fontFamilyCSS font stack, up to 200 characterssystem UI stack
lightThemeColorssee belowColors used in light mode.
darkThemeColorssee belowColors used in dark mode.

ThemeColors (each a CSS color string of up to 64 characters):

FieldLight defaultDark defaultUsed for
background#ffffff#0f172aPanel and item background
foreground#0f172a#f1f5f9Text and the bell icon
muted#f1f5f9#1e293bHover backgrounds, tabs
mutedForeground#64748b#94a3b8Secondary text, times
border#e2e8f0#1e293bDividers and outlines
unreadBackground#eff6ff#172554Background of unread items
badgeBackground#ef4444#ef4444Bell badge
badgeForeground#ffffff#ffffffBell badge text
Example
{
  "colorScheme": "system",
  "primaryColor": "#6d28d9",
  "radius": 10,
  "light": { "unreadBackground": "#f5f3ff" },
  "dark": { "background": "#0b0b12", "unreadBackground": "#1e1b4b" }
}

Dashboard theme vs. code theme

Themes are merged field by field, later layers winning, and light/dark are merged key by key. Unset (undefined or null) values never override:

  1. built-in defaults (the tables above);
  2. the dashboard theme, delivered to the SDK with the feed as config.theme;
  3. the theme from code, in the order of each SDK:
    • JavaScript (custom UIs): createNotificationClient({ theme }), resolved with mergeClientTheme;
    • React and React Native: the theme option of a client you pass as client, then <NotificationProvider theme>, then a component's theme prop.

The dashboard theme is a good place for brand colors that designers may tweak without a release. Code themes are best for values that must follow your app, such as forcing colorScheme to match your own dark-mode toggle.

CSS variables (web)

The React components use the stylesheet @notificationstream/js/styles: ns-* markup, with every color, radius and font taken from CSS custom properties. The resolved theme sets those variables, so you can also restyle with plain CSS:

VariableFrom
--ns-primaryprimaryColor
--ns-radiusradius (in px)
--ns-font-familyfontFamily
--ns-background, --ns-foreground, --ns-muted, --ns-muted-foreground, --ns-border, --ns-unread-background, --ns-badge-background, --ns-badge-foregroundthe active scheme's ThemeColors
--ns-panel-width, --ns-panel-max-heightSize of the React popover (width defaults to 380px)

The variables live on .ns-root. Theme values that are set explicitly (in the dashboard or in code) are applied inline, so target the variables you don't set in a theme, or use classNames and unstyled for full control.

The provider injects the stylesheet at the end of <head> when it mounts, after your own CSS, so its defaults would win over rules with the same selector. Load it yourself before your CSS instead:

import "@notificationstream/react/styles.css";
import "./notifications.css"; // your overrides

<NotificationProvider injectStyles={false} /* … */ />;
notifications.css
.ns-root {
  --ns-primary: #7c3aed;
  --ns-radius: 8px;
  --ns-panel-width: 420px;
}
.ns-root[data-color-scheme="dark"] {
  --ns-background: #0b0b0f;
}

Building your own UI

The theme helpers exported by @notificationstream/js (defaultTheme, mergeTheme, mergeClientTheme, resolveTheme, themeToCssVariables, themeConfigToCssVariables) give custom components the same result as the bundled UIs, and @notificationstream/js/styles.css gives them the same look. See the JavaScript SDK.