Merge "Fix focus styling for context control buttons"
diff --git a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.ts b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.ts
index ce0ea02..4d0d3f1 100644
--- a/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.ts
+++ b/polygerrit-ui/app/elements/admin/gr-access-section/gr-access-section.ts
@@ -24,7 +24,7 @@
   LabelNameToLabelTypeInfoMap,
   RepoName,
 } from '../../../types/common';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {IronInputElement} from '@polymer/iron-input/iron-input';
 import {fontStyles} from '../../../styles/gr-font-styles';
 import {formStyles} from '../../../styles/gr-form-styles';
@@ -34,18 +34,6 @@
 import {BindValueChangeEvent, ValueChangedEvent} from '../../../types/events';
 import {assertIsDefined, queryAndAssert} from '../../../utils/common-util';
 
-/**
- * Fired when the section has been modified or removed.
- *
- * @event access-modified
- */
-
-/**
- * Fired when a section that was previously added was removed.
- *
- * @event added-section-removed
- */
-
 const GLOBAL_NAME = 'GLOBAL_CAPABILITIES';
 
 // The name that gets automatically input when a new reference is added.
@@ -300,7 +288,7 @@
       // For a new section, this is not fired because new permissions and
       // rules have to be added in order to save, modifying the ref is not
       // enough.
-      fireEvent(this, 'access-modified');
+      fire(this, 'access-modified', {});
     }
     this.section.value.updatedId = this.section.id;
     this.requestUpdate();
@@ -432,11 +420,11 @@
       return;
     }
     if (this.section.value.added) {
-      fireEvent(this, 'added-section-removed');
+      fire(this, 'added-section-removed', {});
     }
     this.deleted = true;
     this.section.value.deleted = true;
-    fireEvent(this, 'access-modified');
+    fire(this, 'access-modified', {});
   }
 
   _handleUndoRemove() {
@@ -533,6 +521,10 @@
 
 declare global {
   interface HTMLElementEventMap {
+    /** Fired when the section has been modified or removed. */
+    'access-modified': CustomEvent<{}>;
+    /** Fired when a section that was previously added was removed. */
+    'added-section-removed': CustomEvent<{}>;
     'section-changed': ValueChangedEvent<PermissionAccessSection>;
   }
   interface HTMLElementTagNameMap {
diff --git a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.ts b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.ts
index bb59c0c..61fe0c4 100644
--- a/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-confirm-delete-item-dialog/gr-confirm-delete-item-dialog.ts
@@ -7,7 +7,7 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {css, html, LitElement} from 'lit';
 import {customElement, property} from 'lit/decorators.js';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -69,12 +69,12 @@
   _handleConfirmTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'confirm');
+    fireNoBubble(this, 'confirm', {});
   }
 
   _handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 }
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
index 13a8cd0..b3f1e96 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
@@ -24,7 +24,7 @@
 import {LitElement, PropertyValues, css, html} from 'lit';
 import {customElement, property, query, state} from 'lit/decorators.js';
 import {BindValueChangeEvent, ValueChangedEvent} from '../../../types/events';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {subscribe} from '../../lit/subscription-controller';
 import {configModelToken} from '../../../models/config/config-model';
 import {resolve} from '../../../models/dependency';
@@ -38,6 +38,9 @@
   interface HTMLElementTagNameMap {
     'gr-create-change-dialog': GrCreateChangeDialog;
   }
