Skip to content

Commit c7b853a

Browse files
authored
refactor: set aria-modal and tabindex on the login overlay (#10003)
1 parent 7ff89e2 commit c7b853a

File tree

6 files changed

+66
-10
lines changed

6 files changed

+66
-10
lines changed

dev/login-overlay.html

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@
1111
import '@vaadin/login/vaadin-login-overlay.js';
1212

1313
const login = document.querySelector('vaadin-login-overlay');
14-
login.addEventListener('login', () => {
15-
login.opened = false;
16-
});
1714

1815
const button = document.querySelector('button');
1916
button.addEventListener('click', () => {
17+
login.disabled = false;
2018
login.opened = true;
2119
});
20+
21+
login.addEventListener('login', () => {
22+
login.opened = false;
23+
// Login does not restore focus
24+
button.focus();
25+
});
2226
</script>
2327
</head>
2428

packages/login/src/vaadin-login-overlay-mixin.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export const LoginOverlayMixin = (superClass) =>
4949
super.firstUpdated();
5050

5151
this.setAttribute('role', 'dialog');
52+
this.setAttribute('aria-modal', 'true');
53+
this.setAttribute('tabindex', '0');
5254

5355
this.__titleController = new TitleController(this);
5456
this.addController(this.__titleController);

packages/login/src/vaadin-login-overlay-wrapper.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,29 @@ class LoginOverlayWrapper extends OverlayMixin(DirMixin(ThemableMixin(PolylitMix
4949
return this.owner;
5050
}
5151

52+
/**
53+
* Override method from OverlayFocusMixin to use owner as focus trap root
54+
* @protected
55+
* @override
56+
*/
57+
get _focusTrapRoot() {
58+
return this.owner;
59+
}
60+
61+
/**
62+
* Override method from OverlayFocusMixin to not set `aria-hidden`
63+
* @protected
64+
* @override
65+
*/
66+
get _useAriaHidden() {
67+
return false;
68+
}
69+
5270
/** @protected */
5371
render() {
5472
return html`
5573
<div id="backdrop" part="backdrop" ?hidden="${!this.withBackdrop}"></div>
56-
<div part="overlay" id="overlay" tabindex="0">
74+
<div part="overlay" id="overlay">
5775
<div part="content" id="content">
5876
<section part="card">
5977
<div part="brand">

packages/login/src/vaadin-login-overlay.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,21 @@ class LoginOverlay extends LoginFormMixin(LoginOverlayMixin(ElementMixin(Themabl
6868

6969
static get styles() {
7070
return css`
71-
:host {
72-
display: block;
71+
:host([opened]),
72+
:host([opening]),
73+
:host([closing]) {
74+
display: block !important;
75+
position: absolute;
7376
}
7477
78+
:host,
7579
:host([hidden]) {
7680
display: none !important;
7781
}
82+
83+
:host(:focus) ::part(overlay) {
84+
outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
85+
}
7886
`;
7987
}
8088

packages/login/test/dom/__snapshots__/login-overlay.test.snap.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ export const snapshots = {};
44
snapshots["vaadin-login-overlay host default"] =
55
`<vaadin-login-overlay
66
aria-labelledby="title-vaadin-login-overlay-8"
7+
aria-modal="true"
78
opened=""
89
role="dialog"
10+
tabindex="0"
911
with-backdrop=""
1012
>
1113
<form
@@ -126,8 +128,10 @@ snapshots["vaadin-login-overlay host default"] =
126128
snapshots["vaadin-login-overlay host i18n"] =
127129
`<vaadin-login-overlay
128130
aria-labelledby="title-vaadin-login-overlay-8"
131+
aria-modal="true"
129132
opened=""
130133
role="dialog"
134+
tabindex="0"
131135
with-backdrop=""
132136
>
133137
<form
@@ -248,8 +252,10 @@ snapshots["vaadin-login-overlay host i18n"] =
248252
snapshots["vaadin-login-overlay host i18n-partial"] =
249253
`<vaadin-login-overlay
250254
aria-labelledby="title-vaadin-login-overlay-8"
255+
aria-modal="true"
251256
opened=""
252257
role="dialog"
258+
tabindex="0"
253259
with-backdrop=""
254260
>
255261
<form
@@ -436,7 +442,6 @@ snapshots["vaadin-login-overlay shadow wrapper"] =
436442
<div
437443
id="overlay"
438444
part="overlay"
439-
tabindex="0"
440445
>
441446
<div
442447
id="content"
@@ -469,7 +474,6 @@ snapshots["vaadin-login-overlay shadow i18n"] =
469474
<div
470475
id="overlay"
471476
part="overlay"
472-
tabindex="0"
473477
>
474478
<div
475479
id="content"

packages/login/test/login-overlay.test.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,26 @@ describe('login overlay', () => {
9595
});
9696
});
9797

98+
describe('display', () => {
99+
let login;
100+
101+
beforeEach(async () => {
102+
login = fixtureSync('<vaadin-login-overlay></vaadin-login-overlay>');
103+
await nextRender();
104+
});
105+
106+
it('should use display: none when not opened', () => {
107+
expect(getComputedStyle(login).display).to.equal('none');
108+
});
109+
110+
['opened', 'opening', 'closing'].forEach((state) => {
111+
it(`should use display: block when ${state} attribute is set`, () => {
112+
login.setAttribute(state, '');
113+
expect(getComputedStyle(login).display).to.equal('block');
114+
});
115+
});
116+
});
117+
98118
describe('no autofocus', () => {
99119
let login, overlay;
100120

@@ -107,8 +127,8 @@ describe('no autofocus', () => {
107127
it('should not focus the username field', async () => {
108128
login.opened = true;
109129
await oneEvent(overlay, 'vaadin-overlay-open');
110-
// Overlay traps focus and focuses the wrapper by default
111-
expect(getDeepActiveElement()).to.equal(overlay.$.overlay);
130+
// Overlay traps focus and focuses the host by default
131+
expect(getDeepActiveElement()).to.equal(login);
112132
});
113133
});
114134

0 commit comments

Comments
 (0)