@teqbench/tbx-mat-severity-theme centralizes the shared vocabulary, visuals, and runtime wiring that every @teqbench severity-leveled Angular Material package uses to classify and present messages. Rather than each package re-declaring its own severity enum, color palette, default icons, and invert flag, this foundation package owns them once and the consumer packages depend on it.
It provides four layers:
- Severity contract and enum —
TbxMatSeverityLevel (six tiers) and TbxMatSeverityResolver (the six-method contract any severity-aware icon service implements).
- Abstract icon service bases —
TbxMatSeverityFontIconService and TbxMatSeveritySvgIconService extend the abstract strategies from `@teqbench/tbx-mat-icons` and implement the resolver contract. Downstream packages subclass one and override initialize() to register icon mappings.
- Default icon sets —
TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS (inline SVG markup per level) and TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES (Material Symbols ligature names per level). Consumers pick them up via initialize() rather than re-declaring the same icon data in each package.
- Shared theme layer — an SCSS partial defining neutral
--tbx-mat-severity-<level>-<background|text> tokens and a .tbx-mat-severity-inverted class that swaps them, plus a TBX_MAT_SEVERITY_THEME_CONFIG DI token and provideTbxMatSeverityTheme() helper that wires the invert flag into the application at bootstrap.
Why six severity tiers, not five
The contract includes a default method alongside the four classic severities (success, error, warning, information) plus help. default represents "no severity classification" — a message shown with neutral styling when the application doesn't want to assert that it's conveying success, error, etc. Downstream packages surface this as a default() method on their service (e.g. TbxMatBannerService.default(message)) so the caller doesn't have to pick a severity they don't mean.
Typed-enum/method agreement
The TbxMatSeverityLevel enum's string values exactly match the method names on TbxMatSeverityResolver:
TbxMatSeverityLevel.Default → 'default' → resolver.default()
TbxMatSeverityLevel.Success → 'success' → resolver.success()
- ...and so on.
This intentional redundancy lets consumers pick whichever idiom fits their call site: service.resolve(TbxMatSeverityLevel.Warning) when they already have an enum value, or service.warning() when they know the severity at write time.
When to use
Use @teqbench/tbx-mat-severity-theme when:
- Building a component or service in the
@teqbench family that needs severity-leveled icons or colors — banner, notification, dialog, toast, or any message surface where success/error/warning/etc. distinctions matter.
- Building an application that wants to invert severity colors globally (white backgrounds, colored text) or scoped to part of the UI.
- Building an application that wants to expose its own custom icon choices for the same six severities (e.g. a themed brand variant).
Do not use it for:
- Non-severity icon domains — if the icons you need aren't classified by the six tiers, use `@teqbench/tbx-mat-icons` directly and define your own enum + abstract subclass.
- Fewer or different tiers — the contract's six methods are mandatory; subclasses can't partially implement it. If your domain needs a different set, extend
TbxMatFontIconService / TbxMatSvgIconService directly with your own contract.
At a glance
- Six-tier severity contract — TbxMatSeverityResolver fixes exactly six methods — default, success, error, warning, information, help — so every implementer handles the same tiers consistently.
- Two abstract strategy bases — TbxMatSeverityFontIconService and TbxMatSeveritySvgIconService implement the contract for font and SVG rendering respectively.
- Default icon sets shipped — TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS (CC0 inline SVG markup) and TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES (Material Symbols ligature names) give consumers turnkey defaults.
- Shared SCSS color tokens — Neutral --tbx-mat-severity-<level>-<background|text> custom properties defined once, with a prefix-remap mixin for package-local aliases.
- Pure-CSS invert support — A .tbx-mat-severity-inverted class flips background and text per level across the entire token set.
- DI config and provider helper — TBX_MAT_SEVERITY_THEME_CONFIG and provideTbxMatSeverityTheme({ invert, applyToRoot }) wire the runtime invert behavior into the application at bootstrap — SSR-safe via injected DOCUMENT.
- Typed-enum/method agreement — TbxMatSeverityLevel enum values match the method names exactly — call resolve(level) or the named method, same result.
- Strategy-agnostic substitution — Any implementation of TbxMatSeverityResolver is drop-in interchangeable with another regardless of rendering strategy.
Concepts
- Severity level — A classification of a user-facing message into one of six tiers — default, success, error, warning, information, or help — that drives icon and color choices.
- Severity tier — A single level within the severity classification; there are exactly six and the set is closed by design.
- Default tier — The severity value representing no classification — used when the message shouldn't assert success, error, or any other semantic category. Its theme tokens alias Material's system color tokens so it remains theme-responsive.
- Severity resolver contract — The TbxMatSeverityResolver interface pinning down exactly the six severity methods that every severity-aware icon service must implement.
- Enum/method agreement — The intentional redundancy where TbxMatSeverityLevel enum values match the corresponding method names on TbxMatSeverityResolver character-for-character.
- Severity color token — One of the CSS custom properties (--tbx-mat-severity-<level>-background, --tbx-mat-severity-<level>-text) that consumer packages reference for severity-driven coloring.
- Inverted variant — The visual mode where background and text swap per severity level; scoped by the tbx-mat-severity-inverted class on any ancestor.
- Root-class application — The provider helper's default behavior of toggling the inverted class on <html> at bootstrap; opt out via applyToRoot false for scoped inversion.
- Strategy-agnostic substitution — The ability to swap one severity icon service for another (font-based for SVG-based, or custom for default) without any callsite change because both honor the same contract.
- Downstream icon registration — The pattern where a consuming package subclasses a severity icon service and overrides initialize() to register its own icon choices, typically pulling from one of the shipped default sets.
Services
TbxMatSeverityFontIconService
Abstract font-icon base for severity-level icon resolution
Extends TbxMatFontIconService to inherit font set resolution (the fontSet property and font ligature registry) and implements TbxMatSeverityResolver by delegating each severity method to the inherited resolve(). Concrete subclasses register their ligature mappings (e.g., this.register(TbxMatSeverityLevel.Success, 'check_circle')) and the six severity methods automatically resolve via the registry.
Because this class is abstract, it is not injectable directly. Provide a concrete subclass in the Angular DI tree instead.
Each severity method delegates to resolve() with a non-null assertion. If a concrete subclass does not register a mapping for a given level in initialize(), resolve() returns undefined and the assertion silently yields undefined typed as string.
When to use
Extend this class in a downstream package to create a concrete font-icon service for a specific icon set. Override initialize() to register ligature mappings for each TbxMatSeverityLevel.
Example
Concrete font icon service (in a downstream package):
import { Injectable } from '@angular/core';
import {
TbxMatSeverityLevel,
TbxMatSeverityFontIconService,
} from '@teqbench/tbx-mat-severity-theme';
@Injectable()
export class MyNotificationFontIconService
extends TbxMatSeverityFontIconService
{
constructor(fontSet?: string) {
super(fontSet);
}
protected override initialize(): void {
super.initialize();
this.register(TbxMatSeverityLevel.Default, 'chat_info');
this.register(TbxMatSeverityLevel.Success, 'check_circle');
this.register(TbxMatSeverityLevel.Error, 'error');
this.register(TbxMatSeverityLevel.Warning, 'warning_amber');
this.register(TbxMatSeverityLevel.Information, 'info');
this.register(TbxMatSeverityLevel.Help, 'help');
}
}
Example
Component consuming the service:
import { Component, inject, input } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';
import { MyNotificationFontIconService } from './my-notification-font-icon.service';
@Component({
selector: 'app-notification',
imports: [MatIconModule],
template: `
<mat-icon [fontSet]="icons.fontSet">
{{ icons.resolve(severity()) }}
</mat-icon>
`,
})
export class NotificationComponent {
readonly icons = inject(MyNotificationFontIconService);
readonly severity = input.required<TbxMatSeverityLevel>();
}
TbxMatSeveritySvgIconService
Abstract SVG-icon base for severity-level icon resolution
Extends TbxMatSvgIconService to inherit inline SVG registration (via MatIconRegistry and DomSanitizer) and implements TbxMatSeverityResolver by delegating each severity method to the inherited resolve(). Concrete subclasses register their SVG markup (e.g., this.register(TbxMatSeverityLevel.Success, '<svg>...</svg>')) and the six severity methods automatically resolve via the registry.
Because this class is abstract, it is not injectable directly. Provide a concrete subclass in the Angular DI tree instead.
Each severity method delegates to resolve() with a non-null assertion. If a concrete subclass does not register a mapping for a given level in initialize(), resolve() returns undefined and the assertion silently yields undefined typed as string.
When to use
Extend this class in a downstream package to create a concrete SVG-icon service for a specific icon set. Override initialize() to register SVG markup for each TbxMatSeverityLevel.
Example
Concrete SVG icon service (in a downstream package):
import { Injectable } from '@angular/core';
import {
TbxMatSeverityLevel,
TbxMatSeveritySvgIconService,
} from '@teqbench/tbx-mat-severity-theme';
@Injectable()
export class MyNotificationSvgIconService
extends TbxMatSeveritySvgIconService
{
protected override initialize(): void {
super.initialize();
this.register(TbxMatSeverityLevel.Default, '<svg>...</svg>');
this.register(TbxMatSeverityLevel.Success, '<svg>...</svg>');
this.register(TbxMatSeverityLevel.Error, '<svg>...</svg>');
this.register(TbxMatSeverityLevel.Warning, '<svg>...</svg>');
this.register(TbxMatSeverityLevel.Information, '<svg>...</svg>');
this.register(TbxMatSeverityLevel.Help, '<svg>...</svg>');
}
}
Example
Component consuming the service:
import { Component, inject, input } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';
import { MyNotificationSvgIconService } from './my-notification-svg-icon.service';
@Component({
selector: 'app-notification',
imports: [MatIconModule],
template: `
<mat-icon [svgIcon]="icons.resolve(severity())!"></mat-icon>
`,
})
export class NotificationComponent {
readonly icons = inject(MyNotificationSvgIconService);
readonly severity = input.required<TbxMatSeverityLevel>();
}
Interfaces
TbxMatSeverityResolver
Contract for resolving severity-level icon identifiers
Defines six severity tiers — default, success, error, warning, information, and help — each returning the icon identifier for that level. The identifier may be a font ligature name (for font icon services) or a registered svgIcon name (for SVG icon services).
Implemented by TbxMatSeverityFontIconService, TbxMatSeveritySvgIconService, and any downstream service that needs severity-level icon resolution (e.g., notification and dialog icon services). No provider is registered automatically — consumers must provide a concrete implementation in the Angular DI tree.
When to use
Downstream packages implement this interface indirectly by extending TbxMatSeverityFontIconService or TbxMatSeveritySvgIconService. Use the interface as a type constraint when accepting any severity icon service regardless of icon strategy.
Example
import type { TbxMatSeverityResolver } from '@teqbench/tbx-mat-severity-theme';
function getIcon(resolver: TbxMatSeverityResolver, level: string): string {
return resolver[level as keyof TbxMatSeverityResolver]();
}
TbxMatSeverityThemeConfig
Runtime configuration for the shared severity theme
Consumed via the TBX_MAT_SEVERITY_THEME_CONFIG injection token and typically supplied through the provideTbxMatSeverityTheme() helper. Drives whether the severity color tokens render in their default orientation (colored background, white text) or their inverted orientation (white background, colored text), and whether the inverted class is applied automatically to the document root.
When to use
Pass an instance to provideTbxMatSeverityTheme() in an application's bootstrap providers. To scope inversion to a subtree instead of the entire document, set applyToRoot to false and bind TBX_MAT_SEVERITY_INVERTED_CLASS on the component host that should carry the inverted styling.
Example
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 })],
});
Enums
TbxMatSeverityLevel
Severity levels used by TbxMatSeverityFontIconService and TbxMatSeveritySvgIconService to resolve icon identifiers
Each member doubles as the method name on TbxMatSeverityResolver, so the string values must match the corresponding method names exactly.
When to use
Pass a member to resolve() on either service class to look up the registered icon identifier. Also used as keys in register() calls within initialize().
Example
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';
const level = TbxMatSeverityLevel.Warning;
const icon = service.resolve(level);
Constants
TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES
Default font ligature names for each TbxMatSeverityLevel
Shipped as the package defaults for use with TbxMatSeverityFontIconService. Ligature names target the Material Symbols font set. The Default level uses info_i. Consumers extending TbxMatSeverityFontIconService register these in their concrete service's initialize() override, or substitute their own ligature names per level.
When to use
Iterate the record when registering font ligatures for all severity levels in a consumer package, or index into it for a single level.
Example
import { Injectable } from '@angular/core';
import {
TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES,
TbxMatSeverityLevel,
TbxMatSeverityFontIconService,
} from '@teqbench/tbx-mat-severity-theme';
@Injectable()
export class MyNotificationFontIconService extends TbxMatSeverityFontIconService {
protected override initialize(): void {
super.initialize();
for (const level of Object.values(TbxMatSeverityLevel)) {
this.register(level, TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES[level]);
}
}
}
TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS
Default inline SVG icon markup for each TbxMatSeverityLevel
Shipped as the package defaults for use with TbxMatSeveritySvgIconService. The Default level reuses the Information markup. Consumers register entries via MatIconRegistry in their concrete SVG icon service's initialize() override, or substitute their own SVG markup per level.
When to use
Iterate the record when registering SVG icons for all severity levels in a consumer package, or index into it for a single level.
Example
import { Injectable } from '@angular/core';
import {
TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS,
TbxMatSeverityLevel,
TbxMatSeveritySvgIconService,
} from '@teqbench/tbx-mat-severity-theme';
@Injectable()
export class MyNotificationSvgIconService extends TbxMatSeveritySvgIconService {
protected override initialize(): void {
super.initialize();
for (const level of Object.values(TbxMatSeverityLevel)) {
this.register(level, TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS[level]);
}
}
}
TBX_MAT_SEVERITY_INVERTED_CLASS
CSS class name that flips severity tokens to their inverted variants
When applied to an element (typically <html>, but any ancestor of the severity-styled content), the shared SCSS partial @teqbench/tbx-mat-severity-theme/styles/tbx-mat-severity-theme rewrites the six --tbx-mat-severity-<level>-* custom properties so background and text colors swap. Use this constant instead of hardcoding the class literal when binding manually (e.g., on a component host) or when calling classList.toggle() in application code.
The provideTbxMatSeverityTheme() helper applies this class to document.documentElement automatically when applyToRoot is left at its default of true.
When to use
Bind on a component host for scoped inversion, or toggle manually in imperative code that does not use provideTbxMatSeverityTheme().
Example
import { TBX_MAT_SEVERITY_INVERTED_CLASS } from '@teqbench/tbx-mat-severity-theme';
@Component({
selector: 'app-invertable-panel',
host: { '[class]': 'inverted() ? invertedClass : null' },
})
export class InvertablePanelComponent {
readonly invertedClass = TBX_MAT_SEVERITY_INVERTED_CLASS;
readonly inverted = input(false);
}
TBX_MAT_SEVERITY_THEME_CONFIG
Injection token carrying the runtime TbxMatSeverityThemeConfig
Resolves to the configuration supplied through provideTbxMatSeverityTheme(). The token has a tree-shakeable root-level factory that returns { invert: false } when no value is provided, so injection never throws — consumers who do not opt in get the non-inverted default.
When to use
Inject directly when application code needs to read the current theme configuration (e.g., to conditionally render UI affordances). For the common case of enabling inversion, prefer the provideTbxMatSeverityTheme() helper rather than providing this token manually.
Example
import { Component, inject } from '@angular/core';
import { TBX_MAT_SEVERITY_THEME_CONFIG } from '@teqbench/tbx-mat-severity-theme';
@Component({ selector: 'app-theme-status', template: `{{ config.invert ? 'Inverted' : 'Default' }}` })
export class ThemeStatusComponent {
readonly config = inject(TBX_MAT_SEVERITY_THEME_CONFIG);
}
Function
provideTbxMatSeverityTheme
Register the shared severity theme configuration for an application
Supplies the given TbxMatSeverityThemeConfig value for the TBX_MAT_SEVERITY_THEME_CONFIG injection token and, when config.applyToRoot is left at its default of true, registers an environment initializer that toggles TBX_MAT_SEVERITY_INVERTED_CLASS on document.documentElement based on config.invert.
When applyToRoot is false, the helper provides the config value only; consumers are then responsible for binding the class on whatever element should carry the inverted styling (e.g., a component host).
The DOM class toggle uses DOCUMENT injection rather than the global document reference, keeping the helper compatible with server-side rendering.
When to use
Call once in an application's bootstrap providers. Skip this helper and rely on the token's default factory ({ invert: false }) when the application never enables inversion.
Example
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 })],
});
Example
Scoped inversion (no root class):
bootstrapApplication(AppComponent, {
providers: [
provideTbxMatSeverityTheme({ invert: true, applyToRoot: false }),
],
});
Accessibility
Not applicable — abstract service contracts, no UI surface. Consumers that render <mat-icon> with the values produced by these services are responsible for pairing each icon with an accessible label (either via adjacent severity text, aria-label, or aria-hidden="true" when the icon is decorative).