Fix pointer/more-info inconsistencies for entity rows (#10025)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Philip Allgaier 2021-12-02 10:48:30 +01:00 committed by GitHub
parent acf4d59fde
commit cf062bf0f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 203 additions and 255 deletions

View File

@ -188,8 +188,9 @@ export const DOMAINS_WITH_MORE_INFO = [
"weather", "weather",
]; ];
/** Domains that show no more info dialog. */ /** Domains that do not show the default more info dialog content (e.g. the attribute section)
export const DOMAINS_HIDE_MORE_INFO = [ * and do not have a separate more info (so not in DOMAINS_WITH_MORE_INFO). */
export const DOMAINS_HIDE_DEFAULT_MORE_INFO = [
"input_number", "input_number",
"input_select", "input_select",
"input_text", "input_text",
@ -198,6 +199,30 @@ export const DOMAINS_HIDE_MORE_INFO = [
"select", "select",
]; ];
/** Domains that render an input element instead of a text value when rendered in a row.
* Those rows should then not show a cursor pointer when hovered (which would normally
* be the default) unless the element itself enforces it (e.g. a button). Also those elements
* should not act as a click target to open the more info dialog (the row name and state icon
* still do of course) as the click might instead e.g. activate the input field that this row shows.
*/
export const DOMAINS_INPUT_ROW = [
"cover",
"fan",
"humidifier",
"input_boolean",
"input_datetime",
"input_number",
"input_select",
"input_text",
"light",
"lock",
"media_player",
"number",
"scene",
"script",
"select",
];
/** Domains that should have the history hidden in the more info dialog. */ /** Domains that should have the history hidden in the more info dialog. */
export const DOMAINS_MORE_INFO_NO_HISTORY = ["camera", "configurator", "scene"]; export const DOMAINS_MORE_INFO_NO_HISTORY = ["camera", "configurator", "scene"];

View File

@ -1,6 +1,6 @@
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import { import {
DOMAINS_HIDE_MORE_INFO, DOMAINS_HIDE_DEFAULT_MORE_INFO,
DOMAINS_WITH_MORE_INFO, DOMAINS_WITH_MORE_INFO,
} from "../../common/const"; } from "../../common/const";
import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../common/entity/compute_state_domain";
@ -40,7 +40,7 @@ export const domainMoreInfoType = (domain: string): string => {
if (DOMAINS_WITH_MORE_INFO.includes(domain)) { if (DOMAINS_WITH_MORE_INFO.includes(domain)) {
return domain; return domain;
} }
if (DOMAINS_HIDE_MORE_INFO.includes(domain)) { if (DOMAINS_HIDE_DEFAULT_MORE_INFO.includes(domain)) {
return "hidden"; return "hidden";
} }
return "default"; return "default";

View File

@ -9,7 +9,7 @@ import {
import { property } from "lit/decorators"; import { property } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined"; import { ifDefined } from "lit/directives/if-defined";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const"; import { DOMAINS_INPUT_ROW } from "../../../common/const";
import { toggleAttribute } from "../../../common/dom/toggle_attribute"; import { toggleAttribute } from "../../../common/dom/toggle_attribute";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
@ -31,6 +31,8 @@ class HuiGenericEntityRow extends LitElement {
@property() public secondaryText?: string; @property() public secondaryText?: string;
@property({ type: Boolean }) public hideName = false;
protected render(): TemplateResult { protected render(): TemplateResult {
if (!this.hass || !this.config) { if (!this.hass || !this.config) {
return html``; return html``;
@ -47,10 +49,10 @@ class HuiGenericEntityRow extends LitElement {
`; `;
} }
const pointer = const domain = computeDomain(this.config.entity);
(this.config.tap_action && this.config.tap_action.action !== "none") || const pointer = !(
(this.config.entity && this.config.tap_action && this.config.tap_action.action !== "none"
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this.config.entity))); );
const hasSecondary = this.secondaryText || this.config.secondary_info; const hasSecondary = this.secondaryText || this.config.secondary_info;
const name = this.config.name ?? computeStateName(stateObj); const name = this.config.name ?? computeStateName(stateObj);
@ -72,7 +74,8 @@ class HuiGenericEntityRow extends LitElement {
})} })}
tabindex=${ifDefined(pointer ? "0" : undefined)} tabindex=${ifDefined(pointer ? "0" : undefined)}
></state-badge> ></state-badge>
<div ${!this.hideName
? html` <div
class="info ${classMap({ class="info ${classMap({
pointer, pointer,
"text-content": !hasSecondary, "text-content": !hasSecondary,
@ -84,7 +87,7 @@ class HuiGenericEntityRow extends LitElement {
})} })}
.title=${name} .title=${name}
> >
${name} ${this.config.name || computeStateName(stateObj)}
${hasSecondary ${hasSecondary
? html` ? html`
<div class="secondary"> <div class="secondary">
@ -126,9 +129,9 @@ class HuiGenericEntityRow extends LitElement {
}` }`
: this.config.secondary_info === "tilt-position" && : this.config.secondary_info === "tilt-position" &&
stateObj.attributes.current_tilt_position !== undefined stateObj.attributes.current_tilt_position !== undefined
? `${this.hass.localize("ui.card.cover.tilt_position")}: ${ ? `${this.hass.localize(
stateObj.attributes.current_tilt_position "ui.card.cover.tilt_position"
}` )}: ${stateObj.attributes.current_tilt_position}`
: this.config.secondary_info === "brightness" && : this.config.secondary_info === "brightness" &&
stateObj.attributes.brightness stateObj.attributes.brightness
? html`${Math.round( ? html`${Math.round(
@ -139,8 +142,22 @@ class HuiGenericEntityRow extends LitElement {
</div> </div>
` `
: ""} : ""}
</div> </div>`
: html``}
${!DOMAINS_INPUT_ROW.includes(domain)
? html` <div
class="text-content ${classMap({
pointer,
})}"
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this.config!.hold_action),
hasDoubleClick: hasAction(this.config!.double_tap_action),
})}
>
<slot></slot> <slot></slot>
</div>`
: html`<slot></slot>`}
`; `;
} }

