Skip to content
Permalink
Browse files

feat(renderers): add restoreFocus setting

This controls where focus should be restored when a dialog closes.
By default focus is restored to the last element that was active when
the dialog opened.
  • Loading branch information
RomkeVdMeulen committed Jul 22, 2019
1 parent 4ea60c0 commit c5f4ad4cbba1b08ff85dabc4986c9604da4213ee
@@ -92,6 +92,14 @@ export interface DialogSettings {
* When invoked the function is passed the dialog container and the dialog overlay elements.
*/
position?: (dialogContainer: Element, dialogOverlay?: Element) => void;

/**
* This function is called when a dialog closes to restore focus to the last
* element that was focused when the dialog opened. It can be overridden in
* general settings, or on a case by case basis by providing an override when
* a particular dialog is opened.
*/
restoreFocus?: (lastActiveElement: HTMLElement) => void;
}

/**
@@ -105,4 +113,5 @@ export class DefaultDialogSettings implements DialogSettings {
public rejectOnCancel = false;
public ignoreTransitions = false;
public position?: (dialogContainer: Element, dialogOverlay: Element) => void;
public restoreFocus = (lastActiveElement: HTMLElement) => lastActiveElement.focus();
}
@@ -47,6 +47,7 @@ export class NativeDialogRenderer implements Renderer {
private dialogCancel: (e: Event) => void;

public dialogContainer: HTMLDialogElement;
public lastActiveElement: HTMLElement;
public host: Element;
public anchor: Element;

@@ -62,6 +63,8 @@ export class NativeDialogRenderer implements Renderer {
}

private attach(dialogController: DialogController): void {
this.lastActiveElement = DOM.activeElement as HTMLElement;

const spacingWrapper = DOM.createElement('div'); // TODO: check if redundant
spacingWrapper.appendChild(this.anchor);
this.dialogContainer = DOM.createElement(containerTagName) as HTMLDialogElement;
@@ -92,6 +95,9 @@ export class NativeDialogRenderer implements Renderer {
if (!NativeDialogRenderer.dialogControllers.length) {
this.host.classList.remove('ux-dialog-open');
}
if (dialogController.settings.restoreFocus) {
dialogController.settings.restoreFocus(this.lastActiveElement);
}
}

private setAsActive(): void {
@@ -105,6 +105,7 @@ export class DialogRenderer implements Renderer {

public dialogContainer: HTMLElement;
public dialogOverlay: HTMLElement;
public lastActiveElement: HTMLElement;
public host: Element;
public anchor: Element;

@@ -120,6 +121,8 @@ export class DialogRenderer implements Renderer {
}

private attach(dialogController: DialogController): void {
this.lastActiveElement = DOM.activeElement as HTMLElement;

const spacingWrapper = DOM.createElement('div'); // TODO: check if redundant
spacingWrapper.appendChild(this.anchor);

@@ -156,6 +159,9 @@ export class DialogRenderer implements Renderer {
if (!DialogRenderer.dialogControllers.length) {
host.classList.remove('ux-dialog-open');
}
if (dialogController.settings.restoreFocus) {
dialogController.settings.restoreFocus(this.lastActiveElement);
}
}

private setAsActive(): void {
@@ -182,6 +182,18 @@ describe('native-dialog-renderer.spec.ts', () => {
done();
});
});

describe('"restoreFocus"', () => {
it('and calls the given callback on close', async done => {
let restoreCalled = false;
const renderer = createRenderer({ restoreFocus: () => restoreCalled = true });
await show(done, renderer);
expect(restoreCalled).toBe(false);
await hide(done, renderer);
expect(restoreCalled).toBe(true);
done();
});
});
});

describe('on first open dialog', () => {
@@ -185,6 +185,18 @@ describe('ux-dialog-renderer.spec.ts', () => {
done();
});
});

describe('"restoreFocus"', () => {
it('and calls the given callback on close', async done => {
let restoreCalled = false;
const renderer = createRenderer({ restoreFocus: () => restoreCalled = true });
await show(done, renderer);
expect(restoreCalled).toBe(false);
await hide(done, renderer);
expect(restoreCalled).toBe(true);
done();
});
});
});

describe('on first open dialog', () => {

0 comments on commit c5f4ad4

Please sign in to comment.
You can’t perform that action at this time.