Add tooltip to tile sliders and more info sliders (#18567)

This commit is contained in:
Paul Bottein 2023-11-08 12:47:55 +01:00 committed by GitHub
parent f2505c0798
commit bc21425981
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 269 additions and 134 deletions

View File

@ -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}
>
</ha-control-slider>
</div>
@ -114,6 +119,7 @@ export class DemoHaBarSlider extends LitElement {
@value-changed=${this.handleValueChanged}
@slider-moved=${this.handleSliderMoved}
aria-label=${label}
.tooltipUnit=${config.unit}
>
</ha-control-slider>
`;

View File

@ -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 " ";
};

View File

@ -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`
<span
aria-hidden="true"
class="tooltip ${classMap({
visible,
[position]: true,
[this.mode ?? "start"]: true,
"show-handle": this.showHandle,
})}"
>
${this._formatValue(value)}
</span>
`;
}
protected render(): TemplateResult {
return html`
<div
id="slider"
class="slider"
class="container${classMap({
pressed: this.pressed,
})}"
style=${styleMap({
"--value": `${this.valueToPercentage(this.value ?? 0)}`,
})}
>
<div class="slider-track-background"></div>
<slot name="background"></slot>
${this.mode === "cursor"
? this.value != null
? html`
<div id="slider" class="slider">
<div class="slider-track-background"></div>
<slot name="background"></slot>
${this.mode === "cursor"
? this.value != null
? html`
<div
class=${classMap({
"slider-track-cursor": true,
})}
></div>
`
: null
: html`
<div
class=${classMap({
"slider-track-cursor": true,
"slider-track-bar": true,
[this.mode ?? "start"]: true,
"show-handle": this.showHandle,
})}
></div>
`
: null
: html`
<div
class=${classMap({
"slider-track-bar": true,
[this.mode ?? "start"]: true,
"show-handle": this.showHandle,
})}
></div>
`}
`}
</div>
${this._renderTooltip()}
</div>
`;
}
@ -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 {

View File

@ -34,7 +34,7 @@ export const TEMPERATURE_ATTRIBUTES = new Set([
"max_temp",
]);
export const DOMAIN_ATTRIBUTES_UNITS: Record<string, Record<string, string>> = {
export const DOMAIN_ATTRIBUTES_UNITS = {
climate: {
humidity: "%",
current_humidity: "%",
@ -74,4 +74,4 @@ export const DOMAIN_ATTRIBUTES_UNITS: Record<string, Record<string, string>> = {
sensor: {
battery_level: "%",
},
};
} as const satisfies Record<string, Record<string, string>>;

View File

@ -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}
>
</ha-control-slider>
`;
@ -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;
}
`;
}

View File

@ -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}
>
<div slot="background" class="gradient"></div>
</ha-control-slider>
@ -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});

View File

@ -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}
>
</ha-control-slider>
`;
@ -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;

View File

@ -77,6 +77,8 @@ export class HaMoreInfoLightBrightness extends LitElement {
"--control-slider-background": color,
})}
.disabled=${this.stateObj.state === UNAVAILABLE}
.tooltipUnit=${"%"}
.locale=${this.hass.locale}
>
</ha-control-slider>
`;
@ -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;
}
`;
}

View File

@ -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}
>
</ha-control-slider>
`;
@ -193,6 +196,7 @@ class LightColorTempPicker extends LitElement {
top,
var(--gradient)
);
--control-slider-tooltip-font-size: 20px;
--control-slider-background-opacity: 1;
}
`,

View File

@ -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 {
<ha-more-info-cover-position
.stateObj=${this.stateObj}
.hass=${this.hass}
@slider-moved=${this._positionSliderMoved}
@value-changed=${this._positionValueChanged}
></ha-more-info-cover-position>
`
: nothing}
@ -157,8 +122,6 @@ class MoreInfoCover extends LitElement {
<ha-more-info-cover-tilt-position
.stateObj=${this.stateObj}
.hass=${this.hass}
@slider-moved=${this._tiltSliderMoved}
@value-changed=${this._tiltValueChanged}
></ha-more-info-cover-tilt-position>
`
: nothing}

View File

@ -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 {
<ha-more-info-fan-speed
.stateObj=${this.stateObj}
.hass=${this.hass}
@slider-moved=${this._speedSliderMoved}
@value-changed=${this._speedValueChanged}
>
</ha-more-info-fan-speed>
`

View File

@ -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<HASSDomEvents["color-hovered"]>) {
if (ev.detail && "color_temp_kelvin" in ev.detail) {
this._colorTempPreview = ev.detail.color_temp_kelvin;
} else {
this._colorTempPreview = undefined;
}
}
protected updated(changedProps: PropertyValues<typeof this>): 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 {
<ha-more-info-light-brightness
.stateObj=${this.stateObj}
.hass=${this.hass}
@slider-moved=${this._brightnessChanged}
>
</ha-more-info-light-brightness>
`
@ -187,7 +156,6 @@ class MoreInfoLight extends LitElement {
<light-color-temp-picker
.hass=${this.hass}
.stateObj=${this.stateObj}
@color-hovered=${this._tempColorHovered}
>
</light-color-temp-picker>
`

View File

@ -350,7 +350,6 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
return html`
<ha-card style=${styleMap(style)} class=${classMap({ active })}>
${this._shouldRenderRipple ? html`<mwc-ripple></mwc-ripple>` : nothing}
<div class="tile">
<div
class="background"
@ -366,7 +365,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
@touchstart=${this.handleRippleActivate}
@touchend=${this.handleRippleDeactivate}
@touchcancel=${this.handleRippleDeactivate}
></div>
>
${this._shouldRenderRipple
? html`<mwc-ripple></mwc-ripple>`
: nothing}
</div>
<div class="content ${classMap(contentClasses)}">
<div
class="icon-container"
@ -437,7 +440,6 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
ha-card {
--mdc-ripple-color: var(--tile-color);
height: 100%;
overflow: hidden;
transition:
box-shadow 180ms ease-in-out,
border-color 180ms ease-in-out;
@ -457,6 +459,8 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
left: 0;
bottom: 0;
right: 0;
border-radius: var(--ha-card-border-radius, 12px);
overflow: hidden;
}
.content {
display: flex;

View File

@ -13,6 +13,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types";
import { LovelaceTileFeature } from "../types";
import { CoverPositionTileFeatureConfig } from "./types";
import { DOMAIN_ATTRIBUTES_UNITS } from "../../../data/entity_attributes";
export const supportsCoverPositionTileFeature = (stateObj: HassEntity) => {
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}
></ha-control-slider>
</div>
`;

View File

@ -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}
>
<div slot="background" class="gradient"></div
></ha-control-slider>

View File

@ -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}
></ha-control-slider>
</div>
`;

View File

@ -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}
></ha-control-slider>
</div>
`;

View File

@ -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}
></ha-control-slider>
</div>
`;