TeqBench
Getting started

Configure the severity theme


6 min readupdated April 2026

The severity theme package is the foundation every other @teqbench Material component depends on for coloring. It ships six CSS custom-property pairs (one background + text per tier), a pure-CSS .tbx-mat-severity-inverted class that flips background and text across the set, and an Angular provider that toggles the invert state at bootstrap. Wiring it up is three short steps.

Install the package

From an already-authenticated project (see Install & authenticate):

npm install @teqbench/tbx-mat-severity-theme

The package has a peer dependency on Angular Material, so if your app doesn't already have @angular/material installed, add it in the same step.

Import the SCSS partial

The theme's color tokens are shipped as an SCSS partial, not a global stylesheet. @use it once in your application's root styles — loading the partial emits the base --tbx-mat-severity-<level>-<slot> pairs on html automatically, so every descendant selector can reference them:

@use '@teqbench/tbx-mat-severity-theme/styles/tbx-mat-severity-theme';

After the load, these custom properties are defined on <html> and available to any descendant selector:

--tbx-mat-severity-default-background
--tbx-mat-severity-default-text
--tbx-mat-severity-success-background
--tbx-mat-severity-success-text
--tbx-mat-severity-error-background
--tbx-mat-severity-error-text
--tbx-mat-severity-warning-background
--tbx-mat-severity-warning-text
--tbx-mat-severity-information-background
--tbx-mat-severity-information-text
--tbx-mat-severity-help-background
--tbx-mat-severity-help-text

The default tier aliases Angular Material's --mat-sys-inverse-surface and --mat-sys-inverse-on-surface so it automatically stays aligned with your M3 theme. The five colored tiers (success, error, warning, information, help) use fixed brand-conventional colors with white text.

Use the tokens in your own components

Reference them like any other CSS variable. For a panel that colors itself by severity:

.severity-panel {
  background: var(--tbx-mat-severity-default-background);
  color: var(--tbx-mat-severity-default-text);
}

.severity-panel[data-severity='success'] {
  background: var(--tbx-mat-severity-success-background);
  color: var(--tbx-mat-severity-success-text);
}

.severity-panel[data-severity='error'] {
  background: var(--tbx-mat-severity-error-background);
  color: var(--tbx-mat-severity-error-text);
}

The bound value on [data-severity] should be one of the six TbxMatSeverityLevel enum members — spelled lowercase so the attribute selector matches:

import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';

@Component({
  selector: 'app-severity-panel',
  template: `<div class="severity-panel" [attr.data-severity]="severity()">…</div>`,
})
export class SeverityPanelComponent {
  readonly severity = input<TbxMatSeverityLevel>(TbxMatSeverityLevel.Default);
}

Provide the theme at bootstrap

You only need the provider when you want to turn inversion on, or when you want to read the theme config from a component via DI. Apps that never invert can skip this — the TBX_MAT_SEVERITY_THEME_CONFIG injection token has a default factory that resolves to { invert: false } so nothing throws.

To enable inversion globally:

import { bootstrapApplication } from '@angular/platform-browser';
import { provideTbxMatSeverityTheme } from '@teqbench/tbx-mat-severity-theme';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [provideTbxMatSeverityTheme({ invert: true })],
});

With invert: true, the provider registers an environment initializer that toggles the tbx-mat-severity-inverted class on <html> — all descendants pick up the inverted tokens automatically. The toggle uses Angular's DOCUMENT injection rather than the global document reference, so it's safe under SSR.

Scope inversion to a subtree

When you want only part of the UI (e.g. a single dialog) to render inverted, disable the root toggle and bind the class manually on the target host:

bootstrapApplication(AppComponent, {
  providers: [
    provideTbxMatSeverityTheme({ invert: true, applyToRoot: false }),
  ],
});
import { Component, input } from '@angular/core';
import { TBX_MAT_SEVERITY_INVERTED_CLASS } from '@teqbench/tbx-mat-severity-theme';

@Component({
  selector: 'app-invertable-panel',
  host: { '[class]': 'inverted() ? invertedClass : null' },
  template: `<ng-content />`,
})
export class InvertablePanelComponent {
  readonly invertedClass = TBX_MAT_SEVERITY_INVERTED_CLASS;
  readonly inverted = input(false);
}

The exported constant TBX_MAT_SEVERITY_INVERTED_CLASS (value: 'tbx-mat-severity-inverted') exists so you can bind the class without hard-coding the string — protects you if the value ever changes.

See Scoped inverted palette for a worked example targeting an Angular CDK dialog.

Override individual tokens

To re-brand a single tier (e.g. a darker green for success in a specific theme scope), redeclare the custom property below the import:

@use '@teqbench/tbx-mat-severity-theme/styles/tbx-mat-severity-theme';

html[data-theme='my-brand'] {
  --tbx-mat-severity-success-background: #1b5e20;
}

Any descendant referencing var(--tbx-mat-severity-success-background) under that scope picks up the override; the other five tiers stay on their defaults.

Emit package-prefixed aliases

If you're authoring a downstream package that wants its own alias namespace (e.g. --tbx-mat-notification-success-background pointing at --tbx-mat-severity-success-background), pass a prefix to the mixin:

@use '@teqbench/tbx-mat-severity-theme/styles/tbx-mat-severity-theme' as severity;

html {
  @include severity.tbx-mat-severity-theme('tbx-mat-notification');
}

The mixin emits 12 aliases (6 background + 6 text) of the form --<prefix>-<level>-<slot>: var(--tbx-mat-severity-<level>-<slot>). Consumers of your package can then reference --tbx-mat-notification-* while you pick up any future severity-theme color changes for free.

See it end-to-end with notifications and banners

The notification and banner packages consume the severity tokens internally. Once the theme is installed and provided, you don't thread severity through any component binding — calling a severity-named method on the service is enough for the message surface to pick up the correct color pair.

Install the consumer packages alongside the theme:

npm install @teqbench/tbx-mat-notifications @teqbench/tbx-mat-banners

Bootstrap with the theme provider plus the providers each consumer package exposes:

import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import {
  provideTbxMatSeverityTheme,
} from '@teqbench/tbx-mat-severity-theme';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, {
  providers: [
    provideAnimationsAsync(),
    provideTbxMatSeverityTheme({ invert: false }),
  ],
});

Inject either service and call a severity method. The message surface renders with the matching token pair — no severity argument needed:

import { Component, inject } from '@angular/core';
import { TbxMatNotificationService } from '@teqbench/tbx-mat-notifications';
import { TbxMatBannerService } from '@teqbench/tbx-mat-banners';

@Component({
  selector: 'app-demo',
  template: `
    <button (click)="onSaved()">Save</button>
    <button (click)="onUploadFailed()">Fail upload</button>
  `,
})
export class DemoComponent {
  private readonly notify = inject(TbxMatNotificationService);
  private readonly banner = inject(TbxMatBannerService);

  onSaved(): void {
    void this.notify.success('Item saved.');
  }

  onUploadFailed(): void {
    void this.banner.error('Upload failed. Check your connection and retry.');
  }
}

Toggling invert: true in the bootstrap call flips the palette across both surfaces at once — the green success notification becomes white-bg/green-text, the red error banner becomes white-bg/red-text, etc. That's the whole point of the shared token system: one provider call, consistent visual treatment across every severity-aware component.

Override a single tier (say, a darker success green for a specific theme) and it propagates to both surfaces without either package needing to know. If you later add a third consumer (dialogs, toasts, inline badges), it inherits the same palette.

See Show your first notification and Show your first banner for the full per-service setup, including config options and dismiss handling.

What to wire up next

With the theme installed, the next step depends on the surface you want to render: