Customisation options to the Angular CDK slide-over dialog

Customisation options to the Angular CDK slide-over dialog
Photo by Cecilia O'Reilly / Unsplash

This is part 3 of a three-part series.

  1. Building a custom slide-over with the Angular CDK Dialog
  2. Animating a custom Angular CDK slide-over dialog
  3. Customisation options to the Angular CDK slide-over dialog

Commonly-used Dialog configurations can be set globally at a central section of the code base so they don't have to be set each time.

With the injection token DEFAULT_DIALOG_CONFIG, the slide-over dialog can assume commonly used configurations applicable to all slide-over instances in the app.

Accessibility settings for keyboard interactions, focus management and focus restoration can be provided with reasonable defaults

This token should be provided at the application root module or app config (in the case of standalone components).

export const provideDefaultDialogData = (): EnvironmentProviders => {
  return makeEnvironmentProviders([
    {
      provide: DEFAULT_DIALOG_CONFIG,
      useValue: {
        closeOnOverlayDetachments: false,
        disableClose: true,
        hasBackdrop: true,
        ...
      },
    },
  ]);
};

// in UiSlideOverAnimatedParent

#defaultConfig = inject(DEFAULT_DIALOG_CONFIG);

openAnimatedSlideOver() {
  let uiSlideOverRef: UiSlideOverRef;
  const dialogRef = this.#dialog.open(UiSlideOverAnimatedContent, {
    ...this.#defaultConfig,
    positionStrategy: this.#overlay.position().global().end(),
    panelClass: ['pointer-events-auto', 'w-72'],
    ...
  });

Escape key

By default, pressing the Escape key closes a dialog. However, since the disableClose property was set to true in our config, the Escape key handling must be restored. The following subscription is configured in the constructor of the UiSlideOverRef to re-enable this functionality:

readonly #escapeKey = 'Escape';
...
dialogRef.keydownEvents
  .pipe(
    filter(
      (event) => event.key === this.#escapeKey && 
        !hasModifierKey(event)
    ),
    take(1)
  )
  .subscribe((event: KeyboardEvent) => {
    event.preventDefault();
    this.close();
  });

Accessibility

One of the most important functionalities supported out of the box is the accessibility APIs available for customisation. Aria-labels can be specified with a number of provided aria-related configs such as ariaLabel, ariaLabelledBy, ariaModal, etc.

ariaLabelledBy: 'slide-over-title',
ariaModal: true,
<!-- injected content--> 
<app-ui-slide-over-animated tabindex="-1" 
  class="cdk-dialog-container" 
  id="cdk-dialog-2" 
  aria-modal="true" 
  aria-labelledby="slide-over-title">
  </app-ui-slide-over-animated>

Additionally, with the focus management APIs, when the dialog is activated,

Dialog traps browser focus such that it cannot escape the root role="dialog" element.

On the other hand, when the dialog is deactivated, the focus can be restored to an identified element, in our case, the trigger button that activated the dialog.

autoFocus: 'first-tabbable', // also the default setting
restoreFocus: true,

Conclusion

Leveraging the power of the Angular CDK Dialog made authoring a custom slide-over component as easy as ABC. It is feature-rich and supports several useful Dialog capabilities out of the box. While it's APIs provide consumers with handy customisation options to support whatever Dialog requirements are needed.

This ends our 3-part Angular CDK Dialog series. If you missed the previous articles, do give them a read starting with Building a custom slide-over with the Angular CDK Dialog where we started the setup of our custom slide-over. Next is the Animating a custom Angular CDK slide-over dialog where we added animation capabilities to the slide-over dialog.

Reference

This post is heavily inspired by this article, Custom Overlays with Angular's CDK by Dominic Elm. This gave me clarity as to the power of the Angular CDK. Also being referred to constantly is the Dialog implementation of Angular material.

Lhar Gil

Lhar Gil

Tech-savvy software developer and street photography enthusiast. Exploring the world through code and candid shots of daily life. 📸 All opinions are my own.
England