TeqBench Material Bottom SheetsMaterial Bottom Sheets
An opinionated Angular bottom sheet service built on Angular Material's MatBottomSheet with severity-leveled methods (success / error / warning / information / help / default), bottom sheet-specific UX patterns (confirm / input), pluggable severity and close icons, and rich footer controls.
npm install @teqbench/tbx-mat-bottom-sheets@teqbench/tbx-mat-bottom-sheets provides bottom sheets for Angular applications. It complements small transient notifications and persistent banners with a modal surface anchored to the bottom edge of the viewport — familiar on mobile, unobtrusive on desktop — for focused interactions: confirmations, short input, and simple content projections. Bottom sheets render via Angular Material's MatBottomSheet, which manages overlay, backdrop, focus trap, and modal semantics.
TbxMatBottomSheetService exposes nine opinionated methods. Six mirror the severity-leveled surface of tbx-mat-banners and tbx-mat-notifications — success, error, warning, information, help, and default. Two are bottom sheet-specific UX patterns layered on top of severity — confirm (Yes/No) and input (form content with OK/Cancel). The ninth, show, takes a full configuration for cases where the opinionated methods do not fit. All methods return a Promise<TbxMatBottomSheetResult<T, F>> so consumers can await the user's choice with no subscription management.
Severity (default, success, error, warning, information, help) drives the entire bottom sheet surface — header, body, and footer share the severity background and text. The six CSS custom-property pairs are aliased from the shared @teqbench/tbx-mat-severity-theme tokens, so the colored tiers stay independent of the active M3 theme palette while the default tier remains theme-responsive. Applications can opt into an inverted palette across every severity-aware @teqbench package by calling provideTbxMatSeverityTheme({ invert: true, applyToRoot: true }) at bootstrap.
The footer is a single flex row of buttons and form controls (checkboxes, toggles, radio groups, toggle groups). On dismiss, all collected control values are returned alongside the dismiss reason. Input bottom sheets project a consumer-defined component into the body — the component implements TbxMatBottomSheetData<T> with two signals (isValid, value); the shell reads them to drive the affirm button's disabled state and to extract the form value on confirm.
Angular Material's MatBottomSheet does not expose sizing knobs — width and height are controlled entirely via CSS on the host element. There are no width, minWidth, maxWidth, minHeight, or maxHeight config options on this package.
The library is designed for Angular 21+ applications, and exposes a pluggable icon resolver so consumers can use Material Symbols font icons or bundled SVG icons without changing component code.
When to use
Bottom sheets are one of three message surfaces in the TeqBench component family. Choose based on the weight of the message, the level of interruption appropriate for the context, and the target platform:
@teqbench/tbx-mat-notifications— small, transient messages with at most one action control. Ideally one line of text, two lines acceptable. Use notifications to acknowledge something without interrupting the user's flow.@teqbench/tbx-mat-banners— wide, persistent messages with multiple action controls. Ideally one line of message text, up to three lines still acceptable. Use a banner when the message needs the user's attention and may offer a few follow-up choices.@teqbench/tbx-mat-bottom-sheets(this package) — anchored modal surface for focused, low-to-medium complexity interactions. Less visually disruptive than a centered dialog; feels natural on mobile because it emerges from the bottom edge.@teqbench/tbx-mat-dialogs— centered overlay for the heaviest interactions: long copy, many controls, multi-step input, or anything that demands the user's full visual attention.
Reach for a bottom sheet when the interaction is more than a banner can hold but does not require the full visual weight of a centered dialog. If the content is long, the choices are many, or the layout is complex, promote it to a dialog instead. If a notification or banner is being stretched past its envelope by a single-step confirmation or a short form, a bottom sheet is the right promotion.
At a glance
- Severity-leveled API — success, error, warning, information, help, and default mirror the surface used by tbx-mat-banners and tbx-mat-notifications.
- Bottom sheet-only UX patterns — confirm (Yes/No) and input (projected form content with OK/Cancel) layered on top of severity.
- Async by default — Every method returns Promise<TbxMatBottomSheetResult<T, F>>; use await, no subscription management.
- Typed input bottom sheets — TbxMatBottomSheetData<T> contract with isValid and value signals; the affirm button's disabled state is automatically driven by isValid.
- Rich footer controls — Buttons (text / filled / icon-position) and form controls (checkbox, toggle, radio group, toggle group) collected and returned on dismiss.
- Pluggable icons — Three icon services ship out of the box (severity font, severity SVG, close font); consumers can subclass any of them or supply their own resolver.
- Theming via CSS custom properties — Six severity background/text token pairs aliased from @teqbench/tbx-mat-severity-theme, plus centralized opacity tokens for action button variants.
- Inverted palette flip — provideTbxMatSeverityTheme({ invert: true }) swaps background and text values app-wide; banners, notifications, and bottom sheets invert simultaneously.
- Modal semantics — Backdrop, focus trap, escape-to-close, and aria-modal come from MatBottomSheet; this package adds the chrome and the typed result surface.
Concepts
- Severity level
- A classification (default, success, error, warning, information, help) that selects the icon and color scheme applied to a bottom sheet.
- Bottom sheet patterns
- confirm and input are bottom sheet-specific UX wrappers around the severity model — confirm defaults to Help severity with Yes/No buttons; input defaults to Information severity with a projected content component and OK/Cancel buttons.
- Footer item
- An entry in the bottom sheet footer with a key (used in the returned footerValues record) and an align ('start' flows left, 'end' flows right). The first 'end' item gets margin-left auto, separating start- and end-aligned items.
- Footer button emphasis
- Visual weight of a footer button — 'primary' (filled, severity-colored) or 'text' (no fill). Destructive prompts are expressed via the bottom sheet severity ('warning' or 'error'), not via a per-button variant.
- Dismiss reason
- The cause of a bottom sheet closing — Affirm, Deny, Cancel, or Close. Footer buttons declare a result to map their click; backdrop click and Escape both emit Close with empty footer values.
- Provider config
- The DI-provided configuration (TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG) that supplies the severity icon resolver and an optional close icon resolver. Required.
- Content component
- A consumer-defined @Component that implements TbxMatBottomSheetData<T>. Used in the body of input bottom sheets; the shell reads isValid to drive the affirm button's disabled state and value to extract data on confirm.
Services
TbxMatBottomSheetCloseFontIconService
Resolve the bottom sheet close button to a font-based icon
Remarks
Default font-based close button icon service. Extends TbxMatFontIconService from @teqbench/tbx-mat-icons and registers the 'close' Material Symbols ligature. Used as the package-provided fallback for TbxMatBottomSheetProviderConfig.closeIconResolverService when the consumer does not supply a custom close icon resolver.
No provider is registered automatically — when omitted from TbxMatBottomSheetProviderConfig, the bottom sheet shell instantiates this class with no fontSet argument and relies on the inherited fallback chain.
No default SVG close icon service is provided. Consumers who want SVG close icons must create a concrete subclass of TbxMatSvgIconService from @teqbench/tbx-mat-icons and provide it via TbxMatBottomSheetProviderConfig.closeIconResolverService.
fontSet resolution
The fontSet is resolved by TbxMatFontIconService's fallback chain:
- Explicit constructor argument —
new TbxMatBottomSheetCloseFontIconService('material-symbols-sharp'). 2.TBX_MAT_FONT_ICON_DEFAULT_FONT_SETtoken — set once inapp.config.ts. 3.MAT_ICON_DEFAULT_OPTIONS.fontSet— Angular Material's global icon default. 4. Error — if none of the above provides a fontSet.
When to use
Provide as closeIconResolverService on TbxMatBottomSheetProviderConfig when an explicit fontSet is required. Subclass to override the close ligature.
Example
// app.config.ts — explicit close icon font.
import {
TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
TbxMatBottomSheetSeverityFontIconService,
TbxMatBottomSheetCloseFontIconService,
} from '@teqbench/tbx-mat-bottom-sheets';
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService('material-symbols-rounded'),
closeIconResolverService: new TbxMatBottomSheetCloseFontIconService('material-symbols-rounded'),
}),
},
]TbxMatBottomSheetService
Open a typed bottom sheet and await the user's choice
Remarks
Application-wide bottom sheet service built on Angular Material's MatBottomSheet. Provides nine opinionated bottom sheet methods with sensible defaults and a general-purpose show() method for full control. All bottom sheets use the shared internal shell component for consistent chrome (header, body, footer).
Severity-leveled methods (success, error, warning, information, help, default) mirror the surface exposed by TbxMatBannerService and TbxMatNotificationService. Bottom sheet-specific patterns (confirm, input) layer on top of the severity model with their own default footer presets.
All methods return a Promise that resolves when the bottom sheet closes, so consumers use async/await with no subscription management.
Icons are resolved at render time by the bottom sheet shell via the required TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG injection token. Consumers configure the severity icon resolver (font or SVG) and an optional close icon resolver in app.config.ts; see TbxMatBottomSheetProviderConfig for the full shape. Per-call TbxMatBottomSheetConfig.icon overrides take precedence over the resolved severity icon and are rendered as font ligatures.
Error handling
When the bottom sheet is dismissed via backdrop click or Escape without a button click, the underlying afterDismissed() emits undefined. The service catches this case and returns a TbxMatBottomSheetDismissReason.Close result with an empty footerValues record — dismissal is a negative action like Cancel or Deny and never carries form state.
When to use
Inject in any component or service that needs to prompt the user. Prefer the opinionated methods over show() so severity, icon, and footer defaults stay consistent across the application.
Example
private readonly bottomSheet = inject(TbxMatBottomSheetService);
// Severity methods (mirror banners/notifications).
await this.bottomSheet.success({ title: 'Saved', message: 'Your changes are saved.' });
await this.bottomSheet.error({ title: 'Failed', message: 'Could not save changes.' });
await this.bottomSheet.warning({ title: 'Caution', message: 'This may take a while.' });
await this.bottomSheet.information({ title: 'FYI', message: 'Heads up.' });
await this.bottomSheet.help({ title: 'How it works', message: 'Tap to learn more.' });
await this.bottomSheet.default({ title: 'Notice', message: 'Neutral surface.' });
// Confirmation — Help severity, Yes/No buttons.
const output = await this.bottomSheet.confirm({ title: 'Continue?', message: 'Proceed?' });
if (output.result === TbxMatBottomSheetDismissReason.Affirm) {
// proceed
}
// Input — Information severity, OK/Cancel buttons.
// RenameFormComponent is a hypothetical consumer-defined component that
// implements TbxMatBottomSheetData<string>.
const output = await this.bottomSheet.input<string>({
title: 'Rename',
content: RenameFormComponent,
});
// Typed footer values.
interface MyFooter { dontAskAgain: boolean; }
const output = await this.bottomSheet.confirm<MyFooter>({
title: 'Delete',
message: 'Are you sure?',
footer: [
{ key: 'dontAskAgain', type: 'checkbox', label: "Don't ask again", align: 'start' },
...TBX_MAT_BOTTOM_SHEET_BUTTONS_YES_NO,
],
});
// Full control — no defaults applied.
const output = await this.bottomSheet.show({
title: 'Custom',
icon: 'build',
type: TbxMatSeverityLevel.Warning,
message: 'Full control over every option.',
footer: [...customFooter],
});See also
TbxMatBottomSheetSeverityFontIconService
Resolve severity levels to font-based bottom sheet icons
Remarks
Default font-based severity bottom sheet icon service. Extends TbxMatSeverityFontIconService from @teqbench/tbx-mat-severity-theme and registers the shared default Material Symbols ligatures (TBX_MAT_SEVERITY_DEFAULT_FONT_LIGATURES) for every severity level. The inherited resolve() and severity methods (default(), success(), error(), etc.) work via the registered mappings.
No provider is registered automatically — instantiate explicitly via the TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG factory.
fontSet resolution
The fontSet is resolved by TbxMatFontIconService's fallback chain:
- Explicit constructor argument —
new TbxMatBottomSheetSeverityFontIconService('material-symbols-sharp'). 2.TBX_MAT_FONT_ICON_DEFAULT_FONT_SETtoken — set once inapp.config.ts. 3.MAT_ICON_DEFAULT_OPTIONS.fontSet— Angular Material's global icon default. 4. Error — if none of the above provides a fontSet.
When to use
Provide as severityIconResolverService on TbxMatBottomSheetProviderConfig. Subclass to override individual ligatures.
Example 1
// app.config.ts — using with MAT_ICON_DEFAULT_OPTIONS.
import { MAT_ICON_DEFAULT_OPTIONS } from '@angular/material/icon';
import { TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG, TbxMatBottomSheetSeverityFontIconService }
from '@teqbench/tbx-mat-bottom-sheets';
providers: [
{ provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: 'material-symbols-rounded' } },
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService(),
}),
},
]Example 2
// Using with an explicit fontSet.
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService('material-symbols-rounded'),
}),
},
]TbxMatBottomSheetSeveritySvgIconService
Resolve severity levels to SVG bottom sheet icons
Remarks
Default SVG-based severity bottom sheet icon service. Extends TbxMatSeveritySvgIconService from @teqbench/tbx-mat-severity-theme and registers the shared default SVG icons (TBX_MAT_SEVERITY_DEFAULT_SVG_ICONS) for every severity level. The inherited resolve() and severity methods (default(), success(), error(), etc.) work via the registered mappings.
No provider is registered automatically — instantiate explicitly via the TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG factory.
Default icons ship with @teqbench/tbx-mat-severity-theme. Subclasses can override any default by overriding initialize() and calling register() with the same key and different SVG markup.
When to use
Provide as severityIconResolverService on TbxMatBottomSheetProviderConfig when SVG icons are preferred over font ligatures. Subclass to override individual icons.
Example 1
// app.config.ts — using the defaults directly.
import { TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG, TbxMatBottomSheetSeveritySvgIconService }
from '@teqbench/tbx-mat-bottom-sheets';
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeveritySvgIconService(),
}),
},
]Example 2
// Subclassing with custom SVG markup.
import { Injectable } from '@angular/core';
import { TbxMatBottomSheetSeveritySvgIconService } from '@teqbench/tbx-mat-bottom-sheets';
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';
// MyBottomSheetSvgIcons is a hypothetical consumer-defined subclass.
@Injectable()
export class MyBottomSheetSvgIcons extends TbxMatBottomSheetSeveritySvgIconService {
protected override initialize(): void {
super.initialize();
this.register(TbxMatSeverityLevel.Success, '<svg>...</svg>');
}
}Interfaces
TbxMatBottomSheetConfig
Configuration for opening a bottom sheet via TbxMatBottomSheetService
Remarks
The full configuration shape used by TbxMatBottomSheetService.show(). The opinionated methods (success(), error(), etc.) accept TbxMatBottomSheetConfigArgs instead, which makes every field except title optional.
Angular Material's MatBottomSheetConfig does not expose sizing knobs — width and height are controlled entirely via CSS on the host element.
Type parameters
TType of data for input bottom sheets (the value produced by the projected content component implementing
TbxMatBottomSheetData). Defaults tovoid.
When to use
Used when calling TbxMatBottomSheetService.show() for full control over every option. Most callers should use the opinionated methods, which apply sensible defaults.
Example
import { TbxMatSeverityLevel } from '@teqbench/tbx-mat-severity-theme';
const config: TbxMatBottomSheetConfig = {
title: 'Custom BottomSheet',
icon: 'build',
type: TbxMatSeverityLevel.Warning,
subtitle: 'Optional secondary line',
contextBadge: 'Beta',
message: 'Full control over every option.',
footer: [
{ key: 'cancel', type: 'button', label: 'Cancel', result: TbxMatBottomSheetDismissReason.Cancel, align: 'end' },
{ key: 'proceed', type: 'button', label: 'Proceed', emphasis: 'primary', result: TbxMatBottomSheetDismissReason.Affirm, align: 'end' },
],
};TbxMatBottomSheetData
Contract for components rendered in bottom sheet bodies
Remarks
The bottom sheet shell reads isValid to drive the affirm button's disabled state and reads value to include in TbxMatBottomSheetResult.data when the user confirms. Content components own their own form layout, validation, and state — the bottom sheet system never inspects the content beyond these two signals.
Focus management
For input bottom sheets, the bottom sheet service sets autoFocus: 'first-tabbable' so the consumer's cdkFocusInitial attribute on a form field inside the projected content component takes precedence. Content components should apply cdkFocusInitial to the element that should receive initial focus. This is a plain HTML attribute recognized by the Angular CDK FocusTrap — no directive import needed. Without it, focus would fall through to the first tabbable element in DOM order (typically the header close button), so applying it on the intended target is required for correct UX.
Non-input components (display-only content)
Components that display content without producing a form value use the null object pattern — isValid is always true (nothing to validate), value is always undefined (nothing to extract). This allows any component to be hosted via TbxMatBottomSheetService.show() without type casts.
Type parameters
TType of value produced by the form content.
When to use
Implement on consumer-defined components passed to TbxMatBottomSheetService.input() or TbxMatBottomSheetService.show() via TbxMatBottomSheetConfig.content.
Example
// Input bottom sheet form content.
@Component({
imports: [MatFormFieldModule, MatInputModule],
template: `
<mat-form-field>
<input matInput cdkFocusInitial [ngModel]="name()" (ngModelChange)="name.set($event)" />
</mat-form-field>
`,
})
export class RenameFormComponent implements TbxMatBottomSheetData<string> {
readonly name = signal('');
readonly isValid = computed(() => this.name().trim().length > 0);
readonly value = this.name;
}
// Display-only content — null object pattern.
@Component({ ... })
export class UserSettingsComponent implements TbxMatBottomSheetData<void> {
readonly isValid = signal(true);
readonly value = signal<void>(undefined);
}TbxMatBottomSheetFooterButton
Button footer item
Remarks
Clicking a button with a result closes the bottom sheet and returns that result in TbxMatBottomSheetResult. Buttons without a result perform side effects (e.g., navigation) without dismissing the bottom sheet.
When to use
Add to a TbxMatBottomSheetConfig.footer array, or use a button preset constant (TBX_MAT_BOTTOM_SHEET_BUTTONS_OK, etc.).
Example
const proceed: TbxMatBottomSheetFooterButton = {
key: 'proceed',
type: 'button',
label: 'Proceed',
emphasis: 'primary',
result: TbxMatBottomSheetDismissReason.Affirm,
align: 'end',
};TbxMatBottomSheetFooterCheckbox
Checkbox footer control
Remarks
Value is tracked in TbxMatBottomSheetResult.footerValues as a boolean under the item's key.
When to use
Add to a TbxMatBottomSheetConfig.footer array to collect a boolean alongside the dismiss action.
Example
const remember: TbxMatBottomSheetFooterCheckbox = {
key: 'remember',
type: 'checkbox',
label: "Don't ask again",
align: 'start',
};TbxMatBottomSheetFooterItem
Base interface for all bottom sheet footer items — buttons and form controls alike
Remarks
Every footer item has a key (used in the returned TbxMatBottomSheetResult.footerValues record) and an align (determines left or right positioning in the footer row).
The footer is a single flex row. Items render in caller-specified array order. The first align: 'end' item receives margin-left: auto, pushing it and all subsequent items to the right side.
When to use
Not used directly — extend via the discriminated members of TbxMatBottomSheetFooterControlType.
Example
// Implementations are the concrete footer item interfaces.
const item: TbxMatBottomSheetFooterButton = {
key: 'ok',
type: 'button',
label: 'OK',
emphasis: 'primary',
result: TbxMatBottomSheetDismissReason.Affirm,
align: 'end',
};TbxMatBottomSheetFooterRadioGroup
Radio group footer control — single-select from a set of options
Remarks
Value is tracked in TbxMatBottomSheetResult.footerValues as a string under the item's key.
When to use
Add to a TbxMatBottomSheetConfig.footer array to let the user pick one option from a small set (typically two to four).
Example
const visibility: TbxMatBottomSheetFooterRadioGroup = {
key: 'visibility',
type: 'radio-group',
options: [
{ label: 'Public', value: 'public' },
{ label: 'Private', value: 'private' },
],
initialValue: 'public',
align: 'start',
};TbxMatBottomSheetFooterToggle
Slide toggle footer control
Remarks
Value is tracked in TbxMatBottomSheetResult.footerValues as a boolean under the item's key.
When to use
Add to a TbxMatBottomSheetConfig.footer array to collect a boolean alongside the dismiss action — visually distinct from a checkbox.
Example
const notify: TbxMatBottomSheetFooterToggle = {
key: 'notify',
type: 'toggle',
label: 'Email notifications',
initialValue: true,
align: 'start',
};TbxMatBottomSheetFooterToggleGroup
Button toggle group footer control — single-select or multi-select
Remarks
Value is tracked in TbxMatBottomSheetResult.footerValues as a string (single-select) or string[] (multi-select) under the item's key.
When to use
Add to a TbxMatBottomSheetConfig.footer array to let the user pick from a set of options rendered as a toggle button group. Use multiple: true to allow several selections.
Example
const align: TbxMatBottomSheetFooterToggleGroup = {
key: 'align',
type: 'toggle-group',
options: [
{ label: 'Left', value: 'left', icon: 'format_align_left' },
{ label: 'Center', value: 'center', icon: 'format_align_center' },
{ label: 'Right', value: 'right', icon: 'format_align_right' },
],
initialValue: 'left',
align: 'start',
};TbxMatBottomSheetProviderConfig
Configuration for the bottom sheet component's injectable dependencies
Remarks
Provided via the TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG injection token in app.config.ts. Groups all bottom sheet icon customization into a single provider entry, matching the pattern used by TbxMatBannerProviderConfig and TbxMatNotificationProviderConfig.
No provider is registered automatically — consumers must explicitly provide TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG for the bottom sheet component to render.
Properties
severityIconResolverService— resolves severity levels to icon identifiers. UseTbxMatBottomSheetSeverityFontIconServicefor font icons orTbxMatBottomSheetSeveritySvgIconServicefor SVG icons.closeIconResolverService(optional) — resolves the close button icon. When omitted, the package falls back to a default font-based resolver (TbxMatBottomSheetCloseFontIconService) that registers the'close'Material Symbols ligature.
When to use
Provide in app.config.ts to wire icon resolution. Required.
Example 1
// app.config.ts — font icons with explicit fontSet.
import { TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG, TbxMatBottomSheetSeverityFontIconService }
from '@teqbench/tbx-mat-bottom-sheets';
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService('material-symbols-rounded'),
}),
},
]Example 2
// SVG icons.
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeveritySvgIconService(),
}),
},
]Example 3
// With a custom close icon resolver.
// MyCloseIconService is a hypothetical consumer-defined service that extends
// TbxMatFontIconService<string> or TbxMatSvgIconService<string> and registers
// an icon under the 'close' key.
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService('material-symbols-rounded'),
closeIconResolverService: new MyCloseIconService('material-symbols-rounded'),
}),
},
]TbxMatBottomSheetResult
Typed output returned when a bottom sheet closes
Remarks
Resolved by every TbxMatBottomSheetService method. Carries the user's action (TbxMatBottomSheetDismissReason), any data produced by an input bottom sheet's projected content component, and any values collected from footer form controls.
On any non-Affirm dismissal (Deny, Cancel, Close, Escape, backdrop), data is undefined and footerValues is an empty object — negative actions never carry state that implies confirmation.
Type parameters
TType of data returned by input bottom sheets (from
TbxMatBottomSheetData.value). Defaults tovoidfor informational and confirmation bottom sheets.FType of footer control values. Defaults to
Record<string, unknown>. Callers that need typed footer values specify an interface as the second generic parameter.
When to use
The return shape of every TbxMatBottomSheetService method. await a bottom sheet call and branch on result to handle the user's action.
Example
// Simple confirmation — both generics use defaults.
const output: TbxMatBottomSheetResult = await bottomSheet.confirm({ title: 'Continue?' });
// Input bottom sheet with typed data.
const output: TbxMatBottomSheetResult<string> = await bottomSheet.input<string>({
title: 'Rename',
content: RenameFormComponent, // hypothetical consumer-defined component
});
// Confirmation with typed footer values.
interface MyFooter { dontAskAgain: boolean; }
const output: TbxMatBottomSheetResult<void, MyFooter> = await bottomSheet.confirm<MyFooter>({
title: 'Delete?',
});Enums
TbxMatBottomSheetDismissReason
Identify which action closed a bottom sheet
Remarks
Returned as TbxMatBottomSheetResult.result when the bottom sheet closes.
Affirm— User confirmed the action (OK, Yes, Save, Delete, etc.). -Deny— User explicitly declined (No). -Cancel— User aborted the interaction (Cancel button). -Close— User dismissed without choosing (close button, Escape, backdrop).
When to use
Compare TbxMatBottomSheetResult.result against the enum members to branch on the user's action. Footer button declarations carry a result field that maps the click to one of these values.
Example
const output = await bottomSheet.confirm({ title: 'Delete?', message: 'This cannot be undone.' });
if (output.result === TbxMatBottomSheetDismissReason.Affirm) {
// proceed with deletion
}Types
TbxMatBottomSheetConfigArgs
Convenience type for the opinionated bottom sheet methods (success, error, warning, information, help, default, confirm, input)
Remarks
Requires a title — all other TbxMatBottomSheetConfig fields are optional. Callers specify only what they want to override; the service merges in defaults for severity type and footer button preset.
Type parameters
TType of data for input bottom sheets. Defaults to
void.
When to use
Used as the parameter type for the opinionated TbxMatBottomSheetService methods. Use TbxMatBottomSheetConfig directly when calling show(), which applies no defaults.
Example
await bottomSheet.success({ title: 'Saved' });
await bottomSheet.warning({ title: 'Caution', message: 'This may take a while.' });TbxMatBottomSheetFooterControlType
Discriminated union of all bottom sheet footer item types
Remarks
The bottom sheet shell component renders each item via @switch (control.type), and TypeScript narrows the type automatically in each branch. Members are TbxMatBottomSheetFooterButton, TbxMatBottomSheetFooterCheckbox, TbxMatBottomSheetFooterToggle, TbxMatBottomSheetFooterRadioGroup, and TbxMatBottomSheetFooterToggleGroup.
When to use
Use as the element type when assembling a custom footer array on a TbxMatBottomSheetConfig or a TbxMatBottomSheetConfigArgs.
Example
const footer: readonly TbxMatBottomSheetFooterControlType[] = [
{ key: 'remember', type: 'checkbox', label: 'Remember me', align: 'start' },
{ key: 'cancel', type: 'button', label: 'Cancel', result: TbxMatBottomSheetDismissReason.Cancel, align: 'end' },
{ key: 'ok', type: 'button', label: 'OK', emphasis: 'primary', result: TbxMatBottomSheetDismissReason.Affirm, align: 'end' },
];TbxMatBottomSheetIconResolver
Icon resolver that also exposes the resolved icon's type
Remarks
Combines TbxMatIconResolver from @teqbench/tbx-mat-icons with the static iconType property the bottom sheet template needs to decide whether to render a font ligature or an SVG element.
When to use
The shape of the optional closeIconResolverService slot on TbxMatBottomSheetProviderConfig. Custom close icon services must conform to this shape — extending TbxMatFontIconService<string> or TbxMatSvgIconService<string> from @teqbench/tbx-mat-icons provides it automatically.
Example
// MyCloseIconService is a hypothetical consumer-defined service.
const resolver: TbxMatBottomSheetIconResolver = new MyCloseIconService();
const icon = resolver.resolve('close');
const type = resolver.iconType; // 'font' | 'svg'Constants
TBX_MAT_BOTTOM_SHEET_BUTTONS_OK_CANCEL
OK + Cancel buttons preset — Cancel left, OK right
Remarks
Default footer for the input method.
When to use
Use when the bottom sheet requires a positive commit and offers an explicit cancel path.
Example
await bottomSheet.show({
title: 'Rename',
content: RenameFormComponent, // hypothetical consumer-defined component
footer: TBX_MAT_BOTTOM_SHEET_BUTTONS_OK_CANCEL,
});TBX_MAT_BOTTOM_SHEET_BUTTONS_OK
Single OK button preset — right-aligned, primary emphasis
Remarks
Default footer for the severity-leveled methods (success, error, warning, information, help, default).
When to use
Spread into a custom footer array, or pass directly as the footer field. Use when the bottom sheet only needs an acknowledgement.
Example
await bottomSheet.show({ title: 'Saved', message: 'Done.', footer: TBX_MAT_BOTTOM_SHEET_BUTTONS_OK });TBX_MAT_BOTTOM_SHEET_BUTTONS_YES_NO_CANCEL
Yes + No + Cancel buttons preset — Cancel left, No and Yes right
When to use
Use when the bottom sheet asks a binary question and also needs a third option to back out without committing to either answer.
Example
await bottomSheet.show({
title: 'Save changes?',
message: 'You have unsaved changes.',
footer: TBX_MAT_BOTTOM_SHEET_BUTTONS_YES_NO_CANCEL,
});TBX_MAT_BOTTOM_SHEET_BUTTONS_YES_NO
Yes + No buttons preset — both right-aligned, Yes primary
Remarks
Default footer for the confirm method.
When to use
Use when the bottom sheet asks a binary question without a "back out" path.
Example
await bottomSheet.show({
title: 'Continue?',
message: 'Are you sure?',
footer: TBX_MAT_BOTTOM_SHEET_BUTTONS_YES_NO,
});TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG
Injection token for bottom sheet component icon configuration
Remarks
Required. Provide in app.config.ts to configure the severity icon resolver service and the close button icon. Use TbxMatBottomSheetSeverityFontIconService for font icons or TbxMatBottomSheetSeveritySvgIconService for SVG icons — both ship with sensible defaults from @teqbench/tbx-mat-severity-theme.
No provider is registered automatically — without an explicit provider, the bottom sheet component will not render.
When to use
Provide in app.config.ts with a TbxMatBottomSheetProviderConfig factory.
Example 1
// app.config.ts — font icons with explicit fontSet.
import { TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG, TbxMatBottomSheetSeverityFontIconService }
from '@teqbench/tbx-mat-bottom-sheets';
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService('material-symbols-rounded'),
}),
},
]Example 2
// Font icons via MAT_ICON_DEFAULT_OPTIONS (no explicit fontSet).
import { MAT_ICON_DEFAULT_OPTIONS } from '@angular/material/icon';
import { TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG, TbxMatBottomSheetSeverityFontIconService }
from '@teqbench/tbx-mat-bottom-sheets';
providers: [
{ provide: MAT_ICON_DEFAULT_OPTIONS, useValue: { fontSet: 'material-symbols-rounded' } },
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService(),
}),
},
]Example 3
// With a custom close icon resolver.
// MyCloseIconService is a hypothetical consumer-defined service that extends
// TbxMatFontIconService<string> or TbxMatSvgIconService<string> and registers
// an icon under the 'close' key.
providers: [
{
provide: TBX_MAT_BOTTOM_SHEET_PROVIDER_CONFIG,
useFactory: () => ({
severityIconResolverService: new TbxMatBottomSheetSeverityFontIconService('material-symbols-rounded'),
closeIconResolverService: new MyCloseIconService('material-symbols-rounded'),
}),
},
]Accessibility
- Modal semantics. Bottom sheets render via Angular Material's MatBottomSheet, which sets
aria-modal="true", manages the backdrop, and traps keyboard focus inside the overlay until dismissal. Angular Material does not ship a structural directive equivalent to MatDialogTitle, so the shell wires the title's generatedidinto the host'saria-labelledbyattribute manually to associate the accessible name with the modal container. - Focus. Initial focus depends on what the bottom sheet contains. When the bottom sheet has an affirm button (any footer button with
result: TbxMatBottomSheetDismissReason.Affirm), the shell auto-appliescdkFocusInitialto that button so it receives initial focus. When the bottom sheet projects a content component, focus follows the consumer'scdkFocusInitialattribute on a form field — applying it is the consumer's responsibility, and is recognized by the CDK FocusTrap without any directive import. When neither is present (footerlessshow()calls or footers with only passive dismiss buttons),autoFocusfalls back to'dialog'so initial focus lands on the bottom sheet container, not the close button. The close button is reachable via Tab in every case. - Keyboard.
Escapedismisses the bottom sheet withCloseunlessdisableClose: trueis set.Tabcycles through focusable elements within the bottom sheet. Footer buttons activate onEnterandSpace; form controls use their native Angular Material keyboard behavior. - Reduced motion. Angular Material's MatBottomSheet honors
prefers-reduced-motion: reducefor its open/close animation. - Color contrast. The default severity palette meets WCAG AA contrast for text on each severity background. Overriding the severity CSS custom properties is the consumer's responsibility to re-verify.
- Icons. Severity and close icons are decorative and marked
aria-hidden; meaning is carried by the title and message text and by the close button'saria-label.