diff --git a/src/components/entity/ha-entity-toggle.ts b/src/components/entity/ha-entity-toggle.ts index 2b0c40c3c5..2818cb5ac0 100644 --- a/src/components/entity/ha-entity-toggle.ts +++ b/src/components/entity/ha-entity-toggle.ts @@ -14,6 +14,7 @@ import { } from "lit-element"; import { HomeAssistant } from "../../types"; import { HassEntity } from "home-assistant-js-websocket"; +import { forwardHaptic } from "../../util/haptics"; const isOn = (stateObj?: HassEntity) => stateObj !== undefined && !STATES_OFF.includes(stateObj.state); @@ -89,6 +90,7 @@ class HaEntityToggle extends LitElement { if (!this.hass || !this.stateObj) { return; } + forwardHaptic(this, "light"); const stateDomain = computeStateDomain(this.stateObj); let serviceDomain; let service; diff --git a/src/layouts/app/connection-mixin.js b/src/layouts/app/connection-mixin.js index 6eb72d47b4..94bf192926 100644 --- a/src/layouts/app/connection-mixin.js +++ b/src/layouts/app/connection-mixin.js @@ -16,6 +16,7 @@ import { getLocalLanguage } from "../../util/hass-translation"; import { fetchWithAuth } from "../../util/fetch-with-auth"; import hassCallApi from "../../util/hass-call-api"; import { subscribePanels } from "../../data/ws-panels"; +import { forwardHaptic } from "../../util/haptics"; export default (superClass) => class extends EventsMixin(LocalizeMixin(superClass)) { @@ -75,6 +76,7 @@ export default (superClass) => err ); } + forwardHaptic(this, "error"); const message = this.hass.localize( "ui.notification_toast.service_call_failed", diff --git a/src/panels/lovelace/components/hui-entities-toggle.ts b/src/panels/lovelace/components/hui-entities-toggle.ts index 0c64f794ab..88927f1535 100644 --- a/src/panels/lovelace/components/hui-entities-toggle.ts +++ b/src/panels/lovelace/components/hui-entities-toggle.ts @@ -13,6 +13,7 @@ import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-tog import { DOMAINS_TOGGLE } from "../../../common/const"; import { turnOnOffEntities } from "../common/entity/turn-on-off-entities"; import { HomeAssistant } from "../../../types"; +import { forwardHaptic } from "../../../util/haptics"; @customElement("hui-entities-toggle") class HuiEntitiesToggle extends LitElement { @@ -65,6 +66,7 @@ class HuiEntitiesToggle extends LitElement { } private _callService(ev: MouseEvent): void { + forwardHaptic(this, "light"); const turnOn = (ev.target as PaperToggleButtonElement).checked; turnOnOffEntities(this.hass!, this._toggleEntities!, turnOn!); } diff --git a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts index 22564ae094..c068fe3179 100644 --- a/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-input-select-entity-row.ts @@ -22,6 +22,7 @@ import { HomeAssistant } from "../../../types"; import { EntityRow, EntityConfig } from "./types"; import { setOption } from "../../../data/input-select"; import { hasConfigOrEntityChanged } from "../common/has-changed"; +import { forwardHaptic } from "../../../util/haptics"; @customElement("hui-input-select-entity-row") class HuiInputSelectEntityRow extends LitElement implements EntityRow { @@ -97,6 +98,7 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow { } private _selectedChanged(ev): void { + forwardHaptic(this, "light"); // Selected Option will transition to '' before transitioning to new value const stateObj = this.hass!.states[this._config!.entity]; if ( diff --git a/src/util/haptics.ts b/src/util/haptics.ts new file mode 100644 index 0000000000..0df8c9c712 --- /dev/null +++ b/src/util/haptics.ts @@ -0,0 +1,28 @@ +/** + * Utility function that enables haptic feedback + */ + +import { fireEvent } from "../common/dom/fire_event"; + +// Allowed types are from iOS HIG. +// https://developer.apple.com/design/human-interface-guidelines/ios/user-interaction/feedback/#haptics +// Implementors on platforms other than iOS should attempt to match the patterns (shown in HIG) as closely as possible. +export type HapticType = + | "success" + | "warning" + | "failure" + | "light" + | "medium" + | "heavy" + | "selection"; + +declare global { + // for fire event + interface HASSDomEvents { + haptic: HapticType; + } +} + +export const forwardHaptic = (el: HTMLElement, hapticType: HapticType) => { + fireEvent(el, "haptic", hapticType); +};