Merge "Move few usages of GrOverlay to Dialog element"
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.ts b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.ts
index 567c508..cf5c26d 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.ts
@@ -4,12 +4,11 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 import '../../shared/gr-dialog/gr-dialog';
-import '../../shared/gr-overlay/gr-overlay';
 import '../../shared/gr-shell-command/gr-shell-command';
-import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, css, html} from 'lit';
 import {customElement, property, query} from 'lit/decorators.js';
+import {modalStyles} from '../../../styles/gr-modal-styles';
 
 enum Commands {
   CREATE = 'git commit',
@@ -25,8 +24,8 @@
 
 @customElement('gr-create-commands-dialog')
 export class GrCreateCommandsDialog extends LitElement {
-  @query('#commandsOverlay')
-  commandsOverlay?: GrOverlay;
+  @query('#commandsModal')
+  commandsModal?: HTMLDialogElement;
 
   @property({type: String})
   branch?: string;
@@ -34,6 +33,7 @@
   static override get styles() {
     return [
       sharedStyles,
+      modalStyles,
       css`
         ol {
           list-style: decimal;
@@ -50,13 +50,13 @@
   }
 
   override render() {
-    return html` <gr-overlay id="commandsOverlay" with-backdrop="">
+    return html` <dialog id="commandsModal" tabindex="-1">
       <gr-dialog
         id="commandsDialog"
         confirm-label="Done"
         cancel-label=""
         confirm-on-enter=""
-        @confirm=${() => this.commandsOverlay?.close()}
+        @confirm=${() => this.commandsModal?.close()}
       >
         <div class="header" slot="header">Create change commands</div>
         <div class="main" slot="main">
@@ -90,10 +90,10 @@
           </ol>
         </div>
       </gr-dialog>
-    </gr-overlay>`;
+    </dialog>`;
   }
 
   open() {
-    this.commandsOverlay?.open();
+    this.commandsModal?.showModal();
   }
 }
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.ts b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.ts
index 96ec9eb..3252e3d 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.ts
@@ -27,13 +27,7 @@
     assert.shadowDom.equal(
       element,
       /* prettier-ignore */ /* HTML */ `
-      <gr-overlay
-        aria-hidden="true"
-        id="commandsOverlay"
-        style="outline: none; display: none;"
-        tabindex="-1"
-        with-backdrop=""
-      >
+      <dialog id="commandsModal" tabindex="-1">
         <gr-dialog
           cancel-label=""
           confirm-label="Done"
@@ -71,7 +65,7 @@
             </ol>
           </div>
         </gr-dialog>
-      </gr-overlay>
+      </dialog>
     `
     );
   });
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.ts b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.ts
index 983a0d9..561fffd 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.ts
@@ -4,15 +4,14 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 import '../../shared/gr-dialog/gr-dialog';
-import '../../shared/gr-overlay/gr-overlay';
 import '../../shared/gr-repo-branch-picker/gr-repo-branch-picker';
-import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
 import {RepoName, BranchName} from '../../../types/common';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, html} from 'lit';
 import {customElement, state, query} from 'lit/decorators.js';
 import {assertIsDefined} from '../../../utils/common-util';
 import {BindValueChangeEvent} from '../../../types/events';
+import {modalStyles} from '../../../styles/gr-modal-styles';
 
 export interface CreateDestinationConfirmDetail {
   repo?: RepoName;
@@ -28,25 +27,25 @@
    * @event confirm
    */
 
-  @query('#createOverlay') private createOverlay?: GrOverlay;
+  @query('#createModal') private createModal?: HTMLDialogElement;
 
   @state() private repo?: RepoName;
 
   @state() private branch?: BranchName;
 
   static override get styles() {
-    return [sharedStyles];
+    return [sharedStyles, modalStyles];
   }
 
   override render() {
     return html`
-      <gr-overlay id="createOverlay" with-backdrop>
+      <dialog id="createModal" tabindex="-1">
         <gr-dialog
           confirm-label="View commands"
           @confirm=${this.pickerConfirm}
           @cancel=${() => {
-            assertIsDefined(this.createOverlay, 'createOverlay');
-            this.createOverlay.close();
+            assertIsDefined(this.createModal, 'createModal');
+            this.createModal.close();
           }}
           ?disabled=${!(this.repo && this.branch)}
         >
@@ -67,20 +66,20 @@
             </p>
           </div>
         </gr-dialog>
-      </gr-overlay>
+      </dialog>
     `;
   }
 
   open() {
-    assertIsDefined(this.createOverlay, 'createOverlay');
+    assertIsDefined(this.createModal, 'createModal');
     this.repo = '' as RepoName;
     this.branch = '' as BranchName;
-    this.createOverlay.open();
+    this.createModal.showModal();
   }
 
   private pickerConfirm = (e: Event) => {
-    assertIsDefined(this.createOverlay, 'createOverlay');
-    this.createOverlay.close();
+    assertIsDefined(this.createModal, 'createModal');
+    this.createModal.close();
     const detail: CreateDestinationConfirmDetail = {
       repo: this.repo,
       branch: this.branch,
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog_test.ts b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog_test.ts
index 44b3183..cb27aae 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog_test.ts
@@ -21,13 +21,7 @@
     assert.shadowDom.equal(
       element,
       /* HTML */ `
-        <gr-overlay
-          aria-hidden="true"
-          id="createOverlay"
-          style="outline: none; display: none;"
-          tabindex="-1"
-          with-backdrop=""
-        >
+        <dialog id="createModal" tabindex="-1">
           <gr-dialog confirm-label="View commands" disabled="" role="dialog">
             <div class="header" slot="header">Create change</div>
             <div class="main" slot="main">
@@ -37,7 +31,7 @@
               </p>
             </div>
           </gr-dialog>
-        </gr-overlay>
+        </dialog>
       `
     );
   });
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
index 2dbe6fa..6cfefe5 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls.ts
@@ -8,7 +8,6 @@
 import '../../shared/gr-button/gr-button';
 import '../../shared/gr-dialog/gr-dialog';
 import '../../shared/gr-dropdown/gr-dropdown';
-import '../../shared/gr-overlay/gr-overlay';
 import {GrEditAction, GrEditConstants} from '../gr-edit-constants';
 import {navigationToken} from '../../core/gr-navigation/gr-navigation';
 import {ChangeInfo, RevisionPatchSetNum} from '../../../types/common';
@@ -29,17 +28,18 @@
 import {LitElement, html, css} from 'lit';
 import {customElement, property, query, state} from 'lit/decorators.js';
 import {BindValueChangeEvent} from '../../../types/events';
-import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
 import {IronInputElement} from '@polymer/iron-input/iron-input';
 import {createEditUrl} from '../../../models/views/edit';
 import {resolve} from '../../../models/dependency';
+import {modalStyles} from '../../../styles/gr-modal-styles';
+import {whenVisible} from '../../../utils/dom-util';
 
 @customElement('gr-edit-controls')
 export class GrEditControls extends LitElement {
   // private but used in test
   @query('#newPathIronInput') newPathIronInput?: IronInputElement;
 
-  @query('#overlay') protected overlay?: GrOverlay;
+  @query('#modal') modal?: HTMLDialogElement;
 
   // private but used in test
   @query('#openDialog') openDialog?: GrDialog;
@@ -81,6 +81,7 @@
   static override get styles() {
     return [
       sharedStyles,
+      modalStyles,
       css`
         :host {
           align-items: center;
@@ -137,10 +138,10 @@
   override render() {
     return html`
       ${this.actions.map(action => this.renderAction(action))}
-      <gr-overlay id="overlay" with-backdrop="">
+      <dialog id="modal" tabindex="-1">
         ${this.renderOpenDialog()} ${this.renderDeleteDialog()}
         ${this.renderRenameDialog()} ${this.renderRestoreDialog()}
-      </gr-overlay>
+      </dialog>
     `;
   }
 
@@ -309,7 +310,7 @@
       this.path = path;
     }
     assertIsDefined(this.openDialog, 'openDialog');
-    return this.showDialog(this.openDialog);
+    this.showDialog(this.openDialog);
   }
 
   openDeleteDialog(path?: string) {
@@ -317,7 +318,7 @@
       this.path = path;
     }
     assertIsDefined(this.deleteDialog, 'deleteDialog');
-    return this.showDialog(this.deleteDialog);
+    this.showDialog(this.deleteDialog);
   }
 
   openRenameDialog(path?: string) {
@@ -325,7 +326,7 @@
       this.path = path;
     }
     assertIsDefined(this.renameDialog, 'renameDialog');
-    return this.showDialog(this.renameDialog);
+    this.showDialog(this.renameDialog);
   }
 
   openRestoreDialog(path?: string) {
@@ -333,7 +334,7 @@
     if (path) {
       this.path = path;
     }
-    return this.showDialog(this.restoreDialog);
+    this.showDialog(this.restoreDialog);
   }
 
   /**
@@ -361,23 +362,20 @@
 
   // private but used in test
   showDialog(dialog: GrDialog) {
-    assertIsDefined(this.overlay, 'overlay');
+    assertIsDefined(this.modal, 'modal');
 
     // Some dialogs may not fire their on-close event when closed in certain
     // ways (e.g. by clicking outside the dialog body). This call prevents
-    // multiple dialogs from being shown in the same overlay.
+    // multiple dialogs from being shown in the same modal.
     this.hideAllDialogs();
 
-    return this.overlay.open().then(() => {
+    this.modal.showModal();
+    whenVisible(this.modal, () => {
       dialog.classList.toggle('invisible', false);
       const autocomplete = queryUtil<GrAutocomplete>(dialog, 'gr-autocomplete');
       if (autocomplete) {
         autocomplete.focus();
       }
-      setTimeout(() => {
-        assertIsDefined(this.overlay, 'overlay');
-        this.overlay.center();
-      }, 1);
     });
   }
 
@@ -412,8 +410,8 @@
 
     dialog.classList.toggle('invisible', true);
 
-    assertIsDefined(this.overlay, 'overlay');
-    this.overlay.close();
+    assertIsDefined(this.modal, 'modal');
+    this.modal.close();
   }
 
   private readonly handleDialogCancel = (e: Event) => {
diff --git a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.ts b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.ts
index b4469db..31283ad 100644
--- a/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.ts
+++ b/polygerrit-ui/app/elements/edit/gr-edit-controls/gr-edit-controls_test.ts
@@ -7,7 +7,12 @@
 import './gr-edit-controls';
 import {GrEditControls} from './gr-edit-controls';
 import {navigationToken} from '../../core/gr-navigation/gr-navigation';
-import {queryAll, stubRestApi, waitUntil} from '../../../test/test-utils';
+import {
+  queryAll,
+  stubRestApi,
+  waitUntil,
+  waitUntilVisible,
+} from '../../../test/test-utils';
 import {createChange, createRevision} from '../../../test/test-data-generators';
 import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
 import {
@@ -86,13 +91,7 @@
         >
           Restore
         </gr-button>
-        <gr-overlay
-          aria-hidden="true"
-          id="overlay"
-          style="outline: none; display: none;"
-          tabindex="-1"
-          with-backdrop=""
-        >
+        <dialog id="modal" tabindex="-1">
           <gr-dialog
             class="dialog invisible"
             confirm-label="Confirm"
@@ -180,7 +179,7 @@
               </iron-input>
             </div>
           </gr-dialog>
-        </gr-overlay>
+        </dialog>
       `
     );
   });
@@ -218,7 +217,7 @@
       assert.isFalse(hideDialogStub.called);
       queryAndAssert<GrButton>(element, '#open').click();
       element.patchNum = 1 as RevisionPatchSetNum;
-      await showDialogSpy.lastCall.returnValue;
+      await waitUntilVisible(element.modal!);
       assert.isTrue(hideDialogStub.called);
       assert.isTrue(element.openDialog!.disabled);
       assert.isFalse(queryStub.called);
@@ -241,17 +240,16 @@
 
     test('cancel', async () => {
       queryAndAssert<GrButton>(element, '#open').click();
-      return showDialogSpy.lastCall.returnValue.then(async () => {
-        assert.isTrue(element.openDialog!.disabled);
-        openAutoComplete.noDebounce = true;
-        openAutoComplete.text = 'src/test.cpp';
-        await element.updateComplete;
-        await waitUntil(() => !element.openDialog!.disabled);
-        queryAndAssert<GrButton>(element.openDialog, 'gr-button').click();
-        assert.isFalse(setUrlStub.called);
-        await waitUntil(() => closeDialogSpy.called);
-        assert.equal(element.path, '');
-      });
+      await waitUntilVisible(element.modal!);
+      assert.isTrue(element.openDialog!.disabled);
+      openAutoComplete.noDebounce = true;
+      openAutoComplete.text = 'src/test.cpp';
+      await element.updateComplete;
+      await waitUntil(() => !element.openDialog!.disabled);
+      queryAndAssert<GrButton>(element.openDialog, 'gr-button').click();
+      assert.isFalse(setUrlStub.called);
+      await waitUntil(() => closeDialogSpy.called);
+      assert.equal(element.path, '');
     });
   });
 
@@ -324,21 +322,20 @@
       assert.isFalse(closeDialogSpy.called);
     });
 
-    test('cancel', () => {
+    test('cancel', async () => {
       queryAndAssert<GrButton>(element, '#delete').click();
-      return showDialogSpy.lastCall.returnValue.then(async () => {
-        assert.isTrue(element.deleteDialog!.disabled);
-        queryAndAssert<GrAutocomplete>(
-          element.deleteDialog,
-          'gr-autocomplete'
-        ).text = 'src/test.cpp';
-        await element.updateComplete;
-        await waitUntil(() => !element.deleteDialog!.disabled);
-        queryAndAssert<GrButton>(element.deleteDialog, 'gr-button').click();
-        assert.isFalse(eventStub.called);
-        assert.isTrue(closeDialogSpy.called);
-        await waitUntil(() => element.path === '');
-      });
+      await waitUntilVisible(element.modal!);
+      assert.isTrue(element.deleteDialog!.disabled);
+      queryAndAssert<GrAutocomplete>(
+        element.deleteDialog,
+        'gr-autocomplete'
+      ).text = 'src/test.cpp';
+      await element.updateComplete;
+      await waitUntil(() => !element.deleteDialog!.disabled);
+      queryAndAssert<GrButton>(element.deleteDialog, 'gr-button').click();
+      assert.isFalse(eventStub.called);
+      assert.isTrue(closeDialogSpy.called);
+      await waitUntil(() => element.path === '');
     });
   });
 
@@ -421,22 +418,21 @@
       assert.isFalse(closeDialogSpy.called);
     });
 
-    test('cancel', () => {
+    test('cancel', async () => {
       queryAndAssert<GrButton>(element, '#rename').click();
-      return showDialogSpy.lastCall.returnValue.then(async () => {
-        assert.isTrue(element.renameDialog!.disabled);
-        queryAndAssert<GrAutocomplete>(
-          element.renameDialog,
-          'gr-autocomplete'
-        ).text = 'src/test.cpp';
-        element.newPathIronInput!.bindValue = 'src/test.newPath';
-        await element.updateComplete;
-        assert.isFalse(element.renameDialog!.disabled);
-        queryAndAssert<GrButton>(element.renameDialog, 'gr-button').click();
-        assert.isFalse(eventStub.called);
-        assert.isTrue(closeDialogSpy.called);
-        await waitUntil(() => element.path === '');
-      });
+      await waitUntilVisible(element.modal!);
+      assert.isTrue(element.renameDialog!.disabled);
+      queryAndAssert<GrAutocomplete>(
+        element.renameDialog,
+        'gr-autocomplete'
+      ).text = 'src/test.cpp';
+      element.newPathIronInput!.bindValue = 'src/test.newPath';
+      await element.updateComplete;
+      assert.isFalse(element.renameDialog!.disabled);
+      queryAndAssert<GrButton>(element.renameDialog, 'gr-button').click();
+      assert.isFalse(eventStub.called);
+      assert.isTrue(closeDialogSpy.called);
+      await waitUntil(() => element.path === '');
     });
   });
 
@@ -455,56 +451,53 @@
       );
     });
 
-    test('restore', () => {
+    test('restore', async () => {
       restoreStub.returns(Promise.resolve({ok: true}));
       element.path = 'src/test.cpp';
       queryAndAssert<GrButton>(element, '#restore').click();
-      return showDialogSpy.lastCall.returnValue.then(async () => {
-        queryAndAssert<GrButton>(
-          element.restoreDialog,
-          'gr-button[primary]'
-        ).click();
-        await element.updateComplete;
+      await waitUntilVisible(element.modal!);
+      queryAndAssert<GrButton>(
+        element.restoreDialog,
+        'gr-button[primary]'
+      ).click();
+      await element.updateComplete;
 
-        assert.isTrue(restoreStub.called);
-        assert.equal(restoreStub.lastCall.args[1], 'src/test.cpp');
-        return restoreStub.lastCall.returnValue.then(() => {
-          assert.equal(element.path, '');
-          assert.equal(eventStub.firstCall.args[0].type, 'reload');
-          assert.isTrue(closeDialogSpy.called);
-        });
+      assert.isTrue(restoreStub.called);
+      assert.equal(restoreStub.lastCall.args[1], 'src/test.cpp');
+      return restoreStub.lastCall.returnValue.then(() => {
+        assert.equal(element.path, '');
+        assert.equal(eventStub.firstCall.args[0].type, 'reload');
+        assert.isTrue(closeDialogSpy.called);
       });
     });
 
-    test('restore fails', () => {
+    test('restore fails', async () => {
       restoreStub.returns(Promise.resolve({ok: false}));
       element.path = 'src/test.cpp';
       queryAndAssert<GrButton>(element, '#restore').click();
-      return showDialogSpy.lastCall.returnValue.then(async () => {
-        queryAndAssert<GrButton>(
-          element.restoreDialog,
-          'gr-button[primary]'
-        ).click();
-        await element.updateComplete;
+      await waitUntilVisible(element.modal!);
+      queryAndAssert<GrButton>(
+        element.restoreDialog,
+        'gr-button[primary]'
+      ).click();
+      await element.updateComplete;
 
-        assert.isTrue(restoreStub.called);
-        assert.equal(restoreStub.lastCall.args[1], 'src/test.cpp');
-        return restoreStub.lastCall.returnValue.then(() => {
-          assert.isFalse(eventStub.called);
-          assert.isFalse(closeDialogSpy.called);
-        });
+      assert.isTrue(restoreStub.called);
+      assert.equal(restoreStub.lastCall.args[1], 'src/test.cpp');
+      return restoreStub.lastCall.returnValue.then(() => {
+        assert.isFalse(eventStub.called);
+        assert.isFalse(closeDialogSpy.called);
       });
     });
 
-    test('cancel', () => {
+    test('cancel', async () => {
       element.path = 'src/test.cpp';
       queryAndAssert<GrButton>(element, '#restore').click();
-      return showDialogSpy.lastCall.returnValue.then(() => {
-        queryAndAssert<GrButton>(element.restoreDialog, 'gr-button').click();
-        assert.isFalse(eventStub.called);
-        assert.isTrue(closeDialogSpy.called);
-        assert.equal(element.path, '');
-      });
+      await waitUntilVisible(element.modal!);
+      queryAndAssert<GrButton>(element.restoreDialog, 'gr-button').click();
+      assert.isFalse(eventStub.called);
+      assert.isTrue(closeDialogSpy.called);
+      assert.equal(element.path, '');
     });
   });
 
@@ -546,12 +539,12 @@
   });
 
   test('openOpenDialog', async () => {
-    await element.openOpenDialog('test/path.cpp');
+    element.openOpenDialog('test/path.cpp');
     assert.isFalse(element.openDialog!.hasAttribute('hidden'));
-    assert.equal(
-      queryAndAssert<GrAutocomplete>(element.openDialog, 'gr-autocomplete')
-        .text,
-      'test/path.cpp'
+    await waitUntil(
+      () =>
+        queryAndAssert<GrAutocomplete>(element.openDialog, 'gr-autocomplete')
+          .text === 'test/path.cpp'
     );
   });
 
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts
index b2f8acd..32b32e2 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts
@@ -6,10 +6,8 @@
 import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
 import '../../shared/gr-button/gr-button';
 import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
-import '../../shared/gr-overlay/gr-overlay';
 import {GpgKeyInfo, GpgKeyId} from '../../../types/common';
 import {GrButton} from '../../shared/gr-button/gr-button';
-import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
 import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea';
 import {getAppContext} from '../../../services/app-context';
 import {css, html, LitElement} from 'lit';
@@ -19,6 +17,7 @@
 import {assertIsDefined} from '../../../utils/common-util';
 import {BindValueChangeEvent} from '../../../types/events';
 import {fire} from '../../../utils/event-util';
+import {modalStyles} from '../../../styles/gr-modal-styles';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -27,7 +26,7 @@
 }
 @customElement('gr-gpg-editor')
 export class GrGpgEditor extends LitElement {
-  @query('#viewKeyOverlay') viewKeyOverlay?: GrOverlay;
+  @query('#viewKeyModal') viewKeyModal?: HTMLDialogElement;
 
   @query('#addButton') addButton?: GrButton;
 
@@ -53,6 +52,7 @@
   static override styles = [
     formStyles,
     sharedStyles,
+    modalStyles,
     css`
       .keyHeader {
         width: 9em;
@@ -60,7 +60,7 @@
       .userIdHeader {
         width: 15em;
       }
-      #viewKeyOverlay {
+      #viewKeyModal {
         padding: var(--spacing-xxl);
         width: 50em;
       }
@@ -97,7 +97,7 @@
               ${this.keys.map((key, index) => this.renderKey(key, index))}
             </tbody>
           </table>
-          <gr-overlay id="viewKeyOverlay" with-backdrop="">
+          <dialog id="viewKeyModal" tabindex="-1">
             <fieldset>
               <section>
                 <span class="title">Status</span>
@@ -111,11 +111,11 @@
             <gr-button
               class="closeButton"
               @click=${() => {
-                this.viewKeyOverlay?.close();
+                this.viewKeyModal?.close();
               }}
               >Close</gr-button
             >
-          </gr-overlay>
+          </dialog>
           <gr-button @click=${this.save} ?disabled=${!this.hasUnsavedChanges}
             >Save changes</gr-button
           >
@@ -201,7 +201,7 @@
 
   private showKey(key: GpgKeyInfo) {
     this.keyToView = key;
-    this.viewKeyOverlay?.open();
+    this.viewKeyModal?.showModal();
   }
 
   private handleNewKeyChanged(e: BindValueChangeEvent) {
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts
index 8e653fc..5be5b29 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts
@@ -138,13 +138,7 @@
               </tr>
             </tbody>
           </table>
-          <gr-overlay
-            aria-hidden="true"
-            id="viewKeyOverlay"
-            style="outline: none; display: none;"
-            tabindex="-1"
-            with-backdrop=""
-          >
+          <dialog id="viewKeyModal" tabindex="-1">
             <fieldset>
               <section>
                 <span class="title"> Status </span> <span class="value"> </span>
@@ -161,7 +155,7 @@
             >
               Close
             </gr-button>
-          </gr-overlay>
+          </dialog>
           <gr-button
             aria-disabled="true"
             disabled=""
@@ -242,7 +236,7 @@
   });
 
   test('show key', () => {
-    const openSpy = sinon.spy(element.viewKeyOverlay!, 'open');
+    const openSpy = sinon.spy(element.viewKeyModal!, 'showModal');
 
     // Get the show button for the last row.
     const button = queryAndAssert<GrButton>(