Use resize-controller instead of container queries (#18885)

This commit is contained in:
Paul Bottein 2023-12-04 14:16:10 +01:00 committed by GitHub
parent bb2abe4efc
commit 8a93284bb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 132 additions and 57 deletions

View File

@ -1,3 +1,4 @@
import { ResizeController } from "@lit-labs/observers/resize-controller";
import { mdiMinus, mdiPlus } from "@mdi/js"; import { mdiMinus, mdiPlus } from "@mdi/js";
import { import {
CSSResultGroup, CSSResultGroup,
@ -49,6 +50,13 @@ export class HaControlNumberButton extends LitElement {
@query("#input") _input!: HTMLDivElement; @query("#input") _input!: HTMLDivElement;
private _hideUnit = new ResizeController(this, {
callback: (entries) => {
const width = entries[0]?.contentRect.width;
return width < 100;
},
});
private boundedValue(value: number) { private boundedValue(value: number) {
const clamped = conditionalClamp(value, this.min, this.max); const clamped = conditionalClamp(value, this.min, this.max);
return Math.round(clamped / this._step) * this._step; return Math.round(clamped / this._step) * this._step;
@ -145,7 +153,10 @@ export class HaControlNumberButton extends LitElement {
?disabled=${this.disabled} ?disabled=${this.disabled}
@keydown=${this._handleKeyDown} @keydown=${this._handleKeyDown}
> >
${value} ${unit ? html`<span class="unit">${unit}</span>` : nothing} ${value}
${unit && !this._hideUnit.value
? html`<span class="unit">${unit}</span>`
: nothing}
</div> </div>
<button <button
class="button minus" class="button minus"

View File

@ -64,8 +64,7 @@ class PanelCalendar extends LitElement {
private _end?: Date; private _end?: Date;
private _showPaneController = new ResizeController(this, { private _showPaneController = new ResizeController(this, {
callback: (entries: ResizeObserverEntry[]) => callback: (entries) => entries[0]?.contentRect.width > 750,
entries[0]?.contentRect.width > 750,
}); });
private _mql?: MediaQueryList; private _mql?: MediaQueryList;

View File

@ -68,8 +68,7 @@ class PanelTodo extends LitElement {
private _headerHeight = 56; private _headerHeight = 56;
private _showPaneController = new ResizeController(this, { private _showPaneController = new ResizeController(this, {
callback: (entries: ResizeObserverEntry[]) => callback: (entries) => entries[0]?.contentRect.width > 750,
entries[0]?.contentRect.width > 750,
}); });
private _mql?: MediaQueryList; private _mql?: MediaQueryList;

View File

@ -1,6 +1,7 @@
import { mdiMinus, mdiPlus, mdiWaterPercent } from "@mdi/js"; import { mdiMinus, mdiPlus, mdiWaterPercent } from "@mdi/js";
import { CSSResultGroup, LitElement, PropertyValues, html } from "lit"; import { CSSResultGroup, LitElement, PropertyValues, html } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { stateActive } from "../../common/entity/state_active"; import { stateActive } from "../../common/entity/state_active";
import { domainStateColorProperties } from "../../common/entity/state_color"; import { domainStateColorProperties } from "../../common/entity/state_color";
@ -15,7 +16,10 @@ import { ClimateEntity, ClimateEntityFeature } from "../../data/climate";
import { UNAVAILABLE } from "../../data/entity"; import { UNAVAILABLE } from "../../data/entity";
import { computeCssVariable } from "../../resources/css-variables"; import { computeCssVariable } from "../../resources/css-variables";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import { stateControlCircularSliderStyle } from "../state-control-circular-slider-style"; import {
createStateControlCircularSliderController,
stateControlCircularSliderStyle,
} from "../state-control-circular-slider-style";
@customElement("ha-state-control-climate-humidity") @customElement("ha-state-control-climate-humidity")
export class HaStateControlClimateHumidity extends LitElement { export class HaStateControlClimateHumidity extends LitElement {
@ -28,6 +32,8 @@ export class HaStateControlClimateHumidity extends LitElement {
@state() private _targetHumidity?: number; @state() private _targetHumidity?: number;
private _sizeController = createStateControlCircularSliderController(this);
protected willUpdate(changedProp: PropertyValues): void { protected willUpdate(changedProp: PropertyValues): void {
super.willUpdate(changedProp); super.willUpdate(changedProp);
if (changedProp.has("stateObj")) { if (changedProp.has("stateObj")) {
@ -169,6 +175,10 @@ export class HaStateControlClimateHumidity extends LitElement {
const targetHumidity = this._targetHumidity; const targetHumidity = this._targetHumidity;
const currentHumidity = this.stateObj.attributes.current_humidity; const currentHumidity = this.stateObj.attributes.current_humidity;
const containerSizeClass = this._sizeController.value
? { [this._sizeController.value]: true }
: {};
if ( if (
supportsTargetHumidity && supportsTargetHumidity &&
targetHumidity != null && targetHumidity != null &&
@ -176,7 +186,7 @@ export class HaStateControlClimateHumidity extends LitElement {
) { ) {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
})} })}
@ -204,7 +214,7 @@ export class HaStateControlClimateHumidity extends LitElement {
} }
return html` return html`
<div class="container"> <div class="container${classMap(containerSizeClass)}">
<ha-control-circular-slider <ha-control-circular-slider
.current=${this.stateObj.attributes.current_humidity} .current=${this.stateObj.attributes.current_humidity}
.min=${this._min} .min=${this._min}

View File

@ -22,7 +22,10 @@ import {
} from "../../data/climate"; } from "../../data/climate";
import { UNAVAILABLE } from "../../data/entity"; import { UNAVAILABLE } from "../../data/entity";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import { stateControlCircularSliderStyle } from "../state-control-circular-slider-style"; import {
createStateControlCircularSliderController,
stateControlCircularSliderStyle,
} from "../state-control-circular-slider-style";
type Target = "value" | "low" | "high"; type Target = "value" | "low" | "high";
@ -49,6 +52,8 @@ export class HaStateControlClimateTemperature extends LitElement {
@state() private _selectTargetTemperature: Target = "low"; @state() private _selectTargetTemperature: Target = "low";
private _sizeController = createStateControlCircularSliderController(this);
protected willUpdate(changedProp: PropertyValues): void { protected willUpdate(changedProp: PropertyValues): void {
super.willUpdate(changedProp); super.willUpdate(changedProp);
if (changedProp.has("stateObj")) { if (changedProp.has("stateObj")) {
@ -285,6 +290,10 @@ export class HaStateControlClimateTemperature extends LitElement {
); );
} }
const containerSizeClass = this._sizeController.value
? { [this._sizeController.value]: true }
: {};
if ( if (
supportsTargetTemperature && supportsTargetTemperature &&
this._targetTemperature.value != null && this._targetTemperature.value != null &&
@ -302,7 +311,7 @@ export class HaStateControlClimateTemperature extends LitElement {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
"--action-color": actionColor, "--action-color": actionColor,
@ -340,7 +349,7 @@ export class HaStateControlClimateTemperature extends LitElement {
) { ) {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--low-color": lowColor, "--low-color": lowColor,
"--high-color": highColor, "--high-color": highColor,
@ -395,7 +404,9 @@ export class HaStateControlClimateTemperature extends LitElement {
return html` return html`
<div <div
class="container" class="container${classMap({
[this._sizeController.value ?? ""]: true,
})}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
})} })}
@ -450,15 +461,12 @@ export class HaStateControlClimateTemperature extends LitElement {
.dual button.selected { .dual button.selected {
opacity: 1; opacity: 1;
} }
@container container (max-width: 250px) { .container.md .dual {
.dual { gap: 16px;
gap: 16px;
}
} }
@container container (max-width: 190px) { .container.sm .dual,
.dual { .container.xs .dual {
gap: 8px; gap: 8px;
}
} }
ha-control-circular-slider { ha-control-circular-slider {
--control-circular-slider-low-color: var( --control-circular-slider-low-color: var(

View File

@ -1,6 +1,7 @@
import { mdiMinus, mdiPlus, mdiWaterPercent } from "@mdi/js"; import { mdiMinus, mdiPlus, mdiWaterPercent } from "@mdi/js";
import { CSSResultGroup, LitElement, PropertyValues, html } from "lit"; import { CSSResultGroup, LitElement, PropertyValues, html } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { stateActive } from "../../common/entity/state_active"; import { stateActive } from "../../common/entity/state_active";
import { stateColorCss } from "../../common/entity/state_color"; import { stateColorCss } from "../../common/entity/state_color";
@ -17,7 +18,10 @@ import {
HumidifierEntityDeviceClass, HumidifierEntityDeviceClass,
} from "../../data/humidifier"; } from "../../data/humidifier";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import { stateControlCircularSliderStyle } from "../state-control-circular-slider-style"; import {
createStateControlCircularSliderController,
stateControlCircularSliderStyle,
} from "../state-control-circular-slider-style";
@customElement("ha-state-control-humidifier-humidity") @customElement("ha-state-control-humidifier-humidity")
export class HaStateControlHumidifierHumidity extends LitElement { export class HaStateControlHumidifierHumidity extends LitElement {
@ -30,6 +34,8 @@ export class HaStateControlHumidifierHumidity extends LitElement {
@state() private _targetHumidity?: number; @state() private _targetHumidity?: number;
private _sizeController = createStateControlCircularSliderController(this);
protected willUpdate(changedProp: PropertyValues): void { protected willUpdate(changedProp: PropertyValues): void {
super.willUpdate(changedProp); super.willUpdate(changedProp);
if (changedProp.has("stateObj")) { if (changedProp.has("stateObj")) {
@ -178,6 +184,10 @@ export class HaStateControlHumidifierHumidity extends LitElement {
const targetHumidity = this._targetHumidity; const targetHumidity = this._targetHumidity;
const currentHumidity = this.stateObj.attributes.current_humidity; const currentHumidity = this.stateObj.attributes.current_humidity;
const containerSizeClass = this._sizeController.value
? { [this._sizeController.value]: true }
: {};
if (targetHumidity != null && this.stateObj.state !== UNAVAILABLE) { if (targetHumidity != null && this.stateObj.state !== UNAVAILABLE) {
const inverted = const inverted =
this.stateObj.attributes.device_class === this.stateObj.attributes.device_class ===
@ -185,7 +195,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
"--action-color": actionColor, "--action-color": actionColor,
@ -216,7 +226,7 @@ export class HaStateControlHumidifierHumidity extends LitElement {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--action-color": actionColor, "--action-color": actionColor,
})} })}

View File

@ -1,4 +1,5 @@
import { css } from "lit"; import { ResizeController } from "@lit-labs/observers/resize-controller";
import { ReactiveControllerHost, css } from "lit";
export const stateControlCircularSliderStyle = css` export const stateControlCircularSliderStyle = css`
/* Layout elements */ /* Layout elements */
@ -70,39 +71,50 @@ export const stateControlCircularSliderStyle = css`
--md-outlined-icon-button-icon-size: 24px; --md-outlined-icon-button-icon-size: 24px;
} }
@container container (max-width: 250px) { .container.md ha-big-number {
ha-big-number { font-size: 44px;
font-size: 44px;
}
.buttons {
gap: 16px;
}
.info {
margin-top: 12px;
gap: 6px;
}
.buttons {
display: none;
}
ha-control-circular-slider {
margin-bottom: -16px;
}
} }
@container container (max-width: 190px) { .container.md .info {
ha-big-number { margin-top: 12px;
font-size: 32px; gap: 6px;
} }
.info { .container.md .buttons {
font-size: 14px; display: none;
gap: 2px; }
--mdc-icon-size: 14px; .container.md ha-control-circular-slider {
} margin-bottom: -16px;
} }
@container container (max-width: 130px) { .container.sm ha-big-number {
.label { font-size: 32px;
display: none; }
} .container.sm .info {
margin-top: 12px;
font-size: 14px;
gap: 2px;
--mdc-icon-size: 14px;
}
.container.sm .buttons {
display: none;
}
.container.sm ha-control-circular-slider {
margin-bottom: -16px;
}
.container.xs ha-big-number {
font-size: 32px;
}
.container.xs .info {
margin-top: 12px;
}
.container.xs .buttons {
display: none;
}
.container.xs ha-control-circular-slider {
margin-bottom: -16px;
}
.container.xs .label {
display: none;
} }
/* Slider */ /* Slider */
@ -127,3 +139,19 @@ export const stateControlCircularSliderStyle = css`
pointer-events: none; pointer-events: none;
} }
`; `;
export const createStateControlCircularSliderController = (
element: ReactiveControllerHost & Element
) =>
new ResizeController(element, {
callback: (entries) => {
const width = entries[0]?.contentRect.width;
return width < 130
? "xs"
: width < 190
? "sm"
: width < 250
? "md"
: "lg";
},
});

View File

@ -1,6 +1,7 @@
import { mdiMinus, mdiPlus } from "@mdi/js"; import { mdiMinus, mdiPlus } from "@mdi/js";
import { CSSResultGroup, LitElement, PropertyValues, html } from "lit"; import { CSSResultGroup, LitElement, PropertyValues, html } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { UNIT_F } from "../../common/const"; import { UNIT_F } from "../../common/const";
import { stateActive } from "../../common/entity/state_active"; import { stateActive } from "../../common/entity/state_active";
@ -18,7 +19,10 @@ import {
WaterHeaterEntityFeature, WaterHeaterEntityFeature,
} from "../../data/water_heater"; } from "../../data/water_heater";
import { HomeAssistant } from "../../types"; import { HomeAssistant } from "../../types";
import { stateControlCircularSliderStyle } from "../state-control-circular-slider-style"; import {
createStateControlCircularSliderController,
stateControlCircularSliderStyle,
} from "../state-control-circular-slider-style";
@customElement("ha-state-control-water_heater-temperature") @customElement("ha-state-control-water_heater-temperature")
export class HaStateControlWaterHeaterTemperature extends LitElement { export class HaStateControlWaterHeaterTemperature extends LitElement {
@ -31,6 +35,8 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
@state() private _targetTemperature?: number; @state() private _targetTemperature?: number;
private _sizeController = createStateControlCircularSliderController(this);
protected willUpdate(changedProp: PropertyValues): void { protected willUpdate(changedProp: PropertyValues): void {
super.willUpdate(changedProp); super.willUpdate(changedProp);
if (changedProp.has("stateObj")) { if (changedProp.has("stateObj")) {
@ -174,6 +180,10 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
const stateColor = stateColorCss(this.stateObj); const stateColor = stateColorCss(this.stateObj);
const active = stateActive(this.stateObj); const active = stateActive(this.stateObj);
const containerSizeClass = this._sizeController.value
? { [this._sizeController.value]: true }
: {};
if ( if (
supportsTargetTemperature && supportsTargetTemperature &&
this._targetTemperature != null && this._targetTemperature != null &&
@ -181,7 +191,7 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
) { ) {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
})} })}
@ -211,7 +221,7 @@ export class HaStateControlWaterHeaterTemperature extends LitElement {
return html` return html`
<div <div
class="container" class="container${classMap(containerSizeClass)}"
style=${styleMap({ style=${styleMap({
"--state-color": stateColor, "--state-color": stateColor,
})} })}