+  interface HTMLElementEventMap {
+    'can-create-change': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-create-change-dialog')
@@ -207,7 +210,7 @@
   }
 
   private allowCreate() {
-    fireEvent(this, 'can-create-change');
+    fire(this, 'can-create-change', {});
   }
 
   handleCreateChange(): Promise<void> {
diff --git a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts
index 96688e9..893343f 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-group-dialog/gr-create-group-dialog.ts
@@ -13,7 +13,7 @@
 import {LitElement, PropertyValues, css, html} from 'lit';
 import {customElement, query, property} from 'lit/decorators.js';
 import {BindValueChangeEvent} from '../../../types/events';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {createGroupUrl} from '../../../models/views/group';
 import {resolve} from '../../../models/dependency';
 import {navigationToken} from '../../core/gr-navigation/gr-navigation';
@@ -22,6 +22,9 @@
   interface HTMLElementTagNameMap {
     'gr-create-group-dialog': GrCreateGroupDialog;
   }
+  interface HTMLElementEventMap {
+    'has-new-group-name': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-create-group-dialog')
@@ -75,7 +78,7 @@
   }
 
   private updateGroupName() {
-    fireEvent(this, 'has-new-group-name');
+    fire(this, 'has-new-group-name', {});
   }
 
   override focus() {
diff --git a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts
index 558d571..12f36ec 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-pointer-dialog/gr-create-pointer-dialog.ts
@@ -13,13 +13,16 @@
 import {LitElement, PropertyValues, css, html} from 'lit';
 import {customElement, property, state} from 'lit/decorators.js';
 import {BindValueChangeEvent} from '../../../types/events';
-import {fireAlert, fireEvent, fireReload} from '../../../utils/event-util';
+import {fireAlert, fire, fireReload} from '../../../utils/event-util';
 import {RepoDetailView} from '../../../models/views/repo';
 
 declare global {
   interface HTMLElementTagNameMap {
     'gr-create-pointer-dialog': GrCreatePointerDialog;
   }
+  interface HTMLElementEventMap {
+    'update-item-name': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-create-pointer-dialog')
@@ -113,7 +116,7 @@
   }
 
   private updateItemName() {
-    fireEvent(this, 'update-item-name');
+    fire(this, 'update-item-name', {});
   }
 
   handleCreateItem() {
diff --git a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
index 3548130..1a70f2b 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-repo-dialog/gr-create-repo-dialog.ts
@@ -20,7 +20,7 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, css, html} from 'lit';
 import {customElement, query, property, state} from 'lit/decorators.js';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
 import {createRepoUrl} from '../../../models/views/repo';
 import {resolve} from '../../../models/dependency';
@@ -31,16 +31,14 @@
   interface HTMLElementTagNameMap {
     'gr-create-repo-dialog': GrCreateRepoDialog;
   }
+  interface HTMLElementEventMap {
+    /** Fired when repostiory name is entered. */
+    'new-repo-name': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-create-repo-dialog')
 export class GrCreateRepoDialog extends LitElement {
-  /**
-   * Fired when repostiory name is entered.
-   *
-   * @event new-repo-name
-   */
-
   @query('input')
   input?: HTMLInputElement;
 
@@ -252,7 +250,7 @@
     // because when the event is fired, gr-repo-list gets
     // the nameChanged value.
     this.nameChanged = !!e.detail.value;
-    fireEvent(this, 'new-repo-name');
+    fire(this, 'new-repo-name', {});
     this.requestUpdate();
   }
 
diff --git a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.ts b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.ts
index 0841595..30085e3 100644
--- a/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-group-members/gr-group-members_test.ts
@@ -25,7 +25,7 @@
 } from '../../../types/common';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
-import {EventType, PageErrorEvent} from '../../../types/events';
+import {PageErrorEvent} from '../../../types/events';
 import {getAccountSuggestions} from '../../../utils/account-util';
 import {getAppContext} from '../../../services/app-context';
 import {fixture, html, assert} from '@open-wc/testing';
@@ -446,7 +446,7 @@
 
     const memberName = 'bad-name';
     const alertStub = sinon.stub();
-    element.addEventListener(EventType.SHOW_ALERT, alertStub);
+    element.addEventListener('show-alert', alertStub);
     const errorResponse = {...new Response(), status: 404, ok: false};
     stubRestApi('saveIncludedGroup').callsFake((_, _non, errFn) => {
       if (errFn !== undefined) {
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts
index 46e8ae0..38123ad 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.ts
@@ -34,7 +34,7 @@
   EditableRepoAccessGroups,
 } from '../gr-repo-access/gr-repo-access-interfaces';
 import {getAppContext} from '../../../services/app-context';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {paperStyles} from '../../../styles/gr-paper-styles';
 import {formStyles} from '../../../styles/gr-form-styles';
@@ -64,16 +64,6 @@
   value: GroupInfo;
 }
 
-/**
- * Fired when the permission has been modified or removed.
- *
- * @event access-modified
- */
-/**
- * Fired when a permission that was previously added was removed.
- *
- * @event added-permission-removed
- */
 @customElement('gr-permission')
 export class GrPermission extends LitElement {
   @property({type: String})
@@ -361,7 +351,7 @@
     this.permission.value.modified = true;
     this.permission.value.exclusive = (e.target as HTMLInputElement).checked;
     // Allows overall access page to know a change has been made.
-    fireEvent(this, 'access-modified');
+    fire(this, 'access-modified', {});
   }
 
   handleRemovePermission() {
@@ -369,11 +359,11 @@
       return;
     }
     if (this.permission.value.added) {
-      fireEvent(this, 'added-permission-removed');
+      fire(this, 'added-permission-removed', {});
     }
     this.deleted = true;
     this.permission.value.deleted = true;
-    fireEvent(this, 'access-modified');
+    fire(this, 'access-modified', {});
   }
 
   private handleRulesChanged() {
@@ -542,7 +532,7 @@
     const value = this.rules[this.rules.length - 1].value;
     value!.added = true;
     this.permission.value.rules[groupId] = value!;
-    fireEvent(this, 'access-modified');
+    fire(this, 'access-modified', {});
     this.requestUpdate();
   }
 
@@ -579,6 +569,8 @@
 
 declare global {
   interface HTMLElementEventMap {
+    /** Fired when a permission that was previously added was removed. */
+    'added-permission-removed': CustomEvent<{}>;
     'permission-changed': ValueChangedEvent<
       PermissionArrayItem<EditablePermissionInfo>
     >;
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.ts b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.ts
index dab2706..af2831a 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-commands/gr-repo-commands_test.ts
@@ -13,7 +13,7 @@
   stubRestApi,
 } from '../../../test/test-utils';
 import {GrDialog} from '../../shared/gr-dialog/gr-dialog';
-import {EventType, PageErrorEvent} from '../../../types/events';
+import {PageErrorEvent} from '../../../types/events';
 import {RepoName} from '../../../types/common';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {fixture, html, assert} from '@open-wc/testing';
@@ -147,7 +147,7 @@
       handleSpy = sinon.spy(element, 'handleEditRepoConfig');
       alertStub = sinon.stub();
       element.repo = 'test' as RepoName;
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
     });
 
     test('successful creation of change', async () => {
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts
index 82a4eb5..4e41dfe 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts
@@ -8,7 +8,7 @@
 import '../../shared/gr-select/gr-select';
 import {encodeURL, getBaseUrl} from '../../../utils/url-util';
 import {AccessPermissionId} from '../../../utils/access-util';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {formStyles} from '../../../styles/gr-form-styles';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, PropertyValues, html, css} from 'lit';
@@ -18,18 +18,6 @@
 import {EditablePermissionRuleInfo} from '../gr-repo-access/gr-repo-access-interfaces';
 import {PermissionAction} from '../../../constants/constants';
 
-/**
- * Fired when the rule has been modified or removed.
- *
- * @event access-modified
- */
-
-/**
- * Fired when a rule that was previously added was removed.
- *
- * @event added-rule-removed
- */
-
 const PRIORITY_OPTIONS = [PermissionAction.BATCH, PermissionAction.INTERACTIVE];
 
 const Action = {
@@ -82,6 +70,8 @@
     'gr-rule-editor': GrRuleEditor;
   }
   interface HTMLElementEventMap {
+    /** Fired when a rule that was previously added was removed. */
+    'added-rule-removed': CustomEvent<{}>;
     'rule-changed': ValueChangedEvent<Rule | undefined>;
   }
 }
@@ -434,14 +424,14 @@
   private handleRemoveRule() {
     if (!this.rule?.value) return;
     if (this.rule.value.added) {
-      fireEvent(this, 'added-rule-removed');
+      fire(this, 'added-rule-removed', {});
     }
     this.deleted = true;
     this.rule.value.deleted = true;
 
     this.handleRuleChange();
 
-    fireEvent(this, 'access-modified');
+    fire(this, 'access-modified', {});
   }
 
   private handleUndoRemove() {
@@ -479,7 +469,7 @@
     this.handleRuleChange();
 
     // Allows overall access page to know a change has been made.
-    fireEvent(this, 'access-modified');
+    fire(this, 'access-modified', {});
   }
 
   // private but used in test
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts
index f7a2531..0cc3e18 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-hashtag-flow/gr-change-list-hashtag-flow_test.ts
@@ -29,7 +29,6 @@
   waitUntilObserved,
 } from '../../../test/test-utils';
 import {ChangeInfo, NumericChangeId, Hashtag} from '../../../types/common';
-import {EventType} from '../../../types/events';
 import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import './gr-change-list-hashtag-flow';
@@ -303,7 +302,7 @@
 
     test('add hashtag from selected change', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       // selects "hashtag1"
       queryAll<HTMLButtonElement>(element, 'button.chip')[0].click();
       await element.updateComplete;
@@ -377,7 +376,7 @@
 
     test('add multiple hashtag from selected change', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       // selects "hashtag1"
       queryAll<HTMLButtonElement>(element, 'button.chip')[0].click();
       await element.updateComplete;
@@ -425,7 +424,7 @@
 
     test('add existing hashtag not on selected changes', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
 
       const getHashtagsStub = stubRestApi(
         'getChangesWithSimilarHashtag'
@@ -481,7 +480,7 @@
 
     test('add new hashtag', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
 
       const getHashtagsStub = stubRestApi(
         'getChangesWithSimilarHashtag'
@@ -586,7 +585,7 @@
 
     test('cannot add existing hashtag already on selected changes', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       // selects "sharedHashtag"
       queryAll<HTMLButtonElement>(element, 'button.chip')[1].click();
       await element.updateComplete;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts
index 9125cfd..d2dced2 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-topic-flow/gr-change-list-topic-flow_test.ts
@@ -29,7 +29,6 @@
   waitUntilObserved,
 } from '../../../test/test-utils';
 import {ChangeInfo, NumericChangeId, TopicName} from '../../../types/common';
-import {EventType} from '../../../types/events';
 import {GrAutocomplete} from '../../shared/gr-autocomplete/gr-autocomplete';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import './gr-change-list-topic-flow';
@@ -326,7 +325,7 @@
 
     test('remove single topic', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       queryAll<HTMLButtonElement>(element, 'button.chip')[0].click();
       await element.updateComplete;
       queryAndAssert<GrButton>(element, '#remove-topics-button').click();
@@ -387,7 +386,7 @@
 
     test('shows error when remove topic fails', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       queryAll<HTMLButtonElement>(element, 'button.chip')[0].click();
       await element.updateComplete;
       queryAndAssert<GrButton>(element, '#remove-topics-button').click();
@@ -435,7 +434,7 @@
 
     test('applies topic to all changes', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
 
       queryAll<HTMLButtonElement>(element, 'button.chip')[0].click();
       await element.updateComplete;
@@ -589,7 +588,7 @@
 
     test('create new topic', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       const getTopicsStub = stubRestApi('getChangesWithSimilarTopic').resolves(
         []
       );
@@ -639,7 +638,7 @@
 
     test('shows error when create topic fails', async () => {
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       const getTopicsStub = stubRestApi('getChangesWithSimilarTopic').resolves(
         []
       );
@@ -682,7 +681,7 @@
         {...createChange(), topic: 'foo' as TopicName},
       ]);
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       const autocomplete = queryAndAssert<GrAutocomplete>(
         element,
         'gr-autocomplete'
@@ -732,7 +731,7 @@
         {...createChange(), topic: 'foo' as TopicName},
       ]);
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       const autocomplete = queryAndAssert<GrAutocomplete>(
         element,
         'gr-autocomplete'
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
index 1c86354..b5593f3 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -15,7 +15,7 @@
   RepoName,
 } from '../../../types/common';
 import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star';
-import {fireAlert, fireEvent, fireTitleChange} from '../../../utils/event-util';
+import {fireAlert, fire, fireTitleChange} from '../../../utils/event-util';
 import {getAppContext} from '../../../services/app-context';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, PropertyValues, html, css, nothing} from 'lit';
@@ -316,7 +316,7 @@
       e.detail.change._number,
       e.detail.starred
     );
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
   }
 }
 
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
index 748c2b8..6c7e661 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.ts
@@ -17,7 +17,7 @@
   ServerInfo,
   PreferencesInput,
 } from '../../../types/common';
-import {fire, fireEvent, fireReload} from '../../../utils/event-util';
+import {fire, fireReload} from '../../../utils/event-util';
 import {ColumnNames, ScrollMode} from '../../../constants/constants';
 import {getRequirements} from '../../../utils/label-util';
 import {Key} from '../../../utils/dom-util';
@@ -77,18 +77,6 @@
 @customElement('gr-change-list')
 export class GrChangeList extends LitElement {
   /**
-   * Fired when next page key shortcut was pressed.
-   *
-   * @event next-page
-   */
-
-  /**
-   * Fired when previous page key shortcut was pressed.
-   *
-   * @event previous-page
-   */
-
-  /**
    * The logged-in user's account, or an empty object if no user is logged
    * in.
    */
@@ -415,11 +403,11 @@
   }
 
   private nextPage() {
-    fireEvent(this, 'next-page');
+    fire(this, 'next-page', {});
   }
 
   private prevPage() {
-    fireEvent(this, 'previous-page');
+    fire(this, 'previous-page', {});
   }
 
   private refreshChangeList() {
@@ -484,5 +472,9 @@
   }
   interface HTMLElementEventMap {
     'selected-index-changed': ValueChangedEvent<number>;
+    /** Fired when next page key shortcut was pressed. */
+    'next-page': CustomEvent<{}>;
+    /** Fired when previous page key shortcut was pressed. */
+    'previous-page': CustomEvent<{}>;
   }
 }
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.ts b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.ts
index 9c53fea..d9be9ca 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.ts
@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 import '../../shared/gr-button/gr-button';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, css, html} from 'lit';
 import {customElement} from 'lit/decorators.js';
@@ -14,6 +14,10 @@
   interface HTMLElementTagNameMap {
     'gr-create-change-help': GrCreateChangeHelp;
   }
+  interface HTMLElementEventMap {
+    /** Fired when the "Create change" button is tapped. */
+    'create-tap': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-create-change-help')
@@ -87,11 +91,8 @@
     `;
   }
 
-  /**
-   * Fired when the "Create change" button is tapped.
-   */
   _handleCreateTap(e: Event) {
     e.preventDefault();
-    fireEvent(this, 'create-tap');
+    fire(this, 'create-tap', {});
   }
 }
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 90fff4d..16220ba 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
@@ -89,7 +89,7 @@
     // 'confirm' event here, so let's stop propagation of the bare event.
     e.preventDefault();
     e.stopPropagation();
-    fireNoBubbleNoCompose(this, 'confirm', detail);
+    fireNoBubbleNoCompose(this, 'confirm-destination', detail);
   };
 }
 
@@ -97,4 +97,7 @@
   interface HTMLElementTagNameMap {
     'gr-create-destination-dialog': GrCreateDestinationDialog;
   }
+  interface HTMLElementEventMap {
+    'confirm-destination': CustomEvent<CreateDestinationConfirmDetail>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index cd30440..8c99aaa 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -29,7 +29,7 @@
 import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star';
 import {
   fireAlert,
-  fireEvent,
+  fire,
   firePageError,
   fireTitleChange,
 } from '../../../utils/event-util';
@@ -241,7 +241,9 @@
       </dialog>
       <gr-create-destination-dialog
         id="destinationDialog"
-        @confirm=${(e: CustomEvent<CreateDestinationConfirmDetail>) => {
+        @confirm-destination=${(
+          e: CustomEvent<CreateDestinationConfirmDetail>
+        ) => {
           this.handleDestinationConfirm(e);
         }}
       ></gr-create-destination-dialog>
@@ -537,7 +539,7 @@
       e.detail.change._number,
       e.detail.starred
     );
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
     if (e.detail.starred) {
       this.reporting.reportInteraction('change-starred-from-dashboard');
     }
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index 259c8be..36ac307 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -77,8 +77,7 @@
   fire,
   fireAlert,
   fireError,
-  fireEvent,
-  fireEventNoBubbleNoCompose,
+  fireNoBubbleNoCompose,
   fireReload,
 } from '../../../utils/event-util';
 import {
@@ -86,7 +85,6 @@
   getVotingRange,
   StandardLabels,
 } from '../../../utils/label-util';
-import {EventType} from '../../../types/events';
 import {
   ActionPriority,
   ActionType,
@@ -661,7 +659,7 @@
           id="confirmRebase"
           class="confirmDialog"
           .changeNumber=${this.change?._number}
-          @confirm=${this.handleRebaseConfirm}
+          @confirm-rebase=${this.handleRebaseConfirm}
           @cancel=${this.handleConfirmDialogCancel}
           .disableActions=${this.inProgressActionKeys.has(
             RevisionActions.REBASE
@@ -698,7 +696,7 @@
         <gr-confirm-revert-dialog
           id="confirmRevertDialog"
           class="confirmDialog"
-          @confirm=${this.handleRevertDialogConfirm}
+          @confirm-revert=${this.handleRevertDialogConfirm}
           @cancel=${this.handleConfirmDialogCancel}
         ></gr-confirm-revert-dialog>
         <gr-confirm-abandon-dialog
@@ -1951,7 +1949,7 @@
       .fetchChangeUpdates(change)
       .then(result => {
         if (!result.isLatest) {
-          fire(this, EventType.SHOW_ALERT, {
+          fire(this, 'show-alert', {
             message:
               'Cannot set label: a newer patch has been ' +
               'uploaded to this change.',
@@ -2019,12 +2017,12 @@
 
   // private but used in test
   handleDownloadTap() {
-    fireEvent(this, 'download-tap');
+    fire(this, 'download-tap', {});
   }
 
   // private but used in test
   handleIncludedInTap() {
-    fireEvent(this, 'included-tap');
+    fire(this, 'included-tap', {});
   }
 
   // private but used in test
@@ -2213,17 +2211,21 @@
   }
 
   private handleEditTap() {
-    fireEventNoBubbleNoCompose(this, 'edit-tap');
+    fireNoBubbleNoCompose(this, 'edit-tap', {});
   }
 
   private handleStopEditTap() {
-    fireEventNoBubbleNoCompose(this, 'stop-edit-tap');
+    fireNoBubbleNoCompose(this, 'stop-edit-tap', {});
   }
 }
 
 declare global {
   interface HTMLElementEventMap {
+    'download-tap': CustomEvent<{}>;
+    'edit-tap': CustomEvent<{}>;
+    'included-tap': CustomEvent<{}>;
     'revision-actions-changed': CustomEvent<{value: ActionNameToActionInfoMap}>;
+    'stop-edit-tap': CustomEvent<{}>;
   }
   interface HTMLElementTagNameMap {
     'gr-change-actions': GrChangeActions;
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
index 4602eac..82900a3 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions_test.ts
@@ -54,7 +54,6 @@
 import {GrConfirmMoveDialog} from '../gr-confirm-move-dialog/gr-confirm-move-dialog';
 import {GrConfirmAbandonDialog} from '../gr-confirm-abandon-dialog/gr-confirm-abandon-dialog';
 import {GrConfirmRevertDialog} from '../gr-confirm-revert-dialog/gr-confirm-revert-dialog';
-import {EventType} from '../../../types/events';
 import {testResolver} from '../../../test/common-test-setup';
 import {storageServiceToken} from '../../../services/storage/gr-storage_impl';
 import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
@@ -1456,7 +1455,7 @@
           enabled: true,
         };
         queryAndAssert(element, 'gr-confirm-revert-dialog').dispatchEvent(
-          new CustomEvent('confirm', {
+          new CustomEvent('confirm-revert', {
             detail: {
               message: 'foo message',
               revertType: 1,
@@ -2440,7 +2439,7 @@
         onShowError = sinon.stub();
         element.addEventListener('show-error', onShowError);
         onShowAlert = sinon.stub();
-        element.addEventListener(EventType.SHOW_ALERT, onShowAlert);
+        element.addEventListener('show-alert', onShowAlert);
       });
 
       suite('happy path', () => {
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
index 01399e9..0e71c1f 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
@@ -57,7 +57,7 @@
   isSectionSet,
   DisplayRules,
 } from '../../../utils/change-metadata-util';
-import {fireAlert, fireEvent, fireReload} from '../../../utils/event-util';
+import {fireAlert, fire, fireReload} from '../../../utils/event-util';
 import {
   EditRevisionInfo,
   isDefined,
@@ -769,7 +769,7 @@
     } finally {
       this.settingTopic = false;
     }
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
     fireReload(this);
   }
 
@@ -802,7 +802,7 @@
     await this.restApiService.setChangeHashtag(this.change._number, {
       add: [newHashtag as Hashtag],
     });
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
     fireReload(this);
   }
 
@@ -957,7 +957,7 @@
     } finally {
       target.disabled = false;
     }
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
     fireReload(this);
   }
 
@@ -975,7 +975,7 @@
     } finally {
       target.disabled = false;
     }
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
     fireReload(this);
   }
 
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
index e45de51..c46fe24 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.ts
@@ -54,7 +54,6 @@
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {nothing} from 'lit';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 import {testResolver} from '../../../test/common-test-setup';
 import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
 
@@ -871,7 +870,7 @@
         Promise.resolve(newTopic)
       );
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
 
       element.handleTopicChanged(new CustomEvent('test', {detail: newTopic}));
 
@@ -892,7 +891,7 @@
         Promise.resolve(newTopic)
       );
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       await element.updateComplete;
       const chip = queryAndAssert<GrLinkedChip>(element, 'gr-linked-chip');
       const remove = queryAndAssert<GrButton>(chip, '#remove');
@@ -916,7 +915,7 @@
         Promise.resolve(newHashtag)
       );
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
       element.handleHashtagChanged(
         new CustomEvent('test', {detail: 'new hashtag'})
       );
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 3afe055..2246671 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -116,7 +116,6 @@
 import {EditRevisionInfo, ParsedChangeInfo} from '../../../types/types';
 import {
   EditableContentSaveEvent,
-  EventType,
   FileActionTapEvent,
   OpenFixPreviewEvent,
   ShowReplyDialogEvent,
@@ -128,10 +127,9 @@
 import {GrMessagesList} from '../gr-messages-list/gr-messages-list';
 import {GrThreadList} from '../gr-thread-list/gr-thread-list';
 import {
-  fire,
   fireAlert,
   fireDialogChange,
-  fireEvent,
+  fire,
   fireReload,
   fireTitleChange,
 } from '../../../utils/event-util';
@@ -591,11 +589,9 @@
     this.addEventListener('editable-content-cancel', () =>
       this.handleCommitMessageCancel()
     );
-    this.addEventListener(EventType.OPEN_FIX_PREVIEW, e =>
-      this.onOpenFixPreview(e)
-    );
+    this.addEventListener('open-fix-preview', e => this.onOpenFixPreview(e));
 
-    this.addEventListener(EventType.SHOW_TAB, e => this.setActiveTab(e));
+    this.addEventListener('show-tab', e => this.setActiveTab(e));
     this.addEventListener('reload', e => {
       this.loadData(
         /* isLocationChange= */ false,
@@ -2165,7 +2161,7 @@
     } else if (this.viewState?.commentId) {
       tab = Tab.COMMENT_THREADS;
     }
-    this.setActiveTab(new CustomEvent(EventType.SHOW_TAB, {detail: {tab}}));
+    this.setActiveTab(new CustomEvent('show-tab', {detail: {tab}}));
   }
 
   // Private but used in tests.
@@ -2356,7 +2352,7 @@
 
   private handleOpenReplyDialog() {
     if (!this.loggedIn) {
-      fireEvent(this, 'show-auth-required');
+      fire(this, 'show-auth-required', {});
       return;
     }
     this.openReplyDialog(FocusTarget.ANY);
@@ -2386,7 +2382,7 @@
           reason
         )
         .then(() => {
-          fireEvent(this, 'hide-alert');
+          fire(this, 'hide-alert', {});
         });
     } else {
       const reason = getAddedByReason(this.account, this.serverConfig);
@@ -2403,7 +2399,7 @@
           reason
         )
         .then(() => {
-          fireEvent(this, 'hide-alert');
+          fire(this, 'hide-alert', {});
         });
     }
     this.change = newChange;
@@ -2871,7 +2867,7 @@
     allDataPromises.push(mergeabilityLoaded);
 
     coreDataPromise.then(() => {
-      fireEvent(this, 'change-details-loaded');
+      fire(this, 'change-details-loaded', {});
       this.reporting.timeEnd(Timing.CHANGE_RELOAD);
       if (isLocationChange) {
         this.reporting.changeDisplayed(roleDetails(this.change, this.account));
@@ -3056,7 +3052,7 @@
           }
 
           this.cancelUpdateCheckTimer();
-          fire(this, EventType.SHOW_ALERT, {
+          fire(this, 'show-alert', {
             message: toastMessage,
             // Persist this alert.
             dismissOnNavigation: true,
@@ -3212,7 +3208,7 @@
       e.detail.change._number,
       e.detail.starred
     );
-    fireEvent(this, 'hide-alert');
+    fire(this, 'hide-alert', {});
   }
 
   private getRevisionInfo(): RevisionInfoClass | undefined {
@@ -3240,6 +3236,7 @@
 declare global {
   interface HTMLElementEventMap {
     'toggle-star': CustomEvent<ChangeStarToggleStarDetail>;
+    'change-details-loaded': CustomEvent<{}>;
   }
   interface HTMLElementTagNameMap {
     'gr-change-view': GrChangeView;
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
index cbe3430..2129918 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
@@ -14,7 +14,7 @@
 import {BindValueChangeEvent} from '../../../types/events';
 import {ShortcutController} from '../../lit/shortcut-controller';
 import {ChangeActionDialog} from '../../../types/common';
-import {fireEventNoBubble, fireNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -133,14 +133,14 @@
 
   // private but used in test
   confirm() {
-    fireNoBubble(this, 'confirm', {reason: this.message});
+    fireNoBubble(this, 'confirm', {});
   }
 
   // private but used in test
   handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 
   private handleBindValueChanged(e: BindValueChangeEvent) {
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.ts
index 34a3161..7723327 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-conflict-dialog/gr-confirm-cherrypick-conflict-dialog.ts
@@ -7,7 +7,7 @@
 import {customElement} from 'lit/decorators.js';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {ChangeActionDialog} from '../../../types/common';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 import '../../shared/gr-dialog/gr-dialog';
 
 @customElement('gr-confirm-cherrypick-conflict-dialog')
@@ -67,13 +67,13 @@
   handleConfirmTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'confirm');
+    fireNoBubble(this, 'confirm', {});
   }
 
   handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 }
 
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
index 8ce0f51..4d2602e 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
@@ -30,7 +30,7 @@
   ChangeStatus,
   ProgressStatus,
 } from '../../../constants/constants';
-import {fireEvent, fireEventNoBubble} from '../../../utils/event-util';
+import {fire, fireNoBubble} from '../../../utils/event-util';
 import {css, html, LitElement, PropertyValues} from 'lit';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {choose} from 'lit/directives/choose.js';
@@ -503,12 +503,12 @@
 
   private handlecherryPickSingleChangeClicked() {
     this.cherryPickType = CherryPickType.SINGLE_CHANGE;
-    fireEvent(this, 'iron-resize');
+    fire(this, 'iron-resize', {});
   }
 
   private handlecherryPickTopicClicked() {
     this.cherryPickType = CherryPickType.TOPIC;
-    fireEvent(this, 'iron-resize');
+    fire(this, 'iron-resize', {});
   }
 
   private computeMessage() {
@@ -605,13 +605,13 @@
       return;
     }
     // Cherry pick single change
-    fireEventNoBubble(this, 'confirm');
+    fireNoBubble(this, 'confirm', {});
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 
   resetFocus() {
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
index db14694..6f82e8c 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
@@ -15,7 +15,7 @@
 import {ValueChangedEvent} from '../../../types/events';
 import {ShortcutController} from '../../lit/shortcut-controller';
 import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 const SUGGESTIONS_LIMIT = 15;
 
@@ -143,13 +143,13 @@
   private handleConfirmTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'confirm');
+    fireNoBubble(this, 'confirm', {});
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 
   private getProjectBranchesSuggestions(input: string) {
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
index 3150fc8..34869f2 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog.ts
@@ -22,10 +22,7 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {ValueChangedEvent} from '../../../types/events';
 import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
-import {
-  fireEventNoBubbleNoCompose,
-  fireNoBubbleNoCompose,
-} from '../../../utils/event-util';
+import {fireNoBubbleNoCompose} from '../../../utils/event-util';
 
 export interface RebaseChange {
   name: string;
@@ -355,14 +352,14 @@
       allowConflicts: this.rebaseAllowConflicts.checked,
       rebaseChain: !!this.rebaseChain?.checked,
     };
-    fireNoBubbleNoCompose(this, 'confirm', detail);
+    fireNoBubbleNoCompose(this, 'confirm-rebase', detail);
     this.text = '';
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubbleNoCompose(this, 'cancel');
+    fireNoBubbleNoCompose(this, 'cancel', {});
     this.text = '';
   }
 
@@ -398,4 +395,7 @@
   interface HTMLElementTagNameMap {
     'gr-confirm-rebase-dialog': GrConfirmRebaseDialog;
   }
+  interface HTMLElementEventMap {
+    'confirm-rebase': CustomEvent<ConfirmRebaseEventDetail>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts
index dd9a5ee..fedc377 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts
@@ -30,21 +30,6 @@
   message?: string;
 }
 
-export interface CancelRevertEventDetail {
-  revertType: RevertType;
-}
-
-declare global {
-  interface HTMLElementEventMap {
-    /** Fired when the confirm button is pressed. */
-    // prettier-ignore
-    'confirm': CustomEvent<ConfirmRevertEventDetail>;
-    /** Fired when the cancel button is pressed. */
-    // prettier-ignore
-    'cancel': CustomEvent<CancelRevertEventDetail>;
-  }
-}
-
 @customElement('gr-confirm-revert-dialog')
 export class GrConfirmRevertDialog
   extends LitElement
@@ -302,16 +287,13 @@
       revertType: this.revertType,
       message: this.message,
     };
-    fire(this, 'confirm', detail);
+    fire(this, 'confirm-revert', detail);
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    const detail: ConfirmRevertEventDetail = {
-      revertType: this.revertType,
-    };
-    fire(this, 'cancel', detail);
+    fire(this, 'cancel', {});
   }
 }
 
@@ -319,4 +301,7 @@
   interface HTMLElementTagNameMap {
     'gr-confirm-revert-dialog': GrConfirmRevertDialog;
   }
+  interface HTMLElementEventMap {
+    'confirm-revert': CustomEvent<ConfirmRevertEventDetail>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts
index 38309f2..904285f 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts
@@ -7,7 +7,6 @@
 import '../../../test/common-test-setup';
 import {createChange} from '../../../test/test-data-generators';
 import {ChangeSubmissionId, CommitId} from '../../../types/common';
-import {EventType} from '../../../types/events';
 import './gr-confirm-revert-dialog';
 import {GrConfirmRevertDialog} from './gr-confirm-revert-dialog';
 
@@ -47,7 +46,7 @@
   test('no match', () => {
     assert.isNotOk(element.message);
     const alertStub = sinon.stub();
-    element.addEventListener(EventType.SHOW_ALERT, alertStub);
+    element.addEventListener('show-alert', alertStub);
     element.populateRevertSingleChangeMessage(
       createChange(),
       'not a commitHash in sight',
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.ts
index bf1c5ca..b5297fd 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-submit-dialog/gr-confirm-submit-dialog.ts
@@ -21,7 +21,7 @@
 import {commentsModelToken} from '../../../models/comments/comments-model';
 import {changeModelToken} from '../../../models/change/change-model';
 import {resolve} from '../../../models/dependency';
-import {fireEventNoBubbleNoCompose} from '../../../utils/event-util';
+import {fireNoBubbleNoCompose} from '../../../utils/event-util';
 
 @customElement('gr-confirm-submit-dialog')
 export class GrConfirmSubmitDialog
@@ -194,13 +194,13 @@
   private handleConfirmTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubbleNoCompose(this, 'confirm');
+    fireNoBubbleNoCompose(this, 'confirm', {});
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubbleNoCompose(this, 'cancel');
+    fireNoBubbleNoCompose(this, 'cancel', {});
   }
 }
 
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts
index 7efea5f..11dc890 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.ts
@@ -9,7 +9,7 @@
 import {GrDownloadCommands} from '../../shared/gr-download-commands/gr-download-commands';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {copyToClipbard, hasOwnProperty} from '../../../utils/common-util';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {fontStyles} from '../../../styles/gr-font-styles';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, PropertyValues, html, css} from 'lit';
@@ -233,7 +233,7 @@
       commands[index].command,
       `${commands[index].title} command`
     );
-    fireEvent(this, 'close');
+    fire(this, 'close', {});
   }
 
   override focus() {
@@ -323,7 +323,7 @@
   private handleCloseTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEvent(this, 'close');
+    fire(this, 'close', {});
   }
 
   private schemesChanged() {
diff --git a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
index 4403a8f..69297f6 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list-header/gr-file-list-header.ts
@@ -25,7 +25,7 @@
 import {DiffPreferencesInfo} from '../../../types/diff';
 import {GrDiffModeSelector} from '../../../embed/diff/gr-diff-mode-selector/gr-diff-mode-selector';
 import {GrButton} from '../../shared/gr-button/gr-button';
-import {fireEvent, fireEventNoBubbleNoCompose} from '../../../utils/event-util';
+import {fire, fireNoBubbleNoCompose} from '../../../utils/event-util';
 import {css, html, LitElement} from 'lit';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {when} from 'lit/directives/when.js';
@@ -45,22 +45,6 @@
 
 @customElement('gr-file-list-header')
 export class GrFileListHeader extends LitElement {
-  /**
-   * @event expand-diffs
-   */
-
-  /**
-   * @event collapse-diffs
-   */
-
-  /**
-   * @event open-diff-prefs
-   */
-
-  /**
-   * @event open-download-dialog
-   */
-
   @property({type: Object})
   account: AccountInfo | undefined;
 
@@ -378,11 +362,11 @@
   }
 
   private expandAllDiffs() {
-    fireEvent(this, 'expand-diffs');
+    fire(this, 'expand-diffs', {});
   }
 
   private collapseAllDiffs() {
-    fireEvent(this, 'collapse-diffs');
+    fire(this, 'collapse-diffs', {});
   }
 
   private computeExpandedClass(filesExpanded?: FilesExpandedState) {
@@ -419,13 +403,13 @@
 
   private handlePrefsTap(e: Event) {
     e.preventDefault();
-    fireEvent(this, 'open-diff-prefs');
+    fire(this, 'open-diff-prefs', {});
   }
 
   private handleDownloadTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubbleNoCompose(this, 'open-download-dialog');
+    fireNoBubbleNoCompose(this, 'open-download-dialog', {});
   }
 
   private computeEditModeClass(editMode?: boolean) {
@@ -449,4 +433,10 @@
   interface HTMLElementTagNameMap {
     'gr-file-list-header': GrFileListHeader;
   }
+  interface HTMLElementEventMap {
+    'collapse-diffs': CustomEvent<{}>;
+    'expand-diffs': CustomEvent<{}>;
+    'open-diff-prefs': CustomEvent<{}>;
+    'open-download-dialog': CustomEvent<{}>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.ts b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.ts
index c6eaef7..33dfe82 100644
--- a/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-included-in-dialog/gr-included-in-dialog.ts
@@ -12,7 +12,7 @@
 import {LitElement, PropertyValues, html, css} from 'lit';
 import {customElement, property, state} from 'lit/decorators.js';
 import {BindValueChangeEvent} from '../../../types/events';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 interface DisplayGroup {
   title: string;
@@ -198,7 +198,7 @@
   private handleCloseTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'close');
+    fireNoBubble(this, 'close', {});
   }
 }
 
diff --git a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
index 992a1dc..72969a7 100644
--- a/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
+++ b/polygerrit-ui/app/elements/change/gr-message/gr-message.ts
@@ -63,7 +63,7 @@
   interface HTMLElementEventMap {
     'message-anchor-tap': CustomEvent<MessageAnchorTapDetail>;
     'change-message-deleted': CustomEvent<ChangeMessageDeletedEventDetail>;
-    /* prettier-ignore */
+    // prettier-ignore
     'reply': ReplyEvent;
   }
 }
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index 9f2c6be..a2ffcb8 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -93,9 +93,9 @@
 import {
   fireAlert,
   fireError,
-  fireEvent,
-  fireEventNoBubble,
-  fireEventNoBubbleNoCompose,
+  fire,
+  fireNoBubble,
+  fireNoBubbleNoCompose,
   fireIronAnnounce,
   fireReload,
   fireServerError,
@@ -175,43 +175,6 @@
 
 @customElement('gr-reply-dialog')
 export class GrReplyDialog extends LitElement {
-  /**
-   * Fired when a reply is successfully sent.
-   *
-   * @event send
-   */
-
-  /**
-   * Fired when the user presses the cancel button.
-   *
-   * @event cancel
-   */
-
-  /**
-   * Fires to show an alert when a send is attempted on the non-latest patch.
-   *
-   * @event show-alert
-   */
-
-  /**
-   * Fires when the reply dialog believes that the server side diff drafts
-   * have been updated and need to be refreshed.
-   *
-   * @event comment-refresh
-   */
-
-  /**
-   * Fires when the state of the send button (enabled/disabled) changes.
-   *
-   * @event send-disabled-changed
-   */
-
-  /**
-   * Fired to reload the change page.
-   *
-   * @event reload
-   */
-
   FocusTarget = FocusTarget;
 
   private readonly reporting = getAppContext().reportingService;
@@ -1295,7 +1258,7 @@
     if (this.restApiService.hasPendingDiffDrafts()) {
       this.savingComments = true;
       this.restApiService.awaitPendingDiffDrafts().then(() => {
-        fireEvent(this, 'comment-refresh');
+        fire(this, 'comment-refresh', {});
         this.savingComments = false;
       });
     }
@@ -1485,7 +1448,7 @@
 
         this.patchsetLevelDraftMessage = '';
         this.includeComments = true;
-        fireEventNoBubble(this, 'send');
+        fireNoBubble(this, 'send', {});
         fireIronAnnounce(this, 'Reply sent');
         return;
       })
@@ -1599,7 +1562,7 @@
   onAttentionExpandedChange() {
     // If the attention-detail section is expanded without dispatching this
     // event, then the dialog may expand beyond the screen's bottom border.
-    fireEvent(this, 'iron-resize');
+    fire(this, 'iron-resize', {});
   }
 
   computeAttentionButtonTitle(sendDisabled?: boolean) {
@@ -1868,7 +1831,7 @@
   async cancel() {
     assertIsDefined(this.change, 'change');
     if (!this.change?.owner) throw new Error('missing required owner property');
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
     await this.patchsetLevelGrComment?.save();
     this.rebuildReviewerArrays();
   }
@@ -2076,7 +2039,7 @@
   }
 
   sendDisabledChanged() {
-    fireEventNoBubbleNoCompose(this, 'send-disabled-changed');
+    fireNoBubbleNoCompose(this, 'send-disabled-changed', {});
   }
 
   getReviewerSuggestionsProvider(change?: ChangeInfo | ParsedChangeInfo) {
@@ -2132,4 +2095,19 @@
   interface HTMLElementTagNameMap {
     'gr-reply-dialog': GrReplyDialog;
   }
+  interface HTMLElementEventMap {
+    /** Fired when the user presses the cancel button. */
+    // prettier-ignore
+    'cancel': CustomEvent<{}>;
+    /**
+     * Fires when the reply dialog believes that the server side diff drafts
+     * have been updated and need to be refreshed.
+     */
+    'comment-refresh': CustomEvent<{}>;
+    /** Fired when a reply is successfully sent. */
+    // prettier-ignore
+    'send': CustomEvent<{}>;
+    /** Fires when the state of the send button (enabled/disabled) changes. */
+    'send-disabled-changed': CustomEvent<{}>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
index f7b3aec..5bf6464 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog_test.ts
@@ -1886,7 +1886,7 @@
 
     // Remove and add to other field.
     reviewers.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: reviewer1},
         composed: true,
         bubbles: true,
@@ -1903,14 +1903,14 @@
       })
     );
     ccs.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: cc1},
         composed: true,
         bubbles: true,
       })
     );
     ccs.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: cc3},
         composed: true,
         bubbles: true,
diff --git a/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts b/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts
index 66ad38c..2766114 100644
--- a/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts
+++ b/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard.ts
@@ -10,13 +10,12 @@
 import {
   AccountInfo,
   ChangeStatus,
-  isDetailedLabelInfo,
   SubmitRequirementExpressionInfo,
   SubmitRequirementResultInfo,
   SubmitRequirementStatus,
 } from '../../../api/rest-api';
 import {
-  canVote,
+  canReviewerVote,
   extractAssociatedLabels,
   getApprovalInfo,
   hasVotes,
@@ -204,7 +203,7 @@
       if (requirementLabels.includes(label)) {
         const labelInfo = allLabels[label];
         const canSomeoneVote = (this.change?.reviewers['REVIEWER'] ?? []).some(
-          reviewer => canVote(labelInfo, reviewer)
+          reviewer => canReviewerVote(labelInfo, reviewer)
         );
         if (hasVotes(labelInfo) || canSomeoneVote) {
           labels.push(label);
@@ -280,15 +279,17 @@
     labelName: string,
     type: 'override' | 'submittability'
   ) {
+    if (!this.account) return;
+    const votes = this.change?.permitted_labels?.[labelName];
+    if (!votes || votes.length < 1) return;
+    const maxVote = Number(votes[votes.length - 1]);
+    if (maxVote <= 0) return;
+
     const labels = this.change?.labels ?? {};
     const labelInfo = labels[labelName];
-    if (!labelInfo || !isDetailedLabelInfo(labelInfo)) return;
-    if (!this.account || !canVote(labelInfo, this.account)) return;
-
     const approvalInfo = getApprovalInfo(labelInfo, this.account);
-    const maxVote = approvalInfo?.permitted_voting_range?.max;
-    if (!maxVote || maxVote <= 0) return;
     if (approvalInfo?.value === maxVote) return; // Already voted maxVote
+
     return html` <div class="button quickApprove">
       <gr-button
         link=""
diff --git a/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard_test.ts b/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard_test.ts
index 4e78e8a..18f8e4c 100644
--- a/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-submit-requirement-hovercard/gr-submit-requirement-hovercard_test.ts
@@ -253,6 +253,9 @@
     const change: ParsedChangeInfo = {
       ...createParsedChange(),
       status: ChangeStatus.NEW,
+      permitted_labels: {
+        Verified: ['-1', ' 0', '+1', '+2'],
+      },
       labels: {
         Verified: {
           ...createDetailedLabelInfo(),
@@ -351,6 +354,9 @@
       const change: ParsedChangeInfo = {
         ...createParsedChange(),
         status: ChangeStatus.NEW,
+        permitted_labels: {
+          'Build-Cop': ['-1', ' 0', '+1', '+2'],
+        },
         labels: {
           'Build-Cop': {
             ...createDetailedLabelInfo(),
diff --git a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.ts b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.ts
index b46d2b9..98dd574 100644
--- a/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.ts
+++ b/polygerrit-ui/app/elements/core/gr-account-dropdown/gr-account-dropdown.ts
@@ -8,7 +8,7 @@
 import {getUserName} from '../../../utils/display-name-util';
 import {AccountInfo, ServerInfo} from '../../../types/common';
 import {getAppContext} from '../../../services/app-context';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {
   DropdownContent,
   DropdownLink,
@@ -23,6 +23,9 @@
   interface HTMLElementTagNameMap {
     'gr-account-dropdown': GrAccountDropdown;
   }
+  interface HTMLElementEventMap {
+    'show-keyboard-shortcuts': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-account-dropdown')
@@ -136,7 +139,7 @@
   }
 
   _handleShortcutsTap() {
-    fireEvent(this, 'show-keyboard-shortcuts');
+    fire(this, 'show-keyboard-shortcuts', {});
   }
 
   private readonly handleLocationChange = () => {
diff --git a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.ts b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.ts
index 3898186..5510aa3 100644
--- a/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.ts
+++ b/polygerrit-ui/app/elements/core/gr-error-dialog/gr-error-dialog.ts
@@ -7,12 +7,16 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, html, css} from 'lit';
 import {customElement, property} from 'lit/decorators.js';
-import {fireEventNoBubbleNoCompose} from '../../../utils/event-util';
+import {fireNoBubbleNoCompose} from '../../../utils/event-util';
 
 declare global {
   interface HTMLElementTagNameMap {
     'gr-error-dialog': GrErrorDialog;
   }
+  interface HTMLElementEventMap {
+    // prettier-ignore
+    'dismiss': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-error-dialog')
@@ -84,6 +88,6 @@
   }
 
   private handleConfirm() {
-    fireEventNoBubbleNoCompose(this, 'dismiss');
+    fireNoBubbleNoCompose(this, 'dismiss', {});
   }
 }
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
index 1176ce3..e8675bc 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager.ts
@@ -14,7 +14,6 @@
 import {AccountId} from '../../../types/common';
 import {
   AuthErrorEvent,
-  EventType,
   NetworkErrorEvent,
   ServerErrorEvent,
   ShowAlertEventDetail,
@@ -124,9 +123,9 @@
 
   override connectedCallback() {
     super.connectedCallback();
-    document.addEventListener(EventType.SERVER_ERROR, this.handleServerError);
-    document.addEventListener(EventType.NETWORK_ERROR, this.handleNetworkError);
-    document.addEventListener(EventType.SHOW_ALERT, this.handleShowAlert);
+    document.addEventListener('server-error', this.handleServerError);
+    document.addEventListener('network-error', this.handleNetworkError);
+    document.addEventListener('show-alert', this.handleShowAlert);
     document.addEventListener('hide-alert', this.hideAlert);
     document.addEventListener('show-error', this.handleShowErrorDialog);
     document.addEventListener('visibilitychange', this.handleVisibilityChange);
@@ -140,15 +139,9 @@
 
   override disconnectedCallback() {
     this.clearHideAlertHandle();
-    document.removeEventListener(
-      EventType.SERVER_ERROR,
-      this.handleServerError
-    );
-    document.removeEventListener(
-      EventType.NETWORK_ERROR,
-      this.handleNetworkError
-    );
-    document.removeEventListener(EventType.SHOW_ALERT, this.handleShowAlert);
+    document.removeEventListener('server-error', this.handleServerError);
+    document.removeEventListener('network-error', this.handleNetworkError);
+    document.removeEventListener('show-alert', this.handleShowAlert);
     document.removeEventListener('hide-alert', this.hideAlert);
     document.removeEventListener('show-error', this.handleShowErrorDialog);
     document.removeEventListener(
@@ -358,7 +351,7 @@
     el.show(text, actionText, actionCallback);
     this.alertElement = el;
     fireIronAnnounce(this, `Alert: ${text}`);
-    this.reporting.reportInteraction(EventType.SHOW_ALERT, {text});
+    this.reporting.reportInteraction('show-alert', {text});
   }
 
   private readonly hideAlert = () => {
diff --git a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.ts b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.ts
index f4ee5ed..fff69ef 100644
--- a/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.ts
+++ b/polygerrit-ui/app/elements/core/gr-error-manager/gr-error-manager_test.ts
@@ -24,7 +24,6 @@
 import {waitUntil} from '../../../test/test-utils';
 import {fixture, assert} from '@open-wc/testing';
 import {html} from 'lit';
-import {EventType} from '../../../types/events';
 import {testResolver} from '../../../test/common-test-setup';
 import {authServiceToken} from '../../../services/gr-auth/gr-auth';
 
@@ -391,7 +390,7 @@
 
       // fake an alert
       element.dispatchEvent(
-        new CustomEvent(EventType.SHOW_ALERT, {
+        new CustomEvent('show-alert', {
           detail: {message: 'test reload', action: 'reload'},
           composed: true,
           bubbles: true,
@@ -439,7 +438,7 @@
 
       // fake an alert
       element.dispatchEvent(
-        new CustomEvent(EventType.SHOW_ALERT, {
+        new CustomEvent('show-alert', {
           detail: {message: 'test reload', action: 'reload'},
           composed: true,
           bubbles: true,
@@ -452,7 +451,7 @@
 
       // new alert
       element.dispatchEvent(
-        new CustomEvent(EventType.SHOW_ALERT, {
+        new CustomEvent('show-alert', {
           detail: {message: 'second-test', action: 'reload'},
           composed: true,
           bubbles: true,
@@ -498,7 +497,7 @@
 
       // fake an alert
       element.dispatchEvent(
-        new CustomEvent(EventType.SHOW_ALERT, {
+        new CustomEvent('show-alert', {
           detail: {
             message: 'test-alert',
             action: 'reload',
@@ -519,7 +518,7 @@
       const alertObj = {message: 'foo'};
       const showAlertStub = sinon.stub(element, '_showAlert');
       element.dispatchEvent(
-        new CustomEvent(EventType.SHOW_ALERT, {
+        new CustomEvent('show-alert', {
           detail: alertObj,
           composed: true,
           bubbles: true,
diff --git a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.ts b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.ts
index 68ff9e1..a359072 100644
--- a/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.ts
+++ b/polygerrit-ui/app/elements/core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.ts
@@ -16,7 +16,7 @@
   ShortcutViewListener,
 } from '../../../services/shortcuts/shortcuts-service';
 import {resolve} from '../../../models/dependency';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -163,7 +163,7 @@
   private handleCloseTap(e: MouseEvent) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'close');
+    fireNoBubble(this, 'close', {});
   }
 
   onDirectoryUpdated(directory?: Map<ShortcutSection, SectionView>) {
diff --git a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
index 833a91a..beb843a 100644
--- a/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
+++ b/polygerrit-ui/app/elements/core/gr-main-header/gr-main-header.ts
@@ -25,7 +25,7 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, PropertyValues, html, css} from 'lit';
 import {customElement, property, state} from 'lit/decorators.js';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {resolve} from '../../../models/dependency';
 import {configModelToken} from '../../../models/config/config-model';
 import {userModelToken} from '../../../models/user/user-model';
@@ -97,6 +97,9 @@
   interface HTMLElementTagNameMap {
     'gr-main-header': GrMainHeader;
   }
+  interface HTMLElementEventMap {
+    'mobile-search': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-main-header')
@@ -641,6 +644,6 @@
   private onMobileSearchTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEvent(this, 'mobile-search');
+    fire(this, 'mobile-search', {});
   }
 }
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
index a686b20..b317b97 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
@@ -17,7 +17,7 @@
 } from '../../../test/test-data-generators';
 import {createDefaultDiffPrefs} from '../../../constants/constants';
 import {DiffInfo} from '../../../types/diff';
-import {EventType, OpenFixPreviewEventDetail} from '../../../types/events';
+import {OpenFixPreviewEventDetail} from '../../../types/events';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {fixture, html, assert} from '@open-wc/testing';
 import {SinonStub} from 'sinon';
@@ -51,7 +51,7 @@
 
   async function open(detail: OpenFixPreviewEventDetail) {
     element.open(
-      new CustomEvent<OpenFixPreviewEventDetail>(EventType.OPEN_FIX_PREVIEW, {
+      new CustomEvent<OpenFixPreviewEventDetail>('open-fix-preview', {
         detail,
       })
     );
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
index 79145db..43a6819 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -58,9 +58,8 @@
   firePageError,
   fireAlert,
   fireServerError,
-  fireEvent,
-  waitForEventOnce,
   fire,
+  waitForEventOnce,
 } from '../../../utils/event-util';
 import {assertIsDefined} from '../../../utils/common-util';
 import {DiffContextExpandedEventDetail} from '../../../embed/diff/gr-diff-builder/gr-diff-builder';
@@ -123,8 +122,8 @@
 
 declare global {
   interface HTMLElementEventMap {
-    /* prettier-ignore */
-    'render': CustomEvent<void>;
+    // prettier-ignore
+    'render': CustomEvent<{}>;
     'diff-context-expanded': CustomEvent<DiffContextExpandedEventDetail>;
     'create-comment': CustomEvent<CreateCommentEventDetail>;
     'is-blame-loaded-changed': ValueChangedEvent<boolean>;
@@ -135,7 +134,7 @@
     // Fired when the user selects a line (See gr-diff).
     'line-selected': CustomEvent<LineSelectedEventDetail>;
     // Fired if being logged in is required.
-    'show-auth-required': void;
+    'show-auth-required': CustomEvent<{}>;
   }
 }
 
@@ -1242,7 +1241,7 @@
 
   private canCommentOnPatchSetNum(patchNum: PatchSetNum) {
     if (!this.loggedIn) {
-      fireEvent(this, 'show-auth-required');
+      fire(this, 'show-auth-required', {});
       return false;
     }
     if (!this.patchRange) {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts
index 7a32c27..141a24d 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_test.ts
@@ -51,7 +51,6 @@
 import {GrCommentThread} from '../../shared/gr-comment-thread/gr-comment-thread';
 import {assertIsDefined} from '../../../utils/common-util';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 import {testResolver} from '../../../test/common-test-setup';
 import {userModelToken, UserModel} from '../../../models/user/user-model';
 import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
@@ -662,7 +661,7 @@
     test('loadBlame', async () => {
       const mockBlame: BlameInfo[] = [createBlame()];
       const showAlertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, showAlertStub);
+      element.addEventListener('show-alert', showAlertStub);
       const getBlameStub = stubRestApi('getBlame').returns(
         Promise.resolve(mockBlame)
       );
@@ -694,7 +693,7 @@
       const mockBlame: BlameInfo[] = [];
       const showAlertStub = sinon.stub();
       const isBlameLoadedStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, showAlertStub);
+      element.addEventListener('show-alert', showAlertStub);
       element.addEventListener('is-blame-loaded-changed', isBlameLoadedStub);
       stubRestApi('getBlame').returns(Promise.resolve(mockBlame));
       const changeNum = 42 as NumericChangeId;
@@ -1328,7 +1327,7 @@
 
     test('cannot create thread on an edit', () => {
       const alertSpy = sinon.spy();
-      element.addEventListener(EventType.SHOW_ALERT, alertSpy);
+      element.addEventListener('show-alert', alertSpy);
 
       const diffSide = Side.RIGHT;
       element.patchRange = {
@@ -1356,7 +1355,7 @@
 
     test('cannot create thread on an edit base', () => {
       const alertSpy = sinon.spy();
-      element.addEventListener(EventType.SHOW_ALERT, alertSpy);
+      element.addEventListener('show-alert', alertSpy);
 
       const diffSide = Side.LEFT;
       element.patchRange = {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.ts b/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.ts
index 69ff201..d580127 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-preferences-dialog/gr-diff-preferences-dialog.ts
@@ -12,7 +12,7 @@
 import {customElement, query, state} from 'lit/decorators.js';
 import {ValueChangedEvent} from '../../../types/events';
 import {modalStyles} from '../../../styles/gr-modal-styles';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 @customElement('gr-diff-preferences-dialog')
 export class GrDiffPreferencesDialog extends LitElement {
@@ -121,7 +121,7 @@
     assertIsDefined(this.diffPreferences, 'diffPreferences');
     assertIsDefined(this.diffPrefsModal, 'diffPrefsModal');
     await this.diffPreferences.save();
-    fireEventNoBubble(this, 'reload-diff-preference');
+    fireNoBubble(this, 'reload-diff-preference', {});
     this.diffPrefsModal.close();
   }
 
@@ -136,4 +136,7 @@
   interface HTMLElementTagNameMap {
     'gr-diff-preferences-dialog': GrDiffPreferencesDialog;
   }
+  interface HTMLElementEventMap {
+    'reload-diff-preference': CustomEvent<{}>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index b9074b4..14eb505 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -58,7 +58,7 @@
 import {GrApplyFixDialog} from '../gr-apply-fix-dialog/gr-apply-fix-dialog';
 import {CommentMap} from '../../../utils/comment-util';
 import {OpenFixPreviewEvent, ValueChangedEvent} from '../../../types/events';
-import {fireAlert, fireEvent, fireTitleChange} from '../../../utils/event-util';
+import {fireAlert, fire, fireTitleChange} from '../../../utils/event-util';
 import {assertIsDefined, queryAndAssert} from '../../../utils/common-util';
 import {toggleClass, whenVisible} from '../../../utils/dom-util';
 import {CursorMoveResult} from '../../../api/core';
@@ -1197,7 +1197,7 @@
   // Similar to gr-change-view.handleOpenReplyDialog
   private handleOpenReplyDialog() {
     if (!this.loggedIn) {
-      fireEvent(this, 'show-auth-required');
+      fire(this, 'show-auth-required', {});
       return;
     }
     this.getChangeModel().navigateToChange(true);
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts
index 6507046..e7e1bc8 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.ts
@@ -60,7 +60,6 @@
 import {assertIsDefined} from '../../../utils/common-util';
 import {GrDiffModeSelector} from '../../../embed/diff/gr-diff-mode-selector/gr-diff-mode-selector';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {testResolver} from '../../../test/common-test-setup';
 import {UserModel, userModelToken} from '../../../models/user/user-model';
@@ -1698,10 +1697,7 @@
         pressKey(element, 'n');
 
         assert.isTrue(moveToNextChunkStub.called);
-        assert.equal(
-          dispatchEventStub.lastCall.args[0].type,
-          EventType.SHOW_ALERT
-        );
+        assert.equal(dispatchEventStub.lastCall.args[0].type, 'show-alert');
         assert.isFalse(navToFileStub.called);
       });
 
@@ -1741,10 +1737,7 @@
         pressKey(element, 'p');
 
         assert.isTrue(moveToPreviousChunkStub.called);
-        assert.equal(
-          dispatchEventStub.lastCall.args[0].type,
-          EventType.SHOW_ALERT
-        );
+        assert.equal(dispatchEventStub.lastCall.args[0].type, 'show-alert');
         assert.isFalse(navToFileStub.called);
       });
 
diff --git a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts
index 584fcd7..3813946 100644
--- a/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-patch-range-select/gr-patch-range-select_test.ts
@@ -469,10 +469,10 @@
     await element.updateComplete;
 
     const stub = stubReporting('reportInteraction');
-    fire(element.patchNumDropdown!, 'value-change', {value: '1'});
+    fire(element.patchNumDropdown, 'value-change', {value: '1'});
     assert.isFalse(stub.called);
 
-    fire(element.patchNumDropdown!, 'value-change', {value: '2'});
+    fire(element.patchNumDropdown, 'value-change', {value: '2'});
     assert.isTrue(stub.called);
   });
 });
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts
index 242ddea..0a36a05 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view_test.ts
@@ -27,7 +27,6 @@
 import {GrDefaultEditor} from '../gr-default-editor/gr-default-editor';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 import {Modifier} from '../../../utils/dom-util';
 import {testResolver} from '../../../test/common-test-setup';
 import {storageServiceToken} from '../../../services/storage/gr-storage_impl';
@@ -445,7 +444,7 @@
 
   test('showAlert', async () => {
     const promise = mockPromise();
-    element.addEventListener(EventType.SHOW_ALERT, e => {
+    element.addEventListener('show-alert', e => {
       assert.deepEqual(e.detail, {message: 'test message', showDismiss: true});
       assert.isTrue(e.bubbles);
       promise.resolve();
@@ -533,7 +532,7 @@
       };
 
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
 
       return element.getFileData().then(async () => {
         await element.updateComplete;
@@ -565,7 +564,7 @@
       };
 
       const alertStub = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, alertStub);
+      element.addEventListener('show-alert', alertStub);
 
       return element.getFileData().then(async () => {
         await element.updateComplete;
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts
index e5991f6..98f1f25 100644
--- a/polygerrit-ui/app/elements/gr-app-element.ts
+++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -47,7 +47,6 @@
 import {GrSettingsView} from './settings/gr-settings-view/gr-settings-view';
 import {
   DialogChangeEventDetail,
-  EventType,
   PageErrorEventDetail,
   RpcLogEvent,
   TitleChangeEventDetail,
@@ -175,19 +174,19 @@
   constructor() {
     super();
 
-    document.addEventListener(EventType.PAGE_ERROR, e => {
+    document.addEventListener('page-error', e => {
       this.handlePageError(e);
     });
-    this.addEventListener(EventType.TITLE_CHANGE, e => {
+    this.addEventListener('title-change', e => {
       this.handleTitleChange(e);
     });
-    this.addEventListener(EventType.DIALOG_CHANGE, e => {
+    this.addEventListener('dialog-change', e => {
       this.handleDialogChange(e as CustomEvent<DialogChangeEventDetail>);
     });
-    document.addEventListener(EventType.LOCATION_CHANGE, () =>
+    document.addEventListener('location-change', () =>
       this.handleLocationChange()
     );
-    document.addEventListener(EventType.GR_RPC_LOG, e => this.handleRpcLog(e));
+    document.addEventListener('gr-rpc-log', e => this.handleRpcLog(e));
     this.shortcuts.addAbstract(Shortcut.OPEN_SHORTCUT_HELP_DIALOG, () =>
       this.showKeyboardShortcuts()
     );
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
index 0e75abb..89513e3 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
@@ -15,7 +15,7 @@
 import {AccountDetailInfo, ServerInfo} from '../../../types/common';
 import {EditableAccountField} from '../../../constants/constants';
 import {getAppContext} from '../../../services/app-context';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {LitElement, css, html, nothing, PropertyValues} from 'lit';
 import {customElement, property, state} from 'lit/decorators.js';
 import {sharedStyles} from '../../../styles/shared-styles';
@@ -25,12 +25,6 @@
 
 @customElement('gr-account-info')
 export class GrAccountInfo extends LitElement {
-  /**
-   * Fired when account details are changed.
-   *
-   * @event account-detail-update
-   */
-
   // private but used in test
   @state() nameMutable?: boolean;
 
@@ -341,7 +335,7 @@
         this.hasDisplayNameChange = false;
         this.hasStatusChange = false;
         this.saving = false;
-        fireEvent(this, 'account-detail-update');
+        fire(this, 'account-detail-update', {});
       });
   }
 
@@ -410,6 +404,8 @@
 declare global {
   interface HTMLElementEventMap {
     'unsaved-changes-changed': ValueChangedEvent<boolean>;
+    /** Fired when account details are changed. */
+    'account-detail-update': CustomEvent<{}>;
   }
   interface HTMLElementTagNameMap {
     'gr-account-info': GrAccountInfo;
diff --git a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.ts b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.ts
index a20c0ee..c6c023e 100644
--- a/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.ts
+++ b/polygerrit-ui/app/elements/settings/gr-registration-dialog/gr-registration-dialog.ts
@@ -9,7 +9,7 @@
 import {ServerInfo, AccountDetailInfo} from '../../../types/common';
 import {EditableAccountField} from '../../../constants/constants';
 import {getAppContext} from '../../../services/app-context';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {LitElement, css, html, PropertyValues} from 'lit';
 import {customElement, property, query, state} from 'lit/decorators.js';
 import {sharedStyles} from '../../../styles/shared-styles';
@@ -27,12 +27,6 @@
 @customElement('gr-registration-dialog')
 export class GrRegistrationDialog extends LitElement {
   /**
-   * Fired when account details are changed.
-   *
-   * @event account-detail-update
-   */
-
-  /**
    * Fired when the close button is pressed.
    *
    * @event close
@@ -293,7 +287,7 @@
 
     return Promise.all(promises).then(() => {
       this.saving = false;
-      fireEvent(this, 'account-detail-update');
+      fire(this, 'account-detail-update', {});
     });
   }
 
@@ -309,7 +303,7 @@
 
   private close() {
     this.saving = true; // disable buttons indefinitely
-    fireEvent(this, 'close');
+    fire(this, 'close', {});
   }
 
   // private but used in test
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts
index a5ef86d..a0d7fab 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts
@@ -38,7 +38,6 @@
 } from '../../../test/test-data-generators';
 import {GrSelect} from '../../shared/gr-select/gr-select';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 
 suite('gr-settings-view tests', () => {
   let element: GrSettingsView;
@@ -915,7 +914,7 @@
       await element._testOnly_loadingPromise;
       assert.equal(
         (dispatchEventSpy.lastCall.args[0] as CustomEvent).type,
-        EventType.SHOW_ALERT
+        'show-alert'
       );
       assert.deepEqual(
         (dispatchEventSpy.lastCall.args[0] as CustomEvent).detail,
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts
index e8c5c92..d7c6c8b 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts
@@ -199,7 +199,7 @@
   private handleRemoveTap(e: MouseEvent) {
     e.preventDefault();
     if (!this.account) return;
-    fire(this, 'remove', {account: this.account});
+    fire(this, 'remove-account', {account: this.account});
   }
 
   private getHasAvatars() {
@@ -230,7 +230,6 @@
     'gr-account-chip': GrAccountChip;
   }
   interface HTMLElementEventMap {
-    /* prettier-ignore */
-    'remove': RemoveAccountEvent;
+    'remove-account': RemoveAccountEvent;
   }
 }
diff --git a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.ts b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.ts
index f07bee6..496dff1 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-entry/gr-account-entry.ts
@@ -15,7 +15,7 @@
 import {AddAccountEvent, BindValueChangeEvent} from '../../../types/events';
 import {SuggestedReviewerInfo} from '../../../types/common';
 import {PaperInputElement} from '@polymer/paper-input/paper-input';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 
 /**
  * gr-account-entry is an element for entering account
@@ -105,7 +105,7 @@
 
   private inputTextChanged() {
     if (this.inputText.length && this.allowAnyInput) {
-      fireEvent(this, 'account-text-changed');
+      fire(this, 'account-text-changed', {});
     }
   }
 
@@ -119,16 +119,14 @@
     'gr-account-entry': GrAccountEntry;
   }
   interface HTMLElementEventMap {
-    /**
-     * Fired when an account is entered.
-     */
-    /* prettier-ignore */
+    /** Fired when an account is entered. */
+    // prettier-ignore
     'add': AddAccountEvent;
     /**
      * When allowAnyInput is true, account-text-changed is fired when input text
      * changed. This is needed so that the reply dialog's save button can be
      * enabled for arbitrary cc's, which don't need a 'commit'.
      */
-    'account-text-changed': CustomEvent<void>;
+    'account-text-changed': CustomEvent<{}>;
   }
 }
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
index 0f85266..cf7ff2209 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.ts
@@ -13,9 +13,8 @@
 import {isSelf, isServiceUser} from '../../../utils/account-util';
 import {ChangeInfo, AccountInfo, ServerInfo} from '../../../types/common';
 import {assertIsDefined, hasOwnProperty} from '../../../utils/common-util';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {isInvolved} from '../../../utils/change-util';
-import {EventType} from '../../../types/events';
 import {LitElement, css, html, TemplateResult} from 'lit';
 import {customElement, property, state} from 'lit/decorators.js';
 import {classMap} from 'lit/directives/class-map.js';
@@ -364,7 +363,7 @@
     e.stopPropagation();
     if (!this.account._account_id) return;
 
-    fire(this, EventType.SHOW_ALERT, {
+    fire(this, 'show-alert', {
       message: 'Saving attention set update ...',
       dismissOnNavigation: true,
     });
@@ -388,7 +387,7 @@
         reason
       )
       .then(() => {
-        fireEvent(this, 'hide-alert');
+        fire(this, 'hide-alert', {});
       });
   }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts
index 9034259..8339df9 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list.ts
@@ -152,7 +152,7 @@
   constructor() {
     super();
     this.querySuggestions = input => this.getSuggestions(input);
-    this.addEventListener('remove', e =>
+    this.addEventListener('remove-account', e =>
       this.handleRemove(e as CustomEvent<{account: AccountInput}>)
     );
   }
diff --git a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.ts b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.ts
index 814b623..e7112df 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-list/gr-account-list_test.ts
@@ -35,7 +35,6 @@
 import {createChange} from '../../../test/test-data-generators';
 import {ReviewerState} from '../../../api/rest-api';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 
 class MockSuggestionsProvider implements ReviewerSuggestionsProvider {
   init() {}
@@ -154,7 +153,7 @@
 
     // Removed accounts are taken out of the list.
     element.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: existingAccount1},
         composed: true,
         bubbles: true,
@@ -168,14 +167,14 @@
 
     // Invalid remove is ignored.
     element.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: existingAccount1},
         composed: true,
         bubbles: true,
       })
     );
     element.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: newAccount},
         composed: true,
         bubbles: true,
@@ -197,7 +196,7 @@
 
     // Removed groups are taken out of the list.
     element.dispatchEvent(
-      new CustomEvent('remove', {
+      new CustomEvent('remove-account', {
         detail: {account: newGroup},
         composed: true,
         bubbles: true,
@@ -292,7 +291,7 @@
   test('addAccountItem with invalid item', () => {
     const toastHandler = sinon.stub();
     element.allowAnyInput = false;
-    element.addEventListener(EventType.SHOW_ALERT, toastHandler);
+    element.addEventListener('show-alert', toastHandler);
     const result = element.addAccountItem('test');
     assert.isFalse(result);
     assert.isTrue(toastHandler.called);
@@ -434,7 +433,7 @@
 
     test('toasts on invalid email', () => {
       const toastHandler = sinon.stub();
-      element.addEventListener(EventType.SHOW_ALERT, toastHandler);
+      element.addEventListener('show-alert', toastHandler);
       handleAdd('test');
       assert.isTrue(toastHandler.called);
     });
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.ts b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.ts
index 34b8f11..4b27948 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.ts
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.ts
@@ -6,7 +6,7 @@
 import '../gr-cursor-manager/gr-cursor-manager';
 import '../../../styles/shared-styles';
 import {GrCursorManager} from '../gr-cursor-manager/gr-cursor-manager';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {Key} from '../../../utils/dom-util';
 import {FitController} from '../../lit/fit-controller';
 import {css, html, LitElement, PropertyValues} from 'lit';
@@ -20,6 +20,9 @@
   interface HTMLElementTagNameMap {
     'gr-autocomplete-dropdown': GrAutocompleteDropdown;
   }
+  interface HTMLElementEventMap {
+    'dropdown-closed': CustomEvent<{}>;
+  }
 }
 
 export interface Item {
@@ -313,7 +316,7 @@
   }
 
   private fireClose() {
-    fireEvent(this, 'dropdown-closed');
+    fire(this, 'dropdown-closed', {});
   }
 
   getCursorTarget() {
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts
index 9b0fa7b..a2be983 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.ts
@@ -13,7 +13,7 @@
   GrAutocompleteDropdown,
   ItemSelectedEventDetail,
 } from '../gr-autocomplete-dropdown/gr-autocomplete-dropdown';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {
   debounce,
   DelayedTask,
@@ -614,7 +614,7 @@
       this.activeQueryId = 0;
       this.requestUpdate();
     } else {
-      fireEvent(this, 'cancel');
+      fire(this, 'cancel', {});
     }
   }
 
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
index c36226a..0edfe03 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -44,7 +44,7 @@
   ReplyToCommentEventDetail,
   ValueChangedEvent,
 } from '../../../types/events';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {assertIsDefined, assert} from '../../../utils/common-util';
 import {Key, Modifier, whenVisible} from '../../../utils/dom-util';
 import {commentsModelToken} from '../../../models/comments/comments-model';
@@ -982,7 +982,7 @@
   }
 
   private handleCopyLink() {
-    fireEvent(this, 'copy-comment-link');
+    fire(this, 'copy-comment-link', {});
   }
 
   /** Enter editing mode. */
@@ -1285,4 +1285,7 @@
   interface HTMLElementTagNameMap {
     'gr-comment': GrComment;
   }
+  interface HTMLElementEventMap {
+    'copy-comment-link': CustomEvent<{}>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts
index 1047b87..e8ab172 100644
--- a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts
+++ b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts
@@ -11,7 +11,7 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {assertIsDefined} from '../../../utils/common-util';
 import {BindValueChangeEvent} from '../../../types/events';
-import {fireEventNoBubble, fireNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -109,12 +109,12 @@
   private handleConfirmTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireNoBubble(this, 'confirm', {reason: this.message});
+    fireNoBubble(this, 'confirm', {});
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 }
diff --git a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.ts b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.ts
index c5ad676..6536806 100644
--- a/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dialog/gr-dialog.ts
@@ -10,7 +10,7 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {fontStyles} from '../../../styles/gr-font-styles';
 import {when} from 'lit/directives/when.js';
-import {fireEventNoBubble} from '../../../utils/event-util';
+import {fireNoBubble} from '../../../utils/event-util';
 
 declare global {
   interface HTMLElementTagNameMap {
@@ -200,13 +200,13 @@
 
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'confirm');
+    fireNoBubble(this, 'confirm', {});
   }
 
   private handleCancelTap(e: Event) {
     e.preventDefault();
     e.stopPropagation();
-    fireEventNoBubble(this, 'cancel');
+    fireNoBubble(this, 'cancel', {});
   }
 
   _handleKeydown(e: KeyboardEvent) {
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts
index 01ebb27..3110a96 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts
@@ -10,7 +10,7 @@
 import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
 import '../../plugins/gr-endpoint-param/gr-endpoint-param';
 import '../../plugins/gr-endpoint-slot/gr-endpoint-slot';
-import {fire, fireAlert, fireEvent} from '../../../utils/event-util';
+import {fire, fireAlert} from '../../../utils/event-util';
 import {getAppContext} from '../../../services/app-context';
 import {debounce, DelayedTask} from '../../../utils/async-util';
 import {queryAndAssert} from '../../../utils/common-util';
@@ -21,7 +21,11 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {css} from 'lit';
 import {PropertyValues} from 'lit';
-import {BindValueChangeEvent, ValueChangedEvent} from '../../../types/events';
+import {
+  BindValueChangeEvent,
+  EditableContentSaveEvent,
+  ValueChangedEvent,
+} from '../../../types/events';
 import {nothing} from 'lit';
 import {classMap} from 'lit/directives/class-map.js';
 import {when} from 'lit/directives/when.js';
@@ -39,24 +43,16 @@
   interface HTMLElementEventMap {
     'content-changed': ValueChangedEvent<string>;
     'editing-changed': ValueChangedEvent<boolean>;
+    /** Fired when the 'cancel' button is pressed. */
+    'editable-content-cancel': CustomEvent<{}>;
+    /** Fired when the 'save' button is pressed. */
+    'editable-content-save': EditableContentSaveEvent;
   }
 }
 
 @customElement('gr-editable-content')
 export class GrEditableContent extends LitElement {
   /**
-   * Fired when the save button is pressed.
-   *
-   * @event editable-content-save
-   */
-
-  /**
-   * Fired when the cancel button is pressed.
-   *
-   * @event editable-content-cancel
-   */
-
-  /**
    * Fired when content is restored from storage.
    *
    * @event show-alert
@@ -395,7 +391,7 @@
   handleCancel(e: Event) {
     e.preventDefault();
     this.editing = false;
-    fireEvent(this, 'editable-content-cancel');
+    fire(this, 'editable-content-cancel', {});
   }
 
   toggleCommitCollapsed() {
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts
index b4f25ce..4a5611b 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts
@@ -9,7 +9,6 @@
 import {query, queryAndAssert} from '../../../test/test-utils';
 import {GrButton} from '../gr-button/gr-button';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 import {StorageService} from '../../../services/storage/gr-storage';
 import {storageServiceToken} from '../../../services/storage/gr-storage_impl';
 import {testResolver} from '../../../test/common-test-setup';
@@ -190,7 +189,7 @@
       await element.updateComplete;
       assert.equal(element.newContent, 'stored content');
       assert.isTrue(dispatchSpy.called);
-      assert.equal(dispatchSpy.lastCall.args[0].type, EventType.SHOW_ALERT);
+      assert.equal(dispatchSpy.lastCall.args[0].type, 'show-alert');
     });
 
     test('editing toggled to true, has no stored data', async () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
index 2730fcf..14c2c15 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
@@ -38,13 +38,12 @@
 import {sharedStyles} from '../../../styles/shared-styles';
 import {css, html, LitElement, nothing} from 'lit';
 import {ifDefined} from 'lit/directives/if-defined.js';
-import {EventType} from '../../../types/events';
 import {subscribe} from '../../lit/subscription-controller';
 import {resolve} from '../../../models/dependency';
 import {configModelToken} from '../../../models/config/config-model';
 import {createSearchUrl} from '../../../models/views/search';
 import {createDashboardUrl} from '../../../models/views/dashboard';
-import {fire, fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {userModelToken} from '../../../models/user/user-model';
 
 @customElement('gr-hovercard-account-contents')
@@ -251,10 +250,10 @@
       <a
         href=${ifDefined(this.computeOwnerChangesLink())}
         @click=${() => {
-          fireEvent(this, 'link-clicked');
+          fire(this, 'link-clicked', {});
         }}
         @enter=${() => {
-          fireEvent(this, 'link-clicked');
+          fire(this, 'link-clicked', {});
         }}
       >
         Changes
@@ -263,10 +262,10 @@
       <a
         href=${ifDefined(this.computeOwnerDashboardLink())}
         @click=${() => {
-          fireEvent(this, 'link-clicked');
+          fire(this, 'link-clicked', {});
         }}
         @enter=${() => {
-          fireEvent(this, 'link-clicked');
+          fire(this, 'link-clicked', {});
         }}
       >
         Dashboard
@@ -423,7 +422,7 @@
     // accountKey() throws an error if _account_id & email is not found, which
     // we want to check before showing reloading toast
     const _accountKey = accountKey(this.account);
-    fire(this, EventType.SHOW_ALERT, {
+    fire(this, 'show-alert', {
       message: 'Reloading page...',
     });
     const reviewInput: Partial<ReviewInput> = {};
@@ -453,7 +452,7 @@
   private handleRemoveReviewerOrCC() {
     if (!this.change || !(this.account?._account_id || this.account?.email))
       throw new Error('Missing change or account.');
-    fire(this, EventType.SHOW_ALERT, {
+    fire(this, 'show-alert', {
       message: 'Reloading page...',
     });
     this.restApiService
@@ -486,7 +485,7 @@
 
   private handleClickAddToAttentionSet() {
     if (!this.change || !this.account._account_id) return;
-    fire(this, EventType.SHOW_ALERT, {
+    fire(this, 'show-alert', {
       message: 'Reloading page...',
       dismissOnNavigation: true,
     });
@@ -501,7 +500,7 @@
       reason,
       reason_account: this.selfAccount,
     };
-    fireEvent(this, 'attention-set-updated');
+    fire(this, 'attention-set-updated', {});
 
     this.reporting.reportInteraction(
       'attention-hovercard-add',
@@ -510,14 +509,14 @@
     this.restApiService
       .addToAttentionSet(this.change._number, this.account._account_id, reason)
       .then(() => {
-        fireEvent(this, 'hide-alert');
+        fire(this, 'hide-alert', {});
       });
-    fireEvent(this, 'action-taken');
+    fire(this, 'action-taken', {});
   }
 
   private handleClickRemoveFromAttentionSet() {
     if (!this.change || !this.account._account_id) return;
-    fire(this, EventType.SHOW_ALERT, {
+    fire(this, 'show-alert', {
       message: 'Saving attention set update ...',
       dismissOnNavigation: true,
     });
@@ -528,7 +527,7 @@
     const reason = getRemovedByReason(this.selfAccount, this.serverConfig);
     if (this.change.attention_set)
       delete this.change.attention_set[this.account._account_id];
-    fireEvent(this, 'attention-set-updated');
+    fire(this, 'attention-set-updated', {});
 
     this.reporting.reportInteraction(
       'attention-hovercard-remove',
@@ -541,9 +540,9 @@
         reason
       )
       .then(() => {
-        fireEvent(this, 'hide-alert');
+        fire(this, 'hide-alert', {});
       });
-    fireEvent(this, 'action-taken');
+    fire(this, 'action-taken', {});
   }
 
   private reportingDetails() {
@@ -572,4 +571,9 @@
   interface HTMLElementTagNameMap {
     'gr-hovercard-account-contents': GrHovercardAccountContents;
   }
+  interface HTMLElementEventMap {
+    'action-taken': CustomEvent<{}>;
+    'attention-set-updated': CustomEvent<{}>;
+    'link-clicked': CustomEvent<{}>;
+  }
 }
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts
index bd47ec8..7df06f4 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents_test.ts
@@ -26,7 +26,6 @@
   createDetailedLabelInfo,
 } from '../../../test/test-data-generators';
 import {GrButton} from '../gr-button/gr-button';
-import {EventType} from '../../../types/events';
 import {testResolver} from '../../../test/common-test-setup';
 import {userModelToken} from '../../../models/user/user-model';
 
@@ -308,7 +307,7 @@
     const showAlertListener = sinon.spy();
     const hideAlertListener = sinon.spy();
     const updatedListener = sinon.spy();
-    element.addEventListener(EventType.SHOW_ALERT, showAlertListener);
+    element.addEventListener('show-alert', showAlertListener);
     element.addEventListener('hide-alert', hideAlertListener);
     element.addEventListener('attention-set-updated', updatedListener);
 
@@ -359,7 +358,7 @@
     const showAlertListener = sinon.spy();
     const hideAlertListener = sinon.spy();
     const updatedListener = sinon.spy();
-    element.addEventListener(EventType.SHOW_ALERT, showAlertListener);
+    element.addEventListener('show-alert', showAlertListener);
     element.addEventListener('hide-alert', hideAlertListener);
     element.addEventListener('attention-set-updated', updatedListener);
 
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.ts
index eaf6612..76a6573 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-action-context_test.ts
@@ -7,7 +7,6 @@
 import './gr-js-api-interface';
 import {GrPluginActionContext} from './gr-plugin-action-context';
 import {addListenerForTest, waitEventLoop} from '../../../test/test-utils';
-import {EventType} from '../../../types/events';
 import {assert} from '@open-wc/testing';
 import {PluginApi} from '../../../api/plugin';
 import {SinonStub, stub, spy} from 'sinon';
@@ -147,7 +146,7 @@
     } as unknown as RestPluginApi;
     stub(plugin, 'restApi').returns(fakeRestApi);
     const errorStub = stub();
-    addListenerForTest(document, EventType.SHOW_ALERT, errorStub);
+    addListenerForTest(document, 'show-alert', errorStub);
 
     instance.call({}, () => {});
     await waitEventLoop();
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts
index acce236..b2ac2bf 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-plugin-loader_test.ts
@@ -11,7 +11,6 @@
 import {PluginApi} from '../../../api/plugin';
 import {SinonFakeTimers} from 'sinon';
 import {Timestamp} from '../../../api/rest-api';
-import {EventType} from '../../../types/events';
 import {assert} from '@open-wc/testing';
 import {getAppContext} from '../../../services/app-context';
 
@@ -144,7 +143,7 @@
     ];
 
     const alertStub = sinon.stub();
-    addListenerForTest(document, EventType.SHOW_ALERT, alertStub);
+    addListenerForTest(document, 'show-alert', alertStub);
 
     sinon.stub(pluginLoader, 'loadJsPlugin').callsFake(url => {
       pluginLoader.install(
@@ -178,7 +177,7 @@
     ];
 
     const alertStub = sinon.stub();
-    addListenerForTest(document, EventType.SHOW_ALERT, alertStub);
+    addListenerForTest(document, 'show-alert', alertStub);
 
     sinon.stub(pluginLoader, 'loadJsPlugin').callsFake(url => {
       pluginLoader.install(
@@ -217,7 +216,7 @@
     ];
 
     const alertStub = sinon.stub();
-    addListenerForTest(document, EventType.SHOW_ALERT, alertStub);
+    addListenerForTest(document, 'show-alert', alertStub);
 
     sinon.stub(pluginLoader, 'loadJsPlugin').callsFake(url => {
       pluginLoader.install(
@@ -249,7 +248,7 @@
     ];
 
     const alertStub = sinon.stub();
-    addListenerForTest(document, EventType.SHOW_ALERT, alertStub);
+    addListenerForTest(document, 'show-alert', alertStub);
 
     sinon.stub(pluginLoader, 'loadJsPlugin').callsFake(url => {
       pluginLoader.install(() => {}, url === plugins[0] ? '' : 'alpha', url);
diff --git a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts
index 47d722d..02f830d 100644
--- a/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts
+++ b/polygerrit-ui/app/elements/shared/gr-label-info/gr-label-info.ts
@@ -22,7 +22,7 @@
 import {customElement, property} from 'lit/decorators.js';
 import {GrButton} from '../gr-button/gr-button';
 import {
-  canVote,
+  canReviewerVote,
   getApprovalInfo,
   hasNeutralStatus,
   hasVoted,
@@ -143,7 +143,7 @@
       .filter(reviewer => {
         if (this.showAllReviewers) {
           if (isDetailedLabelInfo(labelInfo)) {
-            return canVote(labelInfo, reviewer);
+            return canReviewerVote(labelInfo, reviewer);
           } else {
             // isQuickLabelInfo
             return hasVoted(labelInfo, reviewer);
diff --git a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.ts b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.ts
index e48dcb3..7717683 100644
--- a/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.ts
+++ b/polygerrit-ui/app/elements/shared/gr-linked-chip/gr-linked-chip.ts
@@ -6,7 +6,7 @@
 import '../gr-button/gr-button';
 import '../gr-icon/gr-icon';
 import '../gr-limited-text/gr-limited-text';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, css, html} from 'lit';
 import {customElement, property} from 'lit/decorators.js';
@@ -15,6 +15,11 @@
   interface HTMLElementTagNameMap {
     'gr-linked-chip': GrLinkedChip;
   }
+  interface HTMLElementEventMap {
+    /** Fired when the 'remove' button was clicked. */
+    // prettier-ignore
+    'remove': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-linked-chip')
@@ -101,6 +106,6 @@
 
   private handleRemoveTap(e: Event) {
     e.preventDefault();
-    fireEvent(this, 'remove');
+    fire(this, 'remove', {});
   }
 }
diff --git a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.ts b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.ts
index 7e90c8d..ea45142 100644
--- a/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.ts
+++ b/polygerrit-ui/app/elements/shared/gr-list-view/gr-list-view.ts
@@ -7,7 +7,7 @@
 import '../gr-button/gr-button';
 import '../gr-icon/gr-icon';
 import {encodeURL, getBaseUrl} from '../../../utils/url-util';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {debounce, DelayedTask} from '../../../utils/async-util';
 import {sharedStyles} from '../../../styles/shared-styles';
 import {LitElement, PropertyValues, css, html} from 'lit';
@@ -22,6 +22,9 @@
   interface HTMLElementTagNameMap {
     'gr-list-view': GrListView;
   }
+  interface HTMLElementEventMap {
+    'create-clicked': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-list-view')
@@ -180,7 +183,7 @@
   }
 
   private createNewItem() {
-    fireEvent(this, 'create-clicked');
+    fire(this, 'create-clicked', {});
   }
 
   // private but used in test
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
index 12d7ec2..71a0637 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element.ts
@@ -41,7 +41,7 @@
   hideInContextControl,
 } from '../gr-diff/gr-diff-group';
 import {getLineNumber, getSideByLineEl} from '../gr-diff/gr-diff-utils';
-import {fireAlert, fireEvent} from '../../../utils/event-util';
+import {fireAlert, fire} from '../../../utils/event-util';
 import {assertIsDefined} from '../../../utils/common-util';
 
 const TRAILING_WHITESPACE_PATTERN = /\s+$/;
@@ -201,7 +201,7 @@
 
     const isBinary = !!(this.isImageDiff || this.diff.binary);
 
-    this.fireDiffEvent('render-start');
+    fire(this.diffElement, 'render-start', {});
     // TODO: processor.process() returns a cancelable promise already.
     // Why wrap another one around it?
     this.cancelableRenderPromise = makeCancelable(
@@ -215,7 +215,7 @@
             this.builder.renderImageDiff();
           }
           await this.untilGroupsRendered();
-          this.fireDiffEvent('render-content');
+          fire(this.diffElement, 'render-content', {});
         })
         // Mocha testing does not like uncaught rejections, so we catch
         // the cancels which are expected and should not throw errors in
@@ -243,11 +243,6 @@
     this.replaceGroup(e.detail.contextGroup, e.detail.groups);
   };
 
-  private fireDiffEvent<K extends keyof HTMLElementEventMap>(type: K) {
-    assertIsDefined(this.diffElement, 'diff table');
-    fireEvent(this.diffElement, type);
-  }
-
   // visible for testing
   setupAnnotationLayers() {
     this.rangeLayer = new GrRangedCommentLayer();
@@ -360,12 +355,12 @@
     newGroups: readonly GrDiffGroup[]
   ) {
     if (!this.builder) return;
-    this.fireDiffEvent('render-start');
+    fire(this.diffElement, 'render-start', {});
     this.builder.replaceGroup(contextGroup, newGroups);
     this.groups = this.groups.filter(g => g !== contextGroup);
     this.groups.push(...newGroups);
     this.untilGroupsRendered(newGroups).then(() => {
-      this.fireDiffEvent('render-content');
+      fire(this.diffElement, 'render-content', {});
     });
   }
 
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts
index 0f02d71..9cf9bae 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-builder/gr-diff-builder-element_test.ts
@@ -30,7 +30,6 @@
 import {KeyLocations} from '../gr-diff-processor/gr-diff-processor';
 import {BlameInfo} from '../../../types/common';
 import {fixture, html, assert} from '@open-wc/testing';
-import {EventType} from '../../../types/events';
 
 const DEFAULT_PREFS = createDefaultDiffPrefs();
 
@@ -134,7 +133,7 @@
 
   test('_handlePreferenceError triggers alert and javascript error', () => {
     const errorStub = sinon.stub();
-    diffTable.addEventListener(EventType.SHOW_ALERT, errorStub);
+    diffTable.addEventListener('show-alert', errorStub);
     assert.throws(() => element.handlePreferenceError('tab size'));
     assert.equal(
       errorStub.lastCall.args[0].detail.message,
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts
index 0f4ab2e..34e9d5a 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff.ts
@@ -45,7 +45,7 @@
   Side,
 } from '../../../constants/constants';
 import {KeyLocations} from '../gr-diff-processor/gr-diff-processor';
-import {fire, fireAlert, fireEvent} from '../../../utils/event-util';
+import {fire, fireAlert} from '../../../utils/event-util';
 import {MovedLinkClickedEvent, ValueChangedEvent} from '../../../types/events';
 import {getContentEditableRange} from '../../../utils/safari-selection-util';
 import {AbortStop} from '../../../api/core';
@@ -1273,10 +1273,10 @@
     threadEl: GrDiffThreadElement
   ) {
     hoverEl.addEventListener('mouseenter', () => {
-      fireEvent(threadEl, 'comment-thread-mouseenter');
+      fire(threadEl, 'comment-thread-mouseenter', {});
     });
     hoverEl.addEventListener('mouseleave', () => {
-      fireEvent(threadEl, 'comment-thread-mouseleave');
+      fire(threadEl, 'comment-thread-mouseleave', {});
     });
   }
 
@@ -1561,10 +1561,10 @@
     // (client), although it was not actually rendered. Clients need to know
     // when it is safe to perform operations like cursor moves, for example,
     // and if changing an input actually requires a reload of the diff table.
-    // Since `fireEvent` is synchronous it allows clients to be aware when an
+    // Since `fire` is synchronous it allows clients to be aware when an
     // async render is needed and that they can wait for a further `render`
     // event to actually take further action.
-    fireEvent(this, 'render-required');
+    fire(this, 'render-required', {});
     this.renderDiffTableTask = debounceP(
       this.renderDiffTableTask,
       async () => await this.renderDiffTable()
@@ -1579,7 +1579,7 @@
   async renderDiffTable() {
     this.unobserveNodes();
     if (!this.diff || !this.prefs) {
-      fireEvent(this, 'render');
+      fire(this, 'render', {});
       return;
     }
     if (
@@ -1589,7 +1589,7 @@
       this.safetyBypass === null
     ) {
       this.showWarning = true;
-      fireEvent(this, 'render');
+      fire(this, 'render', {});
       return;
     }
 
@@ -1633,7 +1633,7 @@
     this.observeNodes();
     // We are just converting 'render-content' into 'render' here. Maybe we
     // should retire the 'render' event in favor of 'render-content'?
-    fireEvent(this, 'render');
+    fire(this, 'render', {});
   }
 
   private observeNodes() {
@@ -1826,6 +1826,9 @@
     'gr-diff': GrDiff;
   }
   interface HTMLElementEventMap {
+    'comment-thread-mouseenter': CustomEvent<{}>;
+    'comment-thread-mouseleave': CustomEvent<{}>;
     'loading-changed': ValueChangedEvent<boolean>;
+    'render-required': CustomEvent<{}>;
   }
 }
diff --git a/polygerrit-ui/app/embed/diff/gr-selection-action-box/gr-selection-action-box.ts b/polygerrit-ui/app/embed/diff/gr-selection-action-box/gr-selection-action-box.ts
index cb08e55..68aa3b4 100644
--- a/polygerrit-ui/app/embed/diff/gr-selection-action-box/gr-selection-action-box.ts
+++ b/polygerrit-ui/app/embed/diff/gr-selection-action-box/gr-selection-action-box.ts
@@ -5,7 +5,7 @@
  */
 import '../../../elements/shared/gr-tooltip/gr-tooltip';
 import {GrTooltip} from '../../../elements/shared/gr-tooltip/gr-tooltip';
-import {fireEvent} from '../../../utils/event-util';
+import {fire} from '../../../utils/event-util';
 import {css, html, LitElement} from 'lit';
 import {customElement, property, query, state} from 'lit/decorators.js';
 import {sharedStyles} from '../../../styles/shared-styles';
@@ -14,16 +14,14 @@
   interface HTMLElementTagNameMap {
     'gr-selection-action-box': GrSelectionActionBox;
   }
+  interface HTMLElementEventMap {
+    /** Fired when the comment creation action was taken (click). */
+    'create-comment-requested': CustomEvent<{}>;
+  }
 }
 
 @customElement('gr-selection-action-box')
 export class GrSelectionActionBox extends LitElement {
-  /**
-   * Fired when the comment creation action was taken (click).
-   *
-   * @event create-comment-requested
-   */
-
   @query('#tooltip')
   tooltip?: GrTooltip;
 
@@ -133,6 +131,6 @@
     } // 0 = main button
     e.preventDefault();
     e.stopPropagation();
-    fireEvent(this, 'create-comment-requested');
+    fire(this, 'create-comment-requested', {});
   }
 }
diff --git a/polygerrit-ui/app/mixins/hovercard-mixin/hovercard-mixin.ts b/polygerrit-ui/app/mixins/hovercard-mixin/hovercard-mixin.ts
index b383fd7..4f79e4c 100644
--- a/polygerrit-ui/app/mixins/hovercard-mixin/hovercard-mixin.ts
+++ b/polygerrit-ui/app/mixins/hovercard-mixin/hovercard-mixin.ts
@@ -6,7 +6,7 @@
 import {Constructor} from '../../utils/common-util';
 import {LitElement, PropertyValues} from 'lit';
 import {property, query} from 'lit/decorators.js';
-import {EventType, ShowAlertEventDetail} from '../../types/events';
+import {ShowAlertEventDetail} from '../../types/events';
 import {debounce, DelayedTask} from '../../utils/async-util';
 import {hovercardStyles} from '../../styles/gr-hovercard-styles';
 import {sharedStyles} from '../../styles/shared-styles';
@@ -303,7 +303,7 @@
     dispatchEventThroughTarget(eventName: string): void;
 
     dispatchEventThroughTarget(
-      eventName: EventType.SHOW_ALERT,
+      eventName: 'show-alert',
       detail: ShowAlertEventDetail
     ): void;
 
diff --git a/polygerrit-ui/app/models/checks/checks-model.ts b/polygerrit-ui/app/models/checks/checks-model.ts
index 4715abf..2aa4aa4 100644
--- a/polygerrit-ui/app/models/checks/checks-model.ts
+++ b/polygerrit-ui/app/models/checks/checks-model.ts
@@ -51,7 +51,7 @@
 import {getShaByPatchNum} from '../../utils/patch-set-util';
 import {ReportingService} from '../../services/gr-reporting/gr-reporting';
 import {Execution, Interaction, Timing} from '../../constants/reporting';
-import {fireAlert, fireEvent} from '../../utils/event-util';
+import {fireAlert, fire} from '../../utils/event-util';
 import {Model} from '../model';
 import {define} from '../dependency';
 import {
@@ -716,7 +716,7 @@
         if (result.errorMessage || result.message) {
           fireAlert(document, `${result.message ?? result.errorMessage}`);
         } else {
-          fireEvent(document, 'hide-alert');
+          fire(document, 'hide-alert', {});
         }
         if (result.shouldReload) {
           this.reloadForCheck(run?.checkName);
diff --git a/polygerrit-ui/app/models/comments/comments-model.ts b/polygerrit-ui/app/models/comments/comments-model.ts
index 1fdf342..0e78274 100644
--- a/polygerrit-ui/app/models/comments/comments-model.ts
+++ b/polygerrit-ui/app/models/comments/comments-model.ts
@@ -31,7 +31,7 @@
 import {select} from '../../utils/observable-util';
 import {define} from '../dependency';
 import {combineLatest, forkJoin, from, Observable, of} from 'rxjs';
-import {fire, fireAlert, fireEvent} from '../../utils/event-util';
+import {fire, fireAlert} from '../../utils/event-util';
 import {CURRENT} from '../../utils/patch-set-util';
 import {RestApiService} from '../../services/gr-rest-api/gr-rest-api';
 import {ChangeModel} from '../change/change-model';
@@ -43,7 +43,6 @@
 import {Model} from '../model';
 import {Deduping} from '../../api/reporting';
 import {extractMentionedUsers, getUserId} from '../../utils/account-util';
-import {EventType} from '../../types/events';
 import {SpecialFilePath} from '../../constants/constants';
 import {AccountsModel} from '../accounts-model/accounts-model';
 import {
@@ -643,7 +642,7 @@
     this.modifyState(s => deleteDraft(s, draft));
     // We don't store empty discarded drafts and don't need an UNDO then.
     if (draft.message?.trim()) {
-      fire(document, EventType.SHOW_ALERT, {
+      fire(document, 'show-alert', {
         message: 'Draft Discarded',
         action: 'Undo',
         callback: () => this.restoreDraft(draft.id),
@@ -693,7 +692,7 @@
 
   private updateRequestToast(requestFailed?: boolean) {
     if (this.numPendingDraftRequests === 0 && !requestFailed) {
-      fireEvent(document, 'hide-alert');
+      fire(document, 'hide-alert', {});
       return;
     }
     const message = getSavingMessage(
diff --git a/polygerrit-ui/app/types/events.ts b/polygerrit-ui/app/types/events.ts
index c28aade..8b02fdf 100644
--- a/polygerrit-ui/app/types/events.ts
+++ b/polygerrit-ui/app/types/events.ts
@@ -11,51 +11,36 @@
 import {DropdownLink} from '../elements/shared/gr-dropdown/gr-dropdown';
 import {AutocompleteCommitEvent} from '../elements/shared/gr-autocomplete/gr-autocomplete';
 
-export enum EventType {
-  BIND_VALUE_CHANGED = 'bind-value-changed',
-  CHANGE = 'change',
-  CHANGED = 'changed',
-  COMMIT = 'commit',
-  DIALOG_CHANGE = 'dialog-change',
-  DROP = 'drop',
-  EDITABLE_CONTENT_SAVE = 'editable-content-save',
-  GR_RPC_LOG = 'gr-rpc-log',
-  IRON_ANNOUNCE = 'iron-announce',
-  KEYDOWN = 'keydown',
-  KEYPRESS = 'keypress',
-  LOCATION_CHANGE = 'location-change',
-  MOVED_LINK_CLICKED = 'moved-link-clicked',
-  NETWORK_ERROR = 'network-error',
-  OPEN_FIX_PREVIEW = 'open-fix-preview',
-  PAGE_ERROR = 'page-error',
-  RELOAD = 'reload',
-  REPLY = 'reply',
-  SERVER_ERROR = 'server-error',
-  SHORTCUT_TRIGGERERD = 'shortcut-triggered',
-  SHOW_ALERT = 'show-alert',
-  SHOW_ERROR = 'show-error',
-  SHOW_TAB = 'show-tab',
-  SHOW_SECONDARY_TAB = 'show-secondary-tab',
-  TAP_ITEM = 'tap-item',
-  TITLE_CHANGE = 'title-change',
-}
-
+// TODO: Local events that are only fired by one component should also be
+// declared and documented in that component. Don't collect ALL the events here.
+// 'show-alert' for example is fine to keep, because it is fired all over the
+// place. But 'line-cursor-moved-in' is only fired by <gr-diff-cursor>, so let's
+// move it there.
 declare global {
   interface HTMLElementEventMap {
     'add-reviewer': AddReviewerEvent;
     'bind-value-changed': BindValueChangeEvent;
-    /* prettier-ignore */
+    /** Fired when a 'cancel' button in a dialog was pressed. */
+    // prettier-ignore
+    'cancel': CustomEvent<{}>;
+    // prettier-ignore
     'change': ChangeEvent;
-    /* prettier-ignore */
+    // prettier-ignore
     'changed': ChangedEvent;
-    /* prettier-ignore */
+    // prettier-ignore
+    'close': CustomEvent<{}>;
+    // prettier-ignore
     'commit': AutocompleteCommitEvent;
+    /** Fired when a 'confirm' button in a dialog was pressed. */
+    // prettier-ignore
+    'confirm': CustomEvent<{}>;
     'dialog-change': DialogChangeEvent;
-    /* prettier-ignore */
+    // prettier-ignore
     'drop': DropEvent;
-    'editable-content-save': EditableContentSaveEvent;
+    'hide-alert': CustomEvent<{}>;
     'location-change': LocationChangeEvent;
     'iron-announce': IronAnnounceEvent;
+    'iron-resize': CustomEvent<{}>;
     'line-mouse-enter': LineNumberEvent;
     'line-mouse-leave': LineNumberEvent;
     'line-cursor-moved-in': LineNumberEvent;
@@ -63,7 +48,7 @@
     'moved-link-clicked': MovedLinkClickedEvent;
     'open-fix-preview': OpenFixPreviewEvent;
     'reply-to-comment': ReplyToCommentEvent;
-    /* prettier-ignore */
+    // prettier-ignore
     'reload': ReloadEvent;
     'remove-reviewer': RemoveReviewerEvent;
     'show-alert': ShowAlertEvent;
@@ -80,7 +65,7 @@
     'gr-rpc-log': RpcLogEvent;
     'network-error': NetworkErrorEvent;
     'page-error': PageErrorEvent;
-    /* prettier-ignore */
+    // prettier-ignore
     'reload': ReloadEvent;
     'server-error': ServerErrorEvent;
     'show-alert': ShowAlertEvent;
diff --git a/polygerrit-ui/app/utils/event-util.ts b/polygerrit-ui/app/utils/event-util.ts
index d45ef55..3704557 100644
--- a/polygerrit-ui/app/utils/event-util.ts
+++ b/polygerrit-ui/app/utils/event-util.ts
@@ -6,65 +6,34 @@
 import {FetchRequest} from '../types/types';
 import {
   DialogChangeEventDetail,
-  EventType,
   SwitchTabEventDetail,
   TabState,
 } from '../types/events';
 
-export function fireEvent(target: EventTarget, type: string) {
-  target.dispatchEvent(
-    new CustomEvent(type, {
-      composed: true,
-      bubbles: true,
-    })
-  );
-}
-
-export function fireEventNoBubble(target: EventTarget, type: string) {
-  target.dispatchEvent(
-    new CustomEvent(type, {
-      composed: true,
-      bubbles: false,
-    })
-  );
-}
-
-export function fireEventNoBubbleNoCompose(target: EventTarget, type: string) {
-  target.dispatchEvent(
-    new CustomEvent(type, {
-      composed: false,
-      bubbles: false,
-    })
-  );
-}
-
 export type HTMLElementEventDetailType<K extends keyof HTMLElementEventMap> =
-  HTMLElementEventMap[K] extends CustomEvent<infer DT>
-    ? unknown extends DT
-      ? never
-      : DT
-    : never;
+  HTMLElementEventMap[K] extends CustomEvent<infer DT> ? DT : never;
 
 type DocumentEventDetailType<K extends keyof DocumentEventMap> =
-  DocumentEventMap[K] extends CustomEvent<infer DT>
-    ? unknown extends DT
-      ? never
-      : DT
-    : never;
+  DocumentEventMap[K] extends CustomEvent<infer DT> ? DT : never;
 
 export function fire<K extends keyof DocumentEventMap>(
-  target: Document,
+  target: Document | undefined,
   type: K,
   detail: DocumentEventDetailType<K>
 ): void;
 
 export function fire<K extends keyof HTMLElementEventMap>(
-  target: EventTarget,
+  target: EventTarget | undefined,
   type: K,
   detail: HTMLElementEventDetailType<K>
 ): void;
 
-export function fire<T>(target: EventTarget, type: string, detail: T) {
+export function fire<T>(
+  target: EventTarget | undefined,
+  type: string,
+  detail: T
+) {
+  if (!target) return;
   target.dispatchEvent(
     new CustomEvent<T>(type, {
       detail,
@@ -103,31 +72,31 @@
 }
 
 export function fireAlert(target: EventTarget, message: string) {
-  fire(target, EventType.SHOW_ALERT, {message, showDismiss: true});
+  fire(target, 'show-alert', {message, showDismiss: true});
 }
 
 export function fireError(target: EventTarget, message: string) {
-  fire(target, EventType.SHOW_ERROR, {message});
+  fire(target, 'show-error', {message});
 }
 
 export function firePageError(response?: Response | null) {
   if (response === null) response = undefined;
-  fire(document, EventType.PAGE_ERROR, {response});
+  fire(document, 'page-error', {response});
 }
 
 export function fireServerError(response: Response, request?: FetchRequest) {
-  fire(document, EventType.SERVER_ERROR, {
+  fire(document, 'server-error', {
     response,
     request,
   });
 }
 
 export function fireNetworkError(error: Error) {
-  fire(document, EventType.NETWORK_ERROR, {error});
+  fire(document, 'network-error', {error});
 }
 
 export function fireTitleChange(target: EventTarget, title: string) {
-  fire(target, EventType.TITLE_CHANGE, {title});
+  fire(target, 'title-change', {title});
 }
 
 // TODO(milutin) - remove once new gr-dialog will do it out of the box
@@ -136,11 +105,11 @@
   target: EventTarget,
   detail: DialogChangeEventDetail
 ) {
-  fire(target, EventType.DIALOG_CHANGE, detail);
+  fire(target, 'dialog-change', detail);
 }
 
 export function fireIronAnnounce(target: EventTarget, text: string) {
-  fire(target, EventType.IRON_ANNOUNCE, {text});
+  fire(target, 'iron-announce', {text});
 }
 
 export function fireShowTab(
@@ -150,11 +119,11 @@
   tabState?: TabState
 ) {
   const detail: SwitchTabEventDetail = {tab, scrollIntoView, tabState};
-  fire(target, EventType.SHOW_TAB, detail);
+  fire(target, 'show-tab', detail);
 }
 
 export function fireReload(target: EventTarget, clearPatchset?: boolean) {
-  fire(target, EventType.RELOAD, {clearPatchset: !!clearPatchset});
+  fire(target, 'reload', {clearPatchset: !!clearPatchset});
 }
 
 export function waitForEventOnce<K extends keyof HTMLElementEventMap>(
diff --git a/polygerrit-ui/app/utils/label-util.ts b/polygerrit-ui/app/utils/label-util.ts
index aaa35a4..8929e9c 100644
--- a/polygerrit-ui/app/utils/label-util.ts
+++ b/polygerrit-ui/app/utils/label-util.ts
@@ -153,7 +153,14 @@
   return false;
 }
 
-export function canVote(label: DetailedLabelInfo, account: AccountInfo) {
+// This method is checking labels.all from change detail,
+// that shows only permitted voting for reviewers or CC.
+// It doesn't have permitted votes for owner. You
+// can see permitted labels for logged in user in change.permitted_labels
+export function canReviewerVote(
+  label: DetailedLabelInfo,
+  account: AccountInfo
+) {
   const approvalInfo = getApprovalInfo(label, account);
   if (!approvalInfo) return false;
   if (approvalInfo.permitted_voting_range) {