Add tooltip to tile sliders and more info sliders (#18567)
This commit is contained in:
parent
f2505c0798
commit
bc21425981
|
@ -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>
|
||||
`;
|
||||
|
|
|
@ -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 " ";
|
||||
};
|
|
@ -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 {
|
||||
|
|
|
@ -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>>;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
|
|
@ -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});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
`,
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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>
|
||||
`
|
||||
|
|
|
@ -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>
|
||||
`
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
`;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
`;
|
||||
|
|
|
@ -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>
|
||||
`;
|
||||
|
|
|
@ -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>
|
||||
`;
|
||||
|
|
Loading…
Reference in New Issue