diff --git a/gallery/src/pages/components/ha-control-slider.ts b/gallery/src/pages/components/ha-control-slider.ts index 5faf01a1fc5d..efc61bb46146 100644 --- a/gallery/src/pages/components/ha-control-slider.ts +++ b/gallery/src/pages/components/ha-control-slider.ts @@ -9,6 +9,7 @@ const sliders: { id: string; label: string; mode?: "start" | "end" | "cursor"; + unit?: string; class?: string; }[] = [ { @@ -31,18 +32,21 @@ const sliders: { label: "Slider (start mode) and custom style", mode: "start", class: "custom", + unit: "mm", }, { id: "slider-end-custom", label: "Slider (end mode) and custom style", mode: "end", class: "custom", + unit: "mm", }, { id: "slider-cursor-custom", label: "Slider (cursor mode) and custom style", mode: "cursor", class: "custom", + unit: "mm", }, ]; @@ -93,6 +97,7 @@ export class DemoHaBarSlider extends LitElement { @value-changed=${this.handleValueChanged} @slider-moved=${this.handleSliderMoved} aria-labelledby=${id} + .tooltipUnit=${config.unit} > @@ -114,6 +119,7 @@ export class DemoHaBarSlider extends LitElement { @value-changed=${this.handleValueChanged} @slider-moved=${this.handleSliderMoved} aria-label=${label} + .tooltipUnit=${config.unit} > `; diff --git a/src/common/translations/blank_before_unit.ts b/src/common/translations/blank_before_unit.ts new file mode 100644 index 000000000000..34fe8ab2d562 --- /dev/null +++ b/src/common/translations/blank_before_unit.ts @@ -0,0 +1,15 @@ +import { FrontendLocaleData } from "../../data/translation"; +import { blankBeforePercent } from "./blank_before_percent"; + +export const blankBeforeUnit = ( + unit: string, + localeOptions?: FrontendLocaleData +): string => { + if (unit === "°") { + return ""; + } + if (localeOptions && unit === "%") { + return blankBeforePercent(localeOptions); + } + return " "; +}; diff --git a/src/components/ha-control-slider.ts b/src/components/ha-control-slider.ts index d323bf0a5514..ea418d4f86e7 100644 --- a/src/components/ha-control-slider.ts +++ b/src/components/ha-control-slider.ts @@ -4,13 +4,17 @@ import { CSSResultGroup, html, LitElement, + nothing, PropertyValues, TemplateResult, } from "lit"; -import { customElement, property, query } from "lit/decorators"; +import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { styleMap } from "lit/directives/style-map"; import { fireEvent } from "../common/dom/fire_event"; +import { FrontendLocaleData } from "../data/translation"; +import { formatNumber } from "../common/number/format_number"; +import { blankBeforeUnit } from "../common/translations/blank_before_unit"; declare global { interface HASSDomEvents { @@ -29,13 +33,21 @@ const A11Y_KEY_CODES = new Set([ "End", ]); +type TooltipPosition = "top" | "bottom" | "left" | "right"; + +type TooltipMode = "never" | "always" | "interaction"; + +type SliderMode = "start" | "end" | "cursor"; + @customElement("ha-control-slider") export class HaControlSlider extends LitElement { + @property({ attribute: false }) public locale?: FrontendLocaleData; + @property({ type: Boolean, reflect: true }) public disabled = false; @property() - public mode?: "start" | "end" | "cursor" = "start"; + public mode?: SliderMode = "start"; @property({ type: Boolean, reflect: true }) public vertical = false; @@ -46,6 +58,15 @@ export class HaControlSlider extends LitElement { @property({ type: Boolean, attribute: "inverted" }) public inverted = false; + @property({ attribute: "tooltip-position" }) + public tooltipPosition?: TooltipPosition; + + @property({ attribute: "tooltip-unit" }) + public tooltipUnit?: string; + + @property({ attribute: "tooltip-mode" }) + public tooltipMode: TooltipMode = "interaction"; + @property({ type: Number }) public value?: number; @@ -58,11 +79,14 @@ export class HaControlSlider extends LitElement { @property({ type: Number }) public max = 100; - private _mc?: HammerManager; - - @property({ type: Boolean, reflect: true }) + @state() public pressed = false; + @state() + public tooltipVisible = false; + + private _mc?: HammerManager; + valueToPercentage(value: number) { const percentage = (this.boundedValue(value) - this.min) / (this.max - this.min); @@ -98,6 +122,7 @@ export class HaControlSlider extends LitElement { if (changedProps.has("value")) { const valuenow = this.steppedValue(this.value ?? 0); this.setAttribute("aria-valuenow", valuenow.toString()); + this.setAttribute("aria-valuetext", this._formatValue(valuenow)); } if (changedProps.has("min")) { this.setAttribute("aria-valuemin", this.min.toString()); @@ -143,11 +168,13 @@ export class HaControlSlider extends LitElement { this._mc.on("panstart", () => { if (this.disabled) return; this.pressed = true; + this._showTooltip(); savedValue = this.value; }); this._mc.on("pancancel", () => { if (this.disabled) return; this.pressed = false; + this._hideTooltip(); this.value = savedValue; }); this._mc.on("panmove", (e) => { @@ -160,6 +187,7 @@ export class HaControlSlider extends LitElement { this._mc.on("panend", (e) => { if (this.disabled) return; this.pressed = false; + this._hideTooltip(); const percentage = this._getPercentageFromEvent(e); this.value = this.steppedValue(this.percentageToValue(percentage)); fireEvent(this, "slider-moved", { value: undefined }); @@ -191,6 +219,21 @@ export class HaControlSlider extends LitElement { return Math.max(this.step, (this.max - this.min) / 10); } + _showTooltip() { + if (this._tooltipTimeout != null) window.clearTimeout(this._tooltipTimeout); + this.tooltipVisible = true; + } + + _hideTooltip(delay?: number) { + if (!delay) { + this.tooltipVisible = false; + return; + } + this._tooltipTimeout = window.setTimeout(() => { + this.tooltipVisible = false; + }, delay); + } + _handleKeyDown(e: KeyboardEvent) { if (!A11Y_KEY_CODES.has(e.code)) return; e.preventDefault(); @@ -220,12 +263,16 @@ export class HaControlSlider extends LitElement { this.value = this.max; break; } + this._showTooltip(); fireEvent(this, "slider-moved", { value: this.value }); } + private _tooltipTimeout?: number; + _handleKeyUp(e: KeyboardEvent) { if (!A11Y_KEY_CODES.has(e.code)) return; e.preventDefault(); + this._hideTooltip(500); fireEvent(this, "value-changed", { value: this.value }); } @@ -242,36 +289,76 @@ export class HaControlSlider extends LitElement { return Math.max(Math.min(1, (x - offset) / total), 0); }; + private _formatValue(value: number) { + const formattedValue = formatNumber(value, this.locale); + + const formattedUnit = this.tooltipUnit + ? `${blankBeforeUnit(this.tooltipUnit, this.locale)}${this.tooltipUnit}` + : ""; + + return `${formattedValue}${formattedUnit}`; + } + + private _renderTooltip() { + if (this.tooltipMode === "never") return nothing; + + const position = this.tooltipPosition ?? (this.vertical ? "left" : "top"); + + const visible = + this.tooltipMode === "always" || + (this.tooltipVisible && this.tooltipMode === "interaction"); + + const value = this.steppedValue(this.value ?? 0); + + return html` + + `; + } + protected render(): TemplateResult { return html`
-
- - ${this.mode === "cursor" - ? this.value != null - ? html` +
+
+ + ${this.mode === "cursor" + ? this.value != null + ? html` +
+ ` + : null + : html`
- ` - : null - : html` -
- `} + `} +
+ ${this._renderTooltip()}
`; } @@ -285,6 +372,7 @@ export class HaControlSlider extends LitElement { --control-slider-background-opacity: 0.2; --control-slider-thickness: 40px; --control-slider-border-radius: 10px; + --control-slider-tooltip-font-size: 14px; height: var(--control-slider-thickness); width: 100%; border-radius: var(--control-slider-border-radius); @@ -298,6 +386,88 @@ export class HaControlSlider extends LitElement { width: var(--control-slider-thickness); height: 100%; } + .container { + position: relative; + height: 100%; + width: 100%; + --handle-size: 4px; + --handle-margin: calc(var(--control-slider-thickness) / 8); + } + .tooltip { + user-select: none; + position: absolute; + background-color: var(--clear-background-color); + color: var(--primary-text-color); + font-size: var(--control-slider-tooltip-font-size); + border-radius: 0.8em; + padding: 0.2em 0.4em; + opacity: 0; + white-space: nowrap; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + transition: + opacity 180ms ease-in-out, + left 180ms ease-in-out, + bottom 180ms ease-in-out; + --handle-spacing: calc(2 * var(--handle-margin) + var(--handle-size)); + --slider-tooltip-margin: -4px; + --slider-tooltip-range: 100%; + --slider-tooltip-offset: 0px; + --slider-tooltip-position: calc( + min( + max( + var(--value) * var(--slider-tooltip-range) + + var(--slider-tooltip-offset), + 0% + ), + 100% + ) + ); + } + .tooltip.start { + --slider-tooltip-offset: calc(-0.5 * (var(--handle-spacing))); + } + .tooltip.end { + --slider-tooltip-offset: calc(0.5 * (var(--handle-spacing))); + } + .tooltip.cursor { + --slider-tooltip-range: calc(100% - var(--handle-spacing)); + --slider-tooltip-offset: calc(0.5 * (var(--handle-spacing))); + } + .tooltip.show-handle { + --slider-tooltip-range: calc(100% - var(--handle-spacing)); + --slider-tooltip-offset: calc(0.5 * (var(--handle-spacing))); + } + .tooltip.visible { + opacity: 1; + } + .tooltip.top { + transform: translate3d(-50%, -100%, 0); + top: var(--slider-tooltip-margin); + left: 50%; + } + .tooltip.bottom { + transform: translate3d(-50%, 100%, 0); + bottom: var(--slider-tooltip-margin); + left: 50%; + } + .tooltip.left { + transform: translate3d(-100%, 50%, 0); + bottom: 50%; + left: var(--slider-tooltip-margin); + } + .tooltip.right { + transform: translate3d(100%, 50%, 0); + bottom: 50%; + right: var(--slider-tooltip-margin); + } + :host(:not([vertical])) .tooltip.top, + :host(:not([vertical])) .tooltip.bottom { + left: var(--slider-tooltip-position); + } + :host([vertical]) .tooltip.right, + :host([vertical]) .tooltip.left { + bottom: var(--slider-tooltip-position); + } .slider { position: relative; height: 100%; @@ -328,8 +498,6 @@ export class HaControlSlider extends LitElement { } .slider .slider-track-bar { --border-radius: var(--control-slider-border-radius); - --handle-size: 4px; - --handle-margin: calc(var(--control-slider-thickness) / 8); --slider-size: 100%; position: absolute; height: 100%; @@ -432,7 +600,6 @@ export class HaControlSlider extends LitElement { .slider .slider-track-cursor { --cursor-size: calc(var(--control-slider-thickness) / 4); - --handle-size: 4px; position: absolute; background-color: white; border-radius: var(--handle-size); @@ -462,9 +629,11 @@ export class HaControlSlider extends LitElement { height: var(--handle-size); width: 50%; } - - :host([pressed]) .slider-track-bar, - :host([pressed]) .slider-track-cursor { + .pressed .tooltip { + transition: opacity 180ms ease-in-out; + } + .pressed .slider-track-bar, + .pressed .slider-track-cursor { transition: none; } :host(:disabled) .slider { diff --git a/src/data/entity_attributes.ts b/src/data/entity_attributes.ts index db9c63e563a6..00e2e6d3dcfb 100644 --- a/src/data/entity_attributes.ts +++ b/src/data/entity_attributes.ts @@ -34,7 +34,7 @@ export const TEMPERATURE_ATTRIBUTES = new Set([ "max_temp", ]); -export const DOMAIN_ATTRIBUTES_UNITS: Record> = { +export const DOMAIN_ATTRIBUTES_UNITS = { climate: { humidity: "%", current_humidity: "%", @@ -74,4 +74,4 @@ export const DOMAIN_ATTRIBUTES_UNITS: Record> = { sensor: { battery_level: "%", }, -}; +} as const satisfies Record>; diff --git a/src/dialogs/more-info/components/cover/ha-more-info-cover-position.ts b/src/dialogs/more-info/components/cover/ha-more-info-cover-position.ts index e1dfeb91c541..ab13306eadd7 100644 --- a/src/dialogs/more-info/components/cover/ha-more-info-cover-position.ts +++ b/src/dialogs/more-info/components/cover/ha-more-info-cover-position.ts @@ -6,6 +6,7 @@ import { stateColorCss } from "../../../../common/entity/state_color"; import "../../../../components/ha-control-slider"; import { CoverEntity } from "../../../../data/cover"; import { UNAVAILABLE } from "../../../../data/entity"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../../data/entity_attributes"; import { HomeAssistant } from "../../../../types"; @customElement("ha-more-info-cover-position") @@ -60,6 +61,8 @@ export class HaMoreInfoCoverPosition extends LitElement { "--control-slider-background": color, })} .disabled=${this.stateObj.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.cover.current_position} + .locale=${this.hass.locale} > `; @@ -76,6 +79,7 @@ export class HaMoreInfoCoverPosition extends LitElement { --control-slider-color: var(--primary-color); --control-slider-background: var(--disabled-color); --control-slider-background-opacity: 0.2; + --control-slider-tooltip-font-size: 20px; } `; } diff --git a/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts b/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts index cf23456e86bd..d5c2113743ba 100644 --- a/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts +++ b/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts @@ -13,6 +13,7 @@ import { stateColorCss } from "../../../../common/entity/state_color"; import "../../../../components/ha-control-slider"; import { CoverEntity } from "../../../../data/cover"; import { UNAVAILABLE } from "../../../../data/entity"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../../data/entity_attributes"; import { HomeAssistant } from "../../../../types"; export function generateTiltSliderTrackBackgroundGradient() { @@ -96,6 +97,8 @@ export class HaMoreInfoCoverTiltPosition extends LitElement { "--control-slider-background": color, })} .disabled=${this.stateObj.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.cover.current_tilt_position} + .locale=${this.hass.locale} >
@@ -113,6 +116,7 @@ export class HaMoreInfoCoverTiltPosition extends LitElement { --control-slider-color: var(--primary-color); --control-slider-background: var(--disabled-color); --control-slider-background-opacity: 0.2; + --control-slider-tooltip-font-size: 20px; } .gradient { background: -webkit-linear-gradient(top, ${GRADIENT}); diff --git a/src/dialogs/more-info/components/fan/ha-more-info-fan-speed.ts b/src/dialogs/more-info/components/fan/ha-more-info-fan-speed.ts index d1a641d6c5fc..7146131040db 100644 --- a/src/dialogs/more-info/components/fan/ha-more-info-fan-speed.ts +++ b/src/dialogs/more-info/components/fan/ha-more-info-fan-speed.ts @@ -8,6 +8,7 @@ import "../../../../components/ha-control-select"; import type { ControlSelectOption } from "../../../../components/ha-control-select"; import "../../../../components/ha-control-slider"; import { UNAVAILABLE } from "../../../../data/entity"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../../data/entity_attributes"; import { computeFanSpeedCount, computeFanSpeedIcon, @@ -130,6 +131,8 @@ export class HaMoreInfoFanSpeed extends LitElement { "--control-slider-background": color, })} .disabled=${this.stateObj.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.fan.percentage} + .locale=${this.hass.locale} > `; @@ -146,6 +149,7 @@ export class HaMoreInfoFanSpeed extends LitElement { --control-slider-color: var(--primary-color); --control-slider-background: var(--disabled-color); --control-slider-background-opacity: 0.2; + --control-slider-tooltip-font-size: 20px; } ha-control-select { height: 45vh; diff --git a/src/dialogs/more-info/components/lights/ha-more-info-light-brightness.ts b/src/dialogs/more-info/components/lights/ha-more-info-light-brightness.ts index 8798250214aa..587df1047b38 100644 --- a/src/dialogs/more-info/components/lights/ha-more-info-light-brightness.ts +++ b/src/dialogs/more-info/components/lights/ha-more-info-light-brightness.ts @@ -77,6 +77,8 @@ export class HaMoreInfoLightBrightness extends LitElement { "--control-slider-background": color, })} .disabled=${this.stateObj.state === UNAVAILABLE} + .tooltipUnit=${"%"} + .locale=${this.hass.locale} > `; @@ -93,6 +95,7 @@ export class HaMoreInfoLightBrightness extends LitElement { --control-slider-color: var(--primary-color); --control-slider-background: var(--disabled-color); --control-slider-background-opacity: 0.2; + --control-slider-tooltip-font-size: 20px; } `; } diff --git a/src/dialogs/more-info/components/lights/light-color-temp-picker.ts b/src/dialogs/more-info/components/lights/light-color-temp-picker.ts index 0331d24b3133..1f645e32c635 100644 --- a/src/dialogs/more-info/components/lights/light-color-temp-picker.ts +++ b/src/dialogs/more-info/components/lights/light-color-temp-picker.ts @@ -26,6 +26,7 @@ import { LightEntity, } from "../../../../data/light"; import { HomeAssistant } from "../../../../types"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../../data/entity_attributes"; declare global { interface HASSDomEvents { @@ -93,6 +94,8 @@ class LightColorTempPicker extends LitElement { "--gradient": gradient, })} .disabled=${this.stateObj.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.light.color_temp_kelvin} + .locale=${this.hass.locale} > `; @@ -193,6 +196,7 @@ class LightColorTempPicker extends LitElement { top, var(--gradient) ); + --control-slider-tooltip-font-size: 20px; --control-slider-background-opacity: 1; } `, diff --git a/src/dialogs/more-info/controls/more-info-cover.ts b/src/dialogs/more-info/controls/more-info-cover.ts index 02b2f2ec5a66..3c2881017e48 100644 --- a/src/dialogs/more-info/controls/more-info-cover.ts +++ b/src/dialogs/more-info/controls/more-info-cover.ts @@ -33,36 +33,12 @@ class MoreInfoCover extends LitElement { @property({ attribute: false }) public stateObj?: CoverEntity; - @state() private _livePosition?: number; - - @state() private _liveTilt?: number; - @state() private _mode?: Mode; private _setMode(ev) { this._mode = ev.currentTarget.mode; } - private _positionSliderMoved(ev) { - const value = (ev.detail as any).value; - if (isNaN(value)) return; - this._livePosition = value; - } - - private _positionValueChanged() { - this._livePosition = undefined; - } - - private _tiltSliderMoved(ev) { - const value = (ev.detail as any).value; - if (isNaN(value)) return; - this._liveTilt = value; - } - - private _tiltValueChanged() { - this._liveTilt = undefined; - } - protected willUpdate(changedProps: PropertyValues): void { super.willUpdate(changedProps); if (changedProps.has("stateObj") && this.stateObj) { @@ -77,20 +53,11 @@ class MoreInfoCover extends LitElement { } private get _stateOverride() { - const liveValue = this._livePosition ?? this._liveTilt; - - const forcedState = - liveValue != null ? (liveValue ? "open" : "closed") : undefined; - - const stateDisplay = this.hass.formatEntityState( - this.stateObj!, - forcedState - ); + const stateDisplay = this.hass.formatEntityState(this.stateObj!); const positionStateDisplay = computeCoverPositionStateDisplay( this.stateObj!, - this.hass, - liveValue + this.hass ); if (positionStateDisplay) { @@ -147,8 +114,6 @@ class MoreInfoCover extends LitElement { ` : nothing} @@ -157,8 +122,6 @@ class MoreInfoCover extends LitElement { ` : nothing} diff --git a/src/dialogs/more-info/controls/more-info-fan.ts b/src/dialogs/more-info/controls/more-info-fan.ts index 8c8f566cdcdb..f2028f577ca8 100644 --- a/src/dialogs/more-info/controls/more-info-fan.ts +++ b/src/dialogs/more-info/controls/more-info-fan.ts @@ -40,18 +40,6 @@ class MoreInfoFan extends LitElement { @state() public _presetMode?: string; - @state() private _liveSpeed?: number; - - private _speedSliderMoved(ev) { - const value = (ev.detail as any).value; - if (isNaN(value)) return; - this._liveSpeed = value; - } - - private _speedValueChanged() { - this._liveSpeed = undefined; - } - private _toggle = () => { const service = this.stateObj?.state === "on" ? "turn_off" : "turn_on"; forwardHaptic("light"); @@ -104,23 +92,14 @@ class MoreInfoFan extends LitElement { } private get _stateOverride() { - const liveValue = this._liveSpeed; - - const forcedState = - liveValue != null ? (liveValue ? "on" : "off") : undefined; - - const stateDisplay = this.hass.formatEntityState( - this.stateObj!, - forcedState - ); + const stateDisplay = this.hass.formatEntityState(this.stateObj!); const positionStateDisplay = computeFanSpeedStateDisplay( this.stateObj!, - this.hass, - liveValue + this.hass ); - if (positionStateDisplay && (stateActive(this.stateObj!) || liveValue)) { + if (positionStateDisplay && stateActive(this.stateObj!)) { return positionStateDisplay; } return stateDisplay; @@ -165,8 +144,6 @@ class MoreInfoFan extends LitElement { ` diff --git a/src/dialogs/more-info/controls/more-info-light.ts b/src/dialogs/more-info/controls/more-info-light.ts index 5d3800d651f1..63e07c722251 100644 --- a/src/dialogs/more-info/controls/more-info-light.ts +++ b/src/dialogs/more-info/controls/more-info-light.ts @@ -60,29 +60,10 @@ class MoreInfoLight extends LitElement { @state() private _effect?: string; - @state() private _selectedBrightness?: number; - - @state() private _colorTempPreview?: number; - @state() private _mainControl: MainControl = "brightness"; - private _brightnessChanged(ev) { - const value = (ev.detail as any).value; - if (isNaN(value)) return; - this._selectedBrightness = (value * 255) / 100; - } - - private _tempColorHovered(ev: CustomEvent) { - if (ev.detail && "color_temp_kelvin" in ev.detail) { - this._colorTempPreview = ev.detail.color_temp_kelvin; - } else { - this._colorTempPreview = undefined; - } - } - protected updated(changedProps: PropertyValues): void { if (changedProps.has("stateObj")) { - this._selectedBrightness = this.stateObj?.attributes.brightness; this._effect = this.stateObj?.attributes.effect; } } @@ -98,19 +79,8 @@ class MoreInfoLight extends LitElement { } private get _stateOverride() { - if (this._colorTempPreview) { - return this.hass.formatEntityAttributeValue( - this.stateObj!, - "color_temp_kelvin", - this._colorTempPreview - ); - } - if (this._selectedBrightness) { - return this.hass.formatEntityAttributeValue( - this.stateObj!, - "brightness", - this._selectedBrightness - ); + if (this.stateObj?.attributes.brightness) { + return this.hass.formatEntityAttributeValue(this.stateObj!, "brightness"); } return undefined; } @@ -168,7 +138,6 @@ class MoreInfoLight extends LitElement { ` @@ -187,7 +156,6 @@ class MoreInfoLight extends LitElement { ` diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index c775a30984d0..8680b42cf006 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -350,7 +350,6 @@ export class HuiTileCard extends LitElement implements LovelaceCard { return html` - ${this._shouldRenderRipple ? html`` : nothing}
+ > + ${this._shouldRenderRipple + ? html`` + : nothing} +
{ const domain = computeDomain(stateObj.entity_id); @@ -93,6 +94,8 @@ class HuiCoverPositionTileFeature "current_position" )} .disabled=${this.stateObj!.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.cover.current_position} + .locale=${this.hass.locale} >
`; diff --git a/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts index 00c5768dd437..7607527d0b09 100644 --- a/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts @@ -13,6 +13,7 @@ import { generateTiltSliderTrackBackgroundGradient } from "../../../dialogs/more import { HomeAssistant } from "../../../types"; import { LovelaceTileFeature } from "../types"; import { CoverTiltPositionTileFeatureConfig } from "./types"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../data/entity_attributes"; const GRADIENT = generateTiltSliderTrackBackgroundGradient(); @@ -92,6 +93,8 @@ class HuiCoverTiltPositionTileFeature "current_tilt_position" )} .disabled=${this.stateObj!.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.cover.current_tilt_position} + .locale=${this.hass.locale} >
diff --git a/src/panels/lovelace/tile-features/hui-fan-speed-tile-feature.ts b/src/panels/lovelace/tile-features/hui-fan-speed-tile-feature.ts index 8e6804d1f458..4b587fb71b7e 100644 --- a/src/panels/lovelace/tile-features/hui-fan-speed-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-fan-speed-tile-feature.ts @@ -23,6 +23,7 @@ import { import { HomeAssistant } from "../../../types"; import { LovelaceTileFeature } from "../types"; import { FanSpeedTileFeatureConfig } from "./types"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../data/entity_attributes"; export const supportsFanSpeedTileFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -126,6 +127,8 @@ class HuiFanSpeedTileFeature extends LitElement implements LovelaceTileFeature { "percentage" )} .disabled=${this.stateObj!.state === UNAVAILABLE} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.fan.percentage} + .locale=${this.hass.locale} >
`; diff --git a/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts b/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts index 01d1e763cf99..a08bbf243033 100644 --- a/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts @@ -67,6 +67,8 @@ class HuiLightBrightnessTileFeature .disabled=${this.stateObj!.state === UNAVAILABLE} @value-changed=${this._valueChanged} .label=${this.hass.localize("ui.card.light.brightness")} + .tooltipUnit=${"%"} + .locale=${this.hass.locale} > `; diff --git a/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts b/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts index 2c35e33eae75..7d641679d7e4 100644 --- a/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-light-color-temp-tile-feature.ts @@ -11,6 +11,7 @@ import { computeDomain } from "../../../common/entity/compute_domain"; import { stateActive } from "../../../common/entity/state_active"; import "../../../components/ha-control-slider"; import { UNAVAILABLE } from "../../../data/entity"; +import { DOMAIN_ATTRIBUTES_UNITS } from "../../../data/entity_attributes"; import { LightColorMode, lightSupportsColorMode } from "../../../data/light"; import { generateColorTemperatureGradient } from "../../../dialogs/more-info/components/lights/light-color-temp-picker"; import { HomeAssistant } from "../../../types"; @@ -85,6 +86,8 @@ class HuiLightColorTempTileFeature style=${styleMap({ "--gradient": gradient, })} + .tooltipUnit=${DOMAIN_ATTRIBUTES_UNITS.light.color_temp_kelvin} + .locale=${this.hass.locale} > `;