View File

@ -49,10 +49,8 @@ class HuiClimateEntityRow extends LitElement implements LovelaceRow {
return html` return html`
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}> <hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
<ha-climate-state <ha-climate-state .hass=${this.hass} .stateObj=${stateObj}>
.hass=${this.hass} </ha-climate-state>
.stateObj=${stateObj}
></ha-climate-state>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }

View File

@ -132,7 +132,6 @@ class HuiInputNumberEntityRow extends LitElement implements LovelaceRow {
return css` return css`
:host { :host {
display: block; display: block;
cursor: pointer;
} }
.flex { .flex {
display: flex; display: flex;

View File

@ -9,11 +9,7 @@ import {
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { stopPropagation } from "../../../common/dom/stop_propagation"; import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "../../../components/ha-paper-dropdown-menu"; import "../../../components/ha-paper-dropdown-menu";
@ -23,13 +19,10 @@ import {
InputSelectEntity, InputSelectEntity,
setInputSelectOption, setInputSelectOption,
} from "../../../data/input_select"; } from "../../../data/input_select";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntitiesCardEntityConfig } from "../cards/types"; import { EntitiesCardEntityConfig } from "../cards/types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning"; import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceRow } from "./types"; import { LovelaceRow } from "./types";
@ -68,27 +61,12 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
`; `;
} }
const pointer =
(this._config.tap_action && this._config.tap_action.action !== "none") ||
(this._config.entity &&
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this._config.entity)));
return html` return html`
<state-badge <hui-generic-entity-row
.stateObj=${stateObj} .hass=${this.hass}
.stateColor=${this._config.state_color} .config=${this._config}
.overrideIcon=${this._config.icon} hideName
.overrideImage=${this._config.image} >
class=${classMap({
pointer,
})}
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config!.hold_action),
hasDoubleClick: hasAction(this._config!.double_tap_action),
})}
tabindex=${ifDefined(pointer ? "0" : undefined)}
></state-badge>
<ha-paper-dropdown-menu <ha-paper-dropdown-menu
.label=${this._config.name || computeStateName(stateObj)} .label=${this._config.name || computeStateName(stateObj)}
.value=${stateObj.state} .value=${stateObj.state}
@ -104,6 +82,7 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
: ""} : ""}
</paper-listbox> </paper-listbox>
</ha-paper-dropdown-menu> </ha-paper-dropdown-menu>
</hui-generic-entity-row>
`; `;
} }
@ -129,10 +108,6 @@ class HuiInputSelectEntityRow extends LitElement implements LovelaceRow {
} }
} }
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action!);
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return css` return css`
:host { :host {

View File

@ -1,12 +1,5 @@
import { PaperInputElement } from "@polymer/paper-input/paper-input"; import { PaperInputElement } from "@polymer/paper-input/paper-input";
import { import { html, LitElement, PropertyValues, TemplateResult } from "lit";
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
import { setValue } from "../../../data/input_text"; import { setValue } from "../../../data/input_text";
@ -80,14 +73,6 @@ class HuiInputTextEntityRow extends LitElement implements LovelaceRow {
ev.target.blur(); ev.target.blur();
} }
static get styles(): CSSResultGroup {
return css`
:host {
cursor: pointer;
}
`;
}
} }
declare global { declare global {

View File

@ -9,24 +9,17 @@ import {
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { stopPropagation } from "../../../common/dom/stop_propagation"; import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "../../../components/ha-paper-dropdown-menu"; import "../../../components/ha-paper-dropdown-menu";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
import { forwardHaptic } from "../../../data/haptics"; import { forwardHaptic } from "../../../data/haptics";
import { SelectEntity, setSelectOption } from "../../../data/select"; import { SelectEntity, setSelectOption } from "../../../data/select";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntitiesCardEntityConfig } from "../cards/types"; import { EntitiesCardEntityConfig } from "../cards/types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning"; import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceRow } from "./types"; import { LovelaceRow } from "./types";
@ -65,26 +58,12 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
`; `;
} }
const pointer =
(this._config.tap_action && this._config.tap_action.action !== "none") ||
(this._config.entity &&
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this._config.entity)));
return html` return html`
<state-badge <hui-generic-entity-row
.stateObj=${stateObj} .hass=${this.hass}
.overrideIcon=${this._config.icon} .config=${this._config}
.overrideImage=${this._config.image} hideName
class=${classMap({ >
pointer,
})}
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config!.hold_action),
hasDoubleClick: hasAction(this._config!.double_tap_action),
})}
tabindex=${ifDefined(pointer ? "0" : undefined)}
></state-badge>
<ha-paper-dropdown-menu <ha-paper-dropdown-menu
.label=${this._config.name || computeStateName(stateObj)} .label=${this._config.name || computeStateName(stateObj)}
.disabled=${stateObj.state === UNAVAILABLE} .disabled=${stateObj.state === UNAVAILABLE}
@ -111,6 +90,7 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
: ""} : ""}
</paper-listbox> </paper-listbox>
</ha-paper-dropdown-menu> </ha-paper-dropdown-menu>
</hui-generic-entity-row>
`; `;
} }
@ -136,10 +116,6 @@ class HuiSelectEntityRow extends LitElement implements LovelaceRow {
} }
} }
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action!);
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return css` return css`
:host { :host {

View File

@ -7,16 +7,9 @@ import {
TemplateResult, TemplateResult,
} from "lit"; } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { EntitiesCardEntityConfig } from "../cards/types"; import { EntitiesCardEntityConfig } from "../cards/types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { handleAction } from "../common/handle-action";
import { hasAction } from "../common/has-action";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row"; import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning"; import { createEntityNotFoundWarning } from "../components/hui-warning";
@ -54,37 +47,13 @@ class HuiTextEntityRow extends LitElement implements LovelaceRow {
`; `;
} }
const pointer =
(this._config.tap_action && this._config.tap_action.action !== "none") ||
(this._config.entity &&
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this._config.entity)));
return html` return html`
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}> <hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
<div ${computeStateDisplay(this.hass!.localize, stateObj, this.hass.locale)}
class="text-content ${classMap({
pointer,
})}"
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config.hold_action),
hasDoubleClick: hasAction(this._config.double_tap_action),
})}
>
${computeStateDisplay(
this.hass!.localize,
stateObj,
this.hass.locale
)}
</div>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action);
}
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return css` return css`
div { div {

View File

@ -9,8 +9,6 @@ import {
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined"; import { ifDefined } from "lit/directives/if-defined";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { formatNumber } from "../../../common/number/format_number"; import { formatNumber } from "../../../common/number/format_number";
@ -67,10 +65,9 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
`; `;
} }
const pointer = const pointer = !(
(this._config.tap_action && this._config.tap_action.action !== "none") || this._config.tap_action && this._config.tap_action.action !== "none"
(this._config.entity && );
!DOMAINS_HIDE_MORE_INFO.includes(computeDomain(this._config.entity)));
const weatherStateIcon = getWeatherStateIcon(stateObj.state, this); const weatherStateIcon = getWeatherStateIcon(stateObj.state, this);
@ -106,7 +103,16 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
> >
${this._config.name || computeStateName(stateObj)} ${this._config.name || computeStateName(stateObj)}
</div> </div>
<div class="attributes"> <div
class="attributes ${classMap({
pointer,
})}"
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config!.hold_action),
hasDoubleClick: hasAction(this._config!.double_tap_action),
})}
>
<div> <div>
${UNAVAILABLE_STATES.includes(stateObj.state) ${UNAVAILABLE_STATES.includes(stateObj.state)
? computeStateDisplay( ? computeStateDisplay(

View File

@ -63,7 +63,6 @@ class HuiAttributeRow extends LitElement implements LovelaceRow {
return html` return html`
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}> <hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
<div>
${this._config.prefix} ${this._config.prefix}
${this._config.format && checkValidDate(date) ${this._config.format && checkValidDate(date)
? html` <hui-timestamp-display ? html` <hui-timestamp-display
@ -78,7 +77,6 @@ class HuiAttributeRow extends LitElement implements LovelaceRow {
? formatAttributeValue(this.hass, attribute) ? formatAttributeValue(this.hass, attribute)
: "-"} : "-"}
${this._config.suffix} ${this._config.suffix}
</div>
</hui-generic-entity-row> </hui-generic-entity-row>
`; `;
} }