Adapt more info button layout depending of number of items and screen (#17691)

This commit is contained in:
Paul Bottein 2023-08-29 15:13:08 +02:00 committed by GitHub
parent 7483833dcd
commit 6f99a39b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 469 additions and 445 deletions

View File

@ -171,15 +171,12 @@ export class HaControlSelectMenu extends SelectBase {
--control-select-menu-background-color: var(--disabled-color); --control-select-menu-background-color: var(--disabled-color);
--control-select-menu-background-opacity: 0.2; --control-select-menu-background-opacity: 0.2;
--control-select-menu-border-radius: 14px; --control-select-menu-border-radius: 14px;
--control-select-menu-min-width: 120px;
--control-select-menu-max-width: 200px;
--control-select-menu-width: 100%;
--mdc-icon-size: 20px; --mdc-icon-size: 20px;
width: auto;
color: var(--primary-text-color); color: var(--primary-text-color);
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color: transparent;
} }
.select-anchor { .select-anchor {
color: var(--control-select-menu-text-color);
height: 48px; height: 48px;
padding: 6px 10px; padding: 6px 10px;
overflow: hidden; overflow: hidden;
@ -198,11 +195,8 @@ export class HaControlSelectMenu extends SelectBase {
z-index: 0; z-index: 0;
font-size: inherit; font-size: inherit;
transition: color 180ms ease-in-out; transition: color 180ms ease-in-out;
color: var(--control-text-icon-color);
gap: 10px; gap: 10px;
min-width: var(--control-select-menu-min-width); width: 100%;
max-width: var(--control-select-menu-max-width);
width: var(--control-select-menu-width);
user-select: none; user-select: none;
font-size: 14px; font-size: 14px;
font-style: normal; font-style: normal;

View File

@ -0,0 +1,79 @@
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
@customElement("ha-more-info-control-select-container")
export class HaMoreInfoControlSelectContainer extends LitElement {
protected render(): TemplateResult {
const classname = `items-${this.childElementCount}`;
return html`
<div class="controls">
<div
class="controls-scroll ${classMap({
[classname]: true,
multiline: this.childElementCount >= 4,
})}"
>
<slot></slot>
</div>
</div>
`;
}
static get styles(): CSSResultGroup {
return css`
.controls {
display: flex;
flex-direction: row;
justify-content: center;
}
.controls-scroll {
display: flex;
flex-direction: row;
justify-content: flex-start;
gap: 12px;
margin: auto;
overflow: auto;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
margin: 0 -24px;
padding: 0 24px;
}
.controls-scroll::-webkit-scrollbar {
display: none;
}
::slotted(*) {
min-width: 120px;
max-width: 160px;
flex: none;
}
@media all and (hover: hover),
all and (min-width: 600px) and (min-height: 501px) {
.controls-scroll {
justify-content: center;
flex-wrap: wrap;
width: 100%;
max-width: 450px;
}
.controls-scroll.items-4 {
max-width: 300px;
}
.controls-scroll.items-3 ::slotted(*) {
max-width: 140px;
}
.multiline ::slotted(*) {
width: 140px;
}
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-more-info-control-select-container": HaMoreInfoControlSelectContainer;
}
}

View File

@ -22,35 +22,6 @@ export const moreInfoControlStyle = css`
margin-bottom: 24px; margin-bottom: 24px;
} }
.secondary-controls {
display: flex;
flex-direction: row;
justify-content: center;
}
.secondary-controls-scroll {
display: flex;
flex-direction: row;
justify-content: flex-start;
gap: 12px;
margin: auto;
overflow: auto;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
margin: 0 -24px;
padding: 0 24px;
}
.secondary-controls-scroll::-webkit-scrollbar {
display: none;
}
/* Don't use scroll on device without touch support */
@media (hover: hover) {
.secondary-controls-scroll {
justify-content: center;
flex-wrap: wrap;
}
}
.buttons { .buttons {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -38,6 +38,7 @@ import { haOscillating } from "../../../data/icons/haOscillating";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import "../components/climate/ha-more-info-climate-humidity"; import "../components/climate/ha-more-info-climate-humidity";
import "../components/climate/ha-more-info-climate-temperature"; import "../components/climate/ha-more-info-climate-temperature";
import "../components/ha-more-info-control-select-container";
import { moreInfoControlStyle } from "../components/ha-more-info-control-style"; import { moreInfoControlStyle } from "../components/ha-more-info-control-style";
type MainControl = "temperature" | "humidity"; type MainControl = "temperature" | "humidity";
@ -163,140 +164,135 @@ class MoreInfoClimate extends LitElement {
` `
: nothing} : nothing}
</div> </div>
<div class="secondary-controls"> <ha-more-info-control-select-container>
<div class="secondary-controls-scroll"> <ha-control-select-menu
<ha-control-select-menu .label=${this.hass.formatEntityAttributeName(
.label=${this.hass.formatEntityAttributeName( this.stateObj,
this.stateObj, "hvac_mode"
"hvac_mode" )}
)} .value=${stateObj.state}
.value=${stateObj.state} .disabled=${this.stateObj.state === UNAVAILABLE}
.disabled=${this.stateObj.state === UNAVAILABLE} fixedMenuPosition
fixedMenuPosition naturalMenuWidth
naturalMenuWidth @selected=${this._handleOperationModeChanged}
@selected=${this._handleOperationModeChanged} @closed=${stopPropagation}
@closed=${stopPropagation} >
> <ha-svg-icon slot="icon" .path=${mdiThermostat}></ha-svg-icon>
<ha-svg-icon slot="icon" .path=${mdiThermostat}></ha-svg-icon> ${stateObj.attributes.hvac_modes
${stateObj.attributes.hvac_modes .concat()
.concat() .sort(compareClimateHvacModes)
.sort(compareClimateHvacModes) .map(
.map( (mode) => html`
(mode) => html` <ha-list-item .value=${mode} graphic="icon">
<ha-list-item .value=${mode} graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${computeHvacModeIcon(mode)}
></ha-svg-icon>
${this.hass.formatEntityState(stateObj, mode)}
</ha-list-item>
`
)}
</ha-control-select-menu>
${supportPresetMode && stateObj.attributes.preset_modes
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
stateObj,
"preset_mode"
)}
.value=${stateObj.attributes.preset_mode}
.disabled=${this.stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handlePresetmodeChanged}
@closed=${stopPropagation}
>
<ha-svg-icon <ha-svg-icon
slot="icon" slot="graphic"
.path=${mdiTuneVariant} .path=${computeHvacModeIcon(mode)}
></ha-svg-icon> ></ha-svg-icon>
${stateObj.attributes.preset_modes!.map( ${this.hass.formatEntityState(stateObj, mode)}
(mode) => html` </ha-list-item>
<ha-list-item .value=${mode} graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${computePresetModeIcon(mode)}
></ha-svg-icon>
${this.hass.formatEntityAttributeValue(
stateObj,
"preset_mode",
mode
)}
</ha-list-item>
`
)}
</ha-control-select-menu>
` `
: nothing} )}
${supportFanMode && stateObj.attributes.fan_modes </ha-control-select-menu>
? html` ${supportPresetMode && stateObj.attributes.preset_modes
<ha-control-select-menu ? html`
.label=${this.hass.formatEntityAttributeName( <ha-control-select-menu
stateObj, .label=${this.hass.formatEntityAttributeName(
"fan_mode" stateObj,
)} "preset_mode"
.value=${stateObj.attributes.fan_mode} )}
.disabled=${this.stateObj.state === UNAVAILABLE} .value=${stateObj.attributes.preset_mode}
fixedMenuPosition .disabled=${this.stateObj.state === UNAVAILABLE}
naturalMenuWidth fixedMenuPosition
@selected=${this._handleFanModeChanged} naturalMenuWidth
@closed=${stopPropagation} @selected=${this._handlePresetmodeChanged}
> @closed=${stopPropagation}
<ha-svg-icon slot="icon" .path=${mdiFan}></ha-svg-icon> >
${stateObj.attributes.fan_modes!.map( <ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
(mode) => html` ${stateObj.attributes.preset_modes!.map(
<ha-list-item .value=${mode} graphic="icon"> (mode) => html`
<ha-svg-icon <ha-list-item .value=${mode} graphic="icon">
slot="graphic" <ha-svg-icon
.path=${computeFanModeIcon(mode)} slot="graphic"
></ha-svg-icon> .path=${computePresetModeIcon(mode)}
${this.hass.formatEntityAttributeValue( ></ha-svg-icon>
stateObj, ${this.hass.formatEntityAttributeValue(
"fan_mode", stateObj,
mode "preset_mode",
)} mode
</ha-list-item> )}
` </ha-list-item>
)} `
</ha-control-select-menu> )}
` </ha-control-select-menu>
: nothing} `
${supportSwingMode && stateObj.attributes.swing_modes : nothing}
? html` ${supportFanMode && stateObj.attributes.fan_modes
<ha-control-select-menu ? html`
.label=${this.hass.formatEntityAttributeName( <ha-control-select-menu
stateObj, .label=${this.hass.formatEntityAttributeName(
"swing_mode" stateObj,
)} "fan_mode"
.value=${stateObj.attributes.swing_mode} )}
.disabled=${this.stateObj.state === UNAVAILABLE} .value=${stateObj.attributes.fan_mode}
fixedMenuPosition .disabled=${this.stateObj.state === UNAVAILABLE}
naturalMenuWidth fixedMenuPosition
@selected=${this._handleSwingmodeChanged} naturalMenuWidth
@closed=${stopPropagation} @selected=${this._handleFanModeChanged}
> @closed=${stopPropagation}
<ha-svg-icon slot="icon" .path=${haOscillating}></ha-svg-icon> >
${stateObj.attributes.swing_modes!.map( <ha-svg-icon slot="icon" .path=${mdiFan}></ha-svg-icon>
(mode) => html` ${stateObj.attributes.fan_modes!.map(
<ha-list-item .value=${mode} graphic="icon"> (mode) => html`
<ha-svg-icon <ha-list-item .value=${mode} graphic="icon">
slot="graphic" <ha-svg-icon
.path=${computeSwingModeIcon(mode)} slot="graphic"
></ha-svg-icon> .path=${computeFanModeIcon(mode)}
${this.hass.formatEntityAttributeValue( ></ha-svg-icon>
stateObj, ${this.hass.formatEntityAttributeValue(
"swing_mode", stateObj,
mode "fan_mode",
)} mode
</ha-list-item> )}
` </ha-list-item>
)} `
</ha-control-select-menu> )}
` </ha-control-select-menu>
: nothing} `
</div> : nothing}
</div> ${supportSwingMode && stateObj.attributes.swing_modes
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
stateObj,
"swing_mode"
)}
.value=${stateObj.attributes.swing_mode}
.disabled=${this.stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleSwingmodeChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${haOscillating}></ha-svg-icon>
${stateObj.attributes.swing_modes!.map(
(mode) => html`
<ha-list-item .value=${mode} graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${computeSwingModeIcon(mode)}
></ha-svg-icon>
${this.hass.formatEntityAttributeValue(
stateObj,
"swing_mode",
mode
)}
</ha-list-item>
`
)}
</ha-control-select-menu>
`
: nothing}
</ha-more-info-control-select-container>
`; `;
} }

View File

@ -27,6 +27,7 @@ import { haOscillating } from "../../../data/icons/haOscillating";
import { haOscillatingOff } from "../../../data/icons/haOscillatingOff"; import { haOscillatingOff } from "../../../data/icons/haOscillatingOff";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "../components/fan/ha-more-info-fan-speed"; import "../components/fan/ha-more-info-fan-speed";
import "../components/ha-more-info-control-select-container";
import { moreInfoControlStyle } from "../components/ha-more-info-control-style"; import { moreInfoControlStyle } from "../components/ha-more-info-control-style";
import "../components/ha-more-info-state-header"; import "../components/ha-more-info-state-header";
import "../components/ha-more-info-toggle"; import "../components/ha-more-info-toggle";
@ -191,117 +192,112 @@ class MoreInfoFan extends LitElement {
` `
: nothing} : nothing}
</div> </div>
<div class="secondary-controls"> <ha-more-info-control-select-container>
<div class="secondary-controls-scroll"> ${supportsPresetMode && this.stateObj.attributes.preset_modes
${supportsPresetMode && this.stateObj.attributes.preset_modes ? html`
? html` <ha-control-select-menu
<ha-control-select-menu .label=${this.hass.formatEntityAttributeName(
.label=${this.hass.formatEntityAttributeName( this.stateObj,
this.stateObj, "preset_mode"
"preset_mode" )}
)} .value=${this.stateObj.attributes.preset_mode}
.value=${this.stateObj.attributes.preset_mode} .disabled=${this.stateObj.state === UNAVAILABLE}
.disabled=${this.stateObj.state === UNAVAILABLE} fixedMenuPosition
fixedMenuPosition naturalMenuWidth
naturalMenuWidth @selected=${this._handlePresetMode}
@selected=${this._handlePresetMode} @closed=${stopPropagation}
@closed=${stopPropagation} >
> <ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
${this.stateObj.attributes.preset_modes?.map(
(mode) => html`
<ha-list-item .value=${mode}>
${this.hass.formatEntityAttributeValue(
this.stateObj!,
"preset_mode",
mode
)}
</ha-list-item>
`
)}
</ha-control-select-menu>
`
: nothing}
${supportsDirection
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
this.stateObj,
"direction"
)}
.value=${this.stateObj.attributes.direction}
.disabled=${this.stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleDirection}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiRotateLeft}></ha-svg-icon>
<ha-list-item value="forward" graphic="icon">
<ha-svg-icon <ha-svg-icon
slot="icon" slot="graphic"
.path=${mdiTuneVariant} .path=${mdiRotateRight}
></ha-svg-icon> ></ha-svg-icon>
${this.stateObj.attributes.preset_modes?.map( ${this.hass.formatEntityAttributeValue(
(mode) => html`
<ha-list-item .value=${mode}>
${this.hass.formatEntityAttributeValue(
this.stateObj!,
"preset_mode",
mode
)}
</ha-list-item>
`
)}
</ha-control-select-menu>
`
: nothing}
${supportsDirection
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
this.stateObj, this.stateObj,
"direction" "direction",
"forward"
)} )}
.value=${this.stateObj.attributes.direction} </ha-list-item>
.disabled=${this.stateObj.state === UNAVAILABLE} <ha-list-item value="reverse" graphic="icon">
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleDirection}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiRotateLeft}></ha-svg-icon>
<ha-list-item value="forward" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${mdiRotateRight}
></ha-svg-icon>
${this.hass.formatEntityAttributeValue(
this.stateObj,
"direction",
"forward"
)}
</ha-list-item>
<ha-list-item value="reverse" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${mdiRotateLeft}
></ha-svg-icon>
${this.hass.formatEntityAttributeValue(
this.stateObj,
"direction",
"reverse"
)}
</ha-list-item>
</ha-control-select-menu>
`
: nothing}
${supportsOscillate
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
this.stateObj,
"oscillating"
)}
.value=${this.stateObj.attributes.oscillating ? "on" : "off"}
.disabled=${this.stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleOscillating}
@closed=${stopPropagation}
>
<ha-svg-icon <ha-svg-icon
slot="icon" slot="graphic"
.path=${mdiRotateLeft}
></ha-svg-icon>
${this.hass.formatEntityAttributeValue(
this.stateObj,
"direction",
"reverse"
)}
</ha-list-item>
</ha-control-select-menu>
`
: nothing}
${supportsOscillate
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
this.stateObj,
"oscillating"
)}
.value=${this.stateObj.attributes.oscillating ? "on" : "off"}
.disabled=${this.stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleOscillating}
@closed=${stopPropagation}
>
<ha-svg-icon
slot="icon"
.path=${haOscillatingOff}
></ha-svg-icon>
<ha-list-item value="on" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${haOscillating}
></ha-svg-icon>
${this.hass.localize("state.default.on")}
</ha-list-item>
<ha-list-item value="off" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${haOscillatingOff} .path=${haOscillatingOff}
></ha-svg-icon> ></ha-svg-icon>
<ha-list-item value="on" graphic="icon"> ${this.hass.localize("state.default.off")}
<ha-svg-icon </ha-list-item>
slot="graphic" </ha-control-select-menu>
.path=${haOscillating} `
></ha-svg-icon> : nothing}
${this.hass.localize("state.default.on")} </ha-more-info-control-select-container>
</ha-list-item>
<ha-list-item value="off" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${haOscillatingOff}
></ha-svg-icon>
${this.hass.localize("state.default.off")}
</ha-list-item>
</ha-control-select-menu>
`
: nothing}
</div>
</div>
`; `;
} }

