diff --git a/src/components/buttons/ha-call-service-button.js b/src/components/buttons/ha-call-service-button.js
deleted file mode 100644
index aa53eec5ac..0000000000
--- a/src/components/buttons/ha-call-service-button.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-/* eslint-plugin-disable lit */
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box";
-import { EventsMixin } from "../../mixins/events-mixin";
-import "./ha-progress-button";
-
-/*
- * @appliesMixin EventsMixin
- */
-class HaCallServiceButton extends EventsMixin(PolymerElement) {
- static get template() {
- return html`
-
- `;
- }
-
- static get properties() {
- return {
- hass: {
- type: Object,
- },
-
- progress: {
- type: Boolean,
- value: false,
- },
-
- domain: {
- type: String,
- },
-
- service: {
- type: String,
- },
-
- serviceData: {
- type: Object,
- value: {},
- },
-
- confirmation: {
- type: String,
- },
-
- disabled: {
- type: Boolean,
- },
- };
- }
-
- callService() {
- this.progress = true;
- // eslint-disable-next-line @typescript-eslint/no-this-alias
- const el = this;
- const eventData = {
- domain: this.domain,
- service: this.service,
- serviceData: this.serviceData,
- };
-
- this.hass
- .callService(this.domain, this.service, this.serviceData)
- .then(
- () => {
- el.progress = false;
- el.$.progress.actionSuccess();
- eventData.success = true;
- },
- () => {
- el.progress = false;
- el.$.progress.actionError();
- eventData.success = false;
- }
- )
- .then(() => {
- el.fire("hass-service-called", eventData);
- });
- }
-
- buttonTapped() {
- if (this.confirmation) {
- showConfirmationDialog(this, {
- text: this.confirmation,
- confirm: () => this.callService(),
- });
- } else {
- this.callService();
- }
- }
-}
-
-customElements.define("ha-call-service-button", HaCallServiceButton);
diff --git a/src/components/buttons/ha-call-service-button.ts b/src/components/buttons/ha-call-service-button.ts
new file mode 100644
index 0000000000..3cea93de0d
--- /dev/null
+++ b/src/components/buttons/ha-call-service-button.ts
@@ -0,0 +1,92 @@
+import { LitElement, TemplateResult, html } from "lit";
+import { customElement, property } from "lit/decorators";
+import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box";
+import "./ha-progress-button";
+import { HomeAssistant } from "../../types";
+import { fireEvent } from "../../common/dom/fire_event";
+
+@customElement("ha-call-service-button")
+class HaCallServiceButton extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property({ type: Boolean }) public disabled = false;
+
+ @property({ type: Boolean }) public progress = false;
+
+ @property() public domain!: string;
+
+ @property() public service!: string;
+
+ @property({ type: Object }) public serviceData = {};
+
+ @property() public confirmation?;
+
+ public render(): TemplateResult {
+ return html`
+
+
+ `;
+ }
+
+ private async _callService() {
+ this.progress = true;
+ const eventData = {
+ domain: this.domain,
+ service: this.service,
+ serviceData: this.serviceData,
+ success: false,
+ };
+
+ const progressElement =
+ this.shadowRoot!.querySelector("ha-progress-button")!;
+
+ try {
+ await this.hass.callService(this.domain, this.service, this.serviceData);
+ this.progress = false;
+ progressElement.actionSuccess();
+ eventData.success = true;
+ } catch (e) {
+ this.progress = false;
+ progressElement.actionError();
+ eventData.success = false;
+ return;
+ } finally {
+ fireEvent(this, "hass-service-called", eventData);
+ }
+ }
+
+ private _buttonTapped() {
+ if (this.confirmation) {
+ showConfirmationDialog(this, {
+ text: this.confirmation,
+ confirm: () => this._callService(),
+ });
+ } else {
+ this._callService();
+ }
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ha-call-service-button": HaCallServiceButton;
+ }
+}
+
+declare global {
+ // for fire event
+ interface HASSDomEvents {
+ "hass-service-called": {
+ domain: string;
+ service: string;
+ serviceData: object;
+ success: boolean;
+ };
+ }
+}