View File

@ -25,6 +25,7 @@ import {
computeHumidiferModeIcon, computeHumidiferModeIcon,
} from "../../../data/humidifier"; } from "../../../data/humidifier";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import "../components/ha-more-info-control-select-container";
import { moreInfoControlStyle } from "../components/ha-more-info-control-style"; import { moreInfoControlStyle } from "../components/ha-more-info-control-style";
import "../components/humidifier/ha-more-info-humidifier-humidity"; import "../components/humidifier/ha-more-info-humidifier-humidity";
@ -91,79 +92,74 @@ class MoreInfoHumidifier extends LitElement {
></ha-more-info-humidifier-humidity> ></ha-more-info-humidifier-humidity>
</div> </div>
<div class="secondary-controls"> <ha-more-info-control-select-container>
<div class="secondary-controls-scroll"> <ha-control-select-menu
<ha-control-select-menu .label=${this.hass.localize("ui.card.humidifier.state")}
.label=${this.hass.localize("ui.card.humidifier.state")} .value=${this.stateObj.state}
.value=${this.stateObj.state} .disabled=${this.stateObj.state === UNAVAILABLE}
.disabled=${this.stateObj.state === UNAVAILABLE} fixedMenuPosition
fixedMenuPosition naturalMenuWidth
naturalMenuWidth @selected=${this._handleStateChanged}
@selected=${this._handleStateChanged} @closed=${stopPropagation}
@closed=${stopPropagation} >
> <ha-svg-icon slot="icon" .path=${mdiPower}></ha-svg-icon>
<ha-svg-icon slot="icon" .path=${mdiPower}></ha-svg-icon> <ha-list-item value="off">
<ha-list-item value="off"> ${computeStateDisplay(
${computeStateDisplay( this.hass.localize,
this.hass.localize, this.stateObj,
this.stateObj, this.hass.locale,
this.hass.locale, this.hass.config,
this.hass.config, this.hass.entities,
this.hass.entities, "off"
"off" )}
)} </ha-list-item>
</ha-list-item> <ha-list-item value="on">
<ha-list-item value="on"> ${computeStateDisplay(
${computeStateDisplay( this.hass.localize,
this.hass.localize, this.stateObj,
this.stateObj, this.hass.locale,
this.hass.locale, this.hass.config,
this.hass.config, this.hass.entities,
this.hass.entities, "on"
"on" )}
)} </ha-list-item>
</ha-list-item> </ha-control-select-menu>
</ha-control-select-menu>
${supportModes ${supportModes
? html` ? html`
<ha-control-select-menu <ha-control-select-menu
.label=${hass.localize("ui.card.humidifier.mode")} .label=${hass.localize("ui.card.humidifier.mode")}
.value=${stateObj.attributes.mode} .value=${stateObj.attributes.mode}
.disabled=${this.stateObj.state === UNAVAILABLE} .disabled=${this.stateObj.state === UNAVAILABLE}
fixedMenuPosition fixedMenuPosition
naturalMenuWidth naturalMenuWidth
@selected=${this._handleModeChanged} @selected=${this._handleModeChanged}
@closed=${stopPropagation} @closed=${stopPropagation}
> >
<ha-svg-icon <ha-svg-icon slot="icon" .path=${mdiTuneVariant}></ha-svg-icon>
slot="icon" ${stateObj.attributes.available_modes!.map(
.path=${mdiTuneVariant} (mode) => html`
></ha-svg-icon> <ha-list-item .value=${mode} graphic="icon">
${stateObj.attributes.available_modes!.map( <ha-svg-icon
(mode) => html` slot="graphic"
<ha-list-item .value=${mode} graphic="icon"> .path=${computeHumidiferModeIcon(mode)}
<ha-svg-icon ></ha-svg-icon>
slot="graphic" ${computeAttributeValueDisplay(
.path=${computeHumidiferModeIcon(mode)} hass.localize,
></ha-svg-icon> stateObj!,
${computeAttributeValueDisplay( hass.locale,
hass.localize, hass.config,
stateObj!, hass.entities,
hass.locale, "mode",
hass.config, mode
hass.entities, )}
"mode", </ha-list-item>
mode `
)} )}
</ha-list-item> </ha-control-select-menu>
` `
)} : nothing}
</ha-control-select-menu> </ha-more-info-control-select-container>
`
: nothing}
</div>
</div>
`; `;
} }

View File

@ -36,6 +36,7 @@ import {
lightSupportsFavoriteColors, lightSupportsFavoriteColors,
} from "../../../data/light"; } from "../../../data/light";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import "../components/ha-more-info-control-select-container";
import { moreInfoControlStyle } from "../components/ha-more-info-control-style"; import { moreInfoControlStyle } from "../components/ha-more-info-control-style";
import "../components/ha-more-info-state-header"; import "../components/ha-more-info-state-header";
import "../components/ha-more-info-toggle"; import "../components/ha-more-info-toggle";
@ -286,39 +287,37 @@ class MoreInfoLight extends LitElement {
: nothing} : nothing}
</div> </div>
<div> <div>
<div class="secondary-controls"> <ha-more-info-control-select-container>
<div class="secondary-controls-scroll"> ${supportsEffects && this.stateObj.attributes.effect_list
${supportsEffects && this.stateObj.attributes.effect_list ? html`
? html` <ha-control-select-menu
<ha-control-select-menu .label=${this.hass.formatEntityAttributeName(
.label=${this.hass.formatEntityAttributeName( this.stateObj,
this.stateObj, "effect"
"effect" )}
)} .value=${this.stateObj.attributes.effect}
.value=${this.stateObj.attributes.effect} .disabled=${this.stateObj.state === UNAVAILABLE}
.disabled=${this.stateObj.state === UNAVAILABLE} fixedMenuPosition
fixedMenuPosition naturalMenuWidth
naturalMenuWidth @selected=${this._handleEffect}
@selected=${this._handleEffect} @closed=${stopPropagation}
@closed=${stopPropagation} >
> <ha-svg-icon slot="icon" .path=${mdiCreation}></ha-svg-icon>
<ha-svg-icon slot="icon" .path=${mdiCreation}></ha-svg-icon> ${this.stateObj.attributes.effect_list?.map(
${this.stateObj.attributes.effect_list?.map( (mode) => html`
(mode) => html` <ha-list-item .value=${mode}>
<ha-list-item .value=${mode}> ${this.hass.formatEntityAttributeValue(
${this.hass.formatEntityAttributeValue( this.stateObj!,
this.stateObj!, "effect",
"effect", mode
mode )}
)} </ha-list-item>
</ha-list-item> `
` )}
)} </ha-control-select-menu>
</ha-control-select-menu> `
` : nothing}
: nothing} </ha-more-info-control-select-container>
</div>
</div>
<ha-attributes <ha-attributes
.hass=${this.hass} .hass=${this.hass}
.stateObj=${this.stateObj} .stateObj=${this.stateObj}

View File

@ -13,6 +13,7 @@ import {
computeOperationModeIcon, computeOperationModeIcon,
} from "../../../data/water_heater"; } from "../../../data/water_heater";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import "../components/ha-more-info-control-select-container";
import { moreInfoControlStyle } from "../components/ha-more-info-control-style"; import { moreInfoControlStyle } from "../components/ha-more-info-control-style";
import "../components/water_heater/ha-more-info-water_heater-temperature"; import "../components/water_heater/ha-more-info-water_heater-temperature";
@ -68,77 +69,69 @@ class MoreInfoWaterHeater extends LitElement {
.stateObj=${this.stateObj} .stateObj=${this.stateObj}
></ha-more-info-water_heater-temperature> ></ha-more-info-water_heater-temperature>
</div> </div>
<div class="secondary-controls"> <ha-more-info-control-select-container>
<div class="secondary-controls-scroll"> ${supportOperationMode && stateObj.attributes.operation_list
${supportOperationMode && stateObj.attributes.operation_list ? html`
? html` <ha-control-select-menu
<ha-control-select-menu .label=${this.hass.formatEntityAttributeName(
.label=${this.hass.formatEntityAttributeName( stateObj,
stateObj, "operation"
"operation" )}
.value=${stateObj.state}
.disabled=${stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleOperationModeChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiWaterBoiler}></ha-svg-icon>
${stateObj.attributes.operation_list
.concat()
.sort(compareWaterHeaterOperationMode)
.map(
(mode) => html`
<ha-list-item .value=${mode} graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${computeOperationModeIcon(mode)}
></ha-svg-icon>
${this.hass.formatEntityState(stateObj, mode)}
</ha-list-item>
`
)} )}
.value=${stateObj.state} </ha-control-select-menu>
.disabled=${stateObj.state === UNAVAILABLE} `
fixedMenuPosition : nothing}
naturalMenuWidth ${supportAwayMode
@selected=${this._handleOperationModeChanged} ? html`
@closed=${stopPropagation} <ha-control-select-menu
> .label=${this.hass.formatEntityAttributeName(
stateObj,
"away_mode"
)}
.value=${stateObj.attributes.away_mode}
.disabled=${stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleAwayModeChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiAccount}></ha-svg-icon>
<ha-list-item value="on" graphic="icon">
<ha-svg-icon <ha-svg-icon
slot="icon" slot="graphic"
.path=${mdiWaterBoiler} .path=${mdiAccountArrowRight}
></ha-svg-icon> ></ha-svg-icon>
${stateObj.attributes.operation_list ${this.hass.localize("state.default.on")}
.concat() </ha-list-item>
.sort(compareWaterHeaterOperationMode) <ha-list-item value="off" graphic="icon">
.map( <ha-svg-icon slot="graphic" .path=${mdiAccount}></ha-svg-icon>
(mode) => html` ${this.hass.localize("state.default.off")}
<ha-list-item .value=${mode} graphic="icon"> </ha-list-item>
<ha-svg-icon </ha-control-select-menu>
slot="graphic" `
.path=${computeOperationModeIcon(mode)} : nothing}
></ha-svg-icon> </ha-more-info-control-select-container>
${this.hass.formatEntityState(stateObj, mode)}
</ha-list-item>
`
)}
</ha-control-select-menu>
`
: nothing}
${supportAwayMode
? html`
<ha-control-select-menu
.label=${this.hass.formatEntityAttributeName(
stateObj,
"away_mode"
)}
.value=${stateObj.attributes.away_mode}
.disabled=${stateObj.state === UNAVAILABLE}
fixedMenuPosition
naturalMenuWidth
@selected=${this._handleAwayModeChanged}
@closed=${stopPropagation}
>
<ha-svg-icon slot="icon" .path=${mdiAccount}></ha-svg-icon>
<ha-list-item value="on" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${mdiAccountArrowRight}
></ha-svg-icon>
${this.hass.localize("state.default.on")}
</ha-list-item>
<ha-list-item value="off" graphic="icon">
<ha-svg-icon
slot="graphic"
.path=${mdiAccount}
></ha-svg-icon>
${this.hass.localize("state.default.off")}
</ha-list-item>
</ha-control-select-menu>
`
: nothing}
</div>
</div>
`; `;
} }