Some fixes in focus and click handling (#5847)

This commit is contained in:
Bram Kragten 2020-05-13 12:47:09 +02:00 committed by GitHub
parent 7f1fb6f75f
commit cc46797576
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 63 deletions

View File

@ -1,4 +1,5 @@
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import { styleMap } from "lit-html/directives/style-map";
import { import {
css, css,
CSSResult, CSSResult,
@ -6,7 +7,6 @@ import {
LitElement, LitElement,
property, property,
PropertyValues, PropertyValues,
query,
TemplateResult, TemplateResult,
} from "lit-element"; } from "lit-element";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
@ -16,7 +16,6 @@ import { stateIcon } from "../../common/entity/state_icon";
import { iconColorCSS } from "../../common/style/icon_color_css"; import { iconColorCSS } from "../../common/style/icon_color_css";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import "../ha-icon"; import "../ha-icon";
import type { HaIcon } from "../ha-icon";
export class StateBadge extends LitElement { export class StateBadge extends LitElement {
public hass?: HomeAssistant; public hass?: HomeAssistant;
@ -29,12 +28,15 @@ export class StateBadge extends LitElement {
@property({ type: Boolean }) public stateColor?: boolean; @property({ type: Boolean }) public stateColor?: boolean;
@query("ha-icon") private _icon!: HaIcon; @property({ type: Boolean, reflect: true, attribute: "icon" })
private _showIcon = true;
@property() private _iconStyle: { [name: string]: string } = {};
protected render(): TemplateResult { protected render(): TemplateResult {
const stateObj = this.stateObj; const stateObj = this.stateObj;
if (!stateObj) { if (!stateObj || !this._showIcon) {
return html``; return html``;
} }
@ -42,7 +44,7 @@ export class StateBadge extends LitElement {
return html` return html`
<ha-icon <ha-icon
id="icon" style=${styleMap(this._iconStyle)}
data-domain=${ifDefined( data-domain=${ifDefined(
this.stateColor || (domain === "light" && this.stateColor !== false) this.stateColor || (domain === "light" && this.stateColor !== false)
? domain ? domain
@ -60,14 +62,13 @@ export class StateBadge extends LitElement {
} }
const stateObj = this.stateObj; const stateObj = this.stateObj;
const iconStyle: Partial<CSSStyleDeclaration> = { const iconStyle: { [name: string]: string } = {};
color: "",
filter: "",
display: "",
};
const hostStyle: Partial<CSSStyleDeclaration> = { const hostStyle: Partial<CSSStyleDeclaration> = {
backgroundImage: "", backgroundImage: "",
}; };
this._showIcon = true;
if (stateObj) { if (stateObj) {
// hide icon if we have entity picture // hide icon if we have entity picture
if ( if (
@ -79,7 +80,7 @@ export class StateBadge extends LitElement {
imageUrl = this.hass.hassUrl(imageUrl); imageUrl = this.hass.hassUrl(imageUrl);
} }
hostStyle.backgroundImage = `url(${imageUrl})`; hostStyle.backgroundImage = `url(${imageUrl})`;
iconStyle.display = "none"; this._showIcon = false;
} else if (stateObj.state === "on") { } else if (stateObj.state === "on") {
if (stateObj.attributes.hs_color && this.stateColor !== false) { if (stateObj.attributes.hs_color && this.stateColor !== false) {
const hue = stateObj.attributes.hs_color[0]; const hue = stateObj.attributes.hs_color[0];
@ -102,7 +103,7 @@ export class StateBadge extends LitElement {
} }
} }
} }
Object.assign(this._icon.style, iconStyle); this._iconStyle = iconStyle;
Object.assign(this.style, hostStyle); Object.assign(this.style, hostStyle);
} }
@ -119,8 +120,17 @@ export class StateBadge extends LitElement {
background-size: cover; background-size: cover;
line-height: 40px; line-height: 40px;
vertical-align: middle; vertical-align: middle;
box-sizing: border-box;
}
:host(:focus) {
outline: none;
}
:host(:not([icon]):focus) {
border: 2px solid var(--divider-color);
}
:host([icon]:focus) {
background: var(--divider-color);
} }
ha-icon { ha-icon {
transition: color 0.3s ease-in-out, filter 0.3s ease-in-out; transition: color 0.3s ease-in-out, filter 0.3s ease-in-out;
} }

View File

@ -18,7 +18,6 @@ import "../../../components/ha-card";
import "../../../components/ha-icon"; import "../../../components/ha-icon";
import { UNAVAILABLE_STATES } from "../../../data/entity"; import { UNAVAILABLE_STATES } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { findEntities } from "../common/find-entites"; import { findEntities } from "../common/find-entites";
import { hasConfigOrEntityChanged } from "../common/has-changed"; import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-warning"; import "../components/hui-warning";
@ -108,46 +107,40 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
: !UNAVAILABLE_STATES.includes(stateObj.state); : !UNAVAILABLE_STATES.includes(stateObj.state);
return html` return html`
<ha-card> <ha-card @click=${this._handleClick} tabindex="0">
<div <div class="header">
@action=${this._handleClick} <div class="name">
.actionHandler=${actionHandler()} ${this._config.name || computeStateName(stateObj)}
tabindex="0"
>
<div class="header">
<div class="name">
${this._config.name || computeStateName(stateObj)}
</div>
<div class="icon">
<ha-icon
.icon=${this._config.icon || stateIcon(stateObj)}
></ha-icon>
</div>
</div> </div>
<div class="info"> <div class="icon">
<span class="value" <ha-icon
>${"attribute" in this._config .icon=${this._config.icon || stateIcon(stateObj)}
? stateObj.attributes[this._config.attribute!] || ></ha-icon>
this.hass.localize("state.default.unknown")
: stateObj.attributes.unit_of_measurement
? stateObj.state
: computeStateDisplay(
this.hass.localize,
stateObj,
this.hass.language
)}</span
>${showUnit
? html`
<span class="measurement"
>${this._config.unit ||
(this._config.attribute
? ""
: stateObj.attributes.unit_of_measurement)}</span
>
`
: ""}
</div> </div>
</div> </div>
<div class="info">
<span class="value"
>${"attribute" in this._config
? stateObj.attributes[this._config.attribute!] ||
this.hass.localize("state.default.unknown")
: stateObj.attributes.unit_of_measurement
? stateObj.state
: computeStateDisplay(
this.hass.localize,
stateObj,
this.hass.language
)}</span
>${showUnit
? html`
<span class="measurement"
>${this._config.unit ||
(this._config.attribute
? ""
: stateObj.attributes.unit_of_measurement)}</span
>
`
: ""}
</div>
${this._footerElement} ${this._footerElement}
</ha-card> </ha-card>
`; `;
@ -194,9 +187,8 @@ export class HuiEntityCard extends LitElement implements LovelaceCard {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
}
ha-card > div {
cursor: pointer; cursor: pointer;
outline: none;
} }
.header { .header {

View File

@ -327,6 +327,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
ha-card { ha-card {
cursor: pointer; cursor: pointer;
padding: 16px; padding: 16px;
outline: none;
} }
.content { .content {

View File

@ -184,11 +184,6 @@ class HuiGenericEntityRow extends LitElement {
state-badge { state-badge {
flex: 0 0 40px; flex: 0 0 40px;
} }
state-badge:focus {
outline: none;
background: var(--divider-color);
border-radius: 100%;
}
:host([rtl]) .flex { :host([rtl]) .flex {
margin-left: 0; margin-left: 0;
margin-right: 16px; margin-right: 16px;

View File

@ -13,15 +13,23 @@ import { HomeAssistant } from "../../../types";
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 "../components/hui-warning"; import "../components/hui-warning";
import { EntityConfig, LovelaceRow } from "./types"; import { LovelaceRow } from "./types";
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
import { computeDomain } from "../../../common/entity/compute_domain";
import { actionHandler } from "../common/directives/action-handler-directive";
import { hasAction } from "../common/has-action";
import { ActionHandlerEvent } from "../../../data/lovelace";
import { handleAction } from "../common/handle-action";
import { classMap } from "lit-html/directives/class-map";
import { EntitiesCardEntityConfig } from "../cards/types";
@customElement("hui-text-entity-row") @customElement("hui-text-entity-row")
class HuiTextEntityRow extends LitElement implements LovelaceRow { class HuiTextEntityRow extends LitElement implements LovelaceRow {
@property() public hass?: HomeAssistant; @property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig; @property() private _config?: EntitiesCardEntityConfig;
public setConfig(config: EntityConfig): void { public setConfig(config: EntitiesCardEntityConfig): void {
if (!config) { if (!config) {
throw new Error("Configuration error"); throw new Error("Configuration error");
} }
@ -51,9 +59,23 @@ 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 class="text-content"> <div
class="text-content ${classMap({
pointer,
})}"
@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config.hold_action),
hasDoubleClick: hasAction(this._config.double_tap_action),
})}
>
${computeStateDisplay( ${computeStateDisplay(
this.hass!.localize, this.hass!.localize,
stateObj, stateObj,
@ -64,11 +86,18 @@ class HuiTextEntityRow extends LitElement implements LovelaceRow {
`; `;
} }
private _handleAction(ev: ActionHandlerEvent) {
handleAction(this, this.hass!, this._config!, ev.detail.action);
}
static get styles(): CSSResult { static get styles(): CSSResult {
return css` return css`
div { div {
text-align: right; text-align: right;
} }
.pointer {
cursor: pointer;
}
`; `;
} }
} }

View File

@ -81,7 +81,7 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
return html` return html`
<div <div
class="icon-image${classMap({ class="icon-image ${classMap({
pointer, pointer,
})}" })}"
@action=${this._handleAction} @action=${this._handleAction}
@ -165,6 +165,12 @@ class HuiWeatherEntityRow extends LitElement implements LovelaceRow {
height: 40px; height: 40px;
} }
.icon-image:focus {
outline: none;
background-color: var(--divider-color);
border-radius: 50%;
}
.weather-icon { .weather-icon {
--iron-icon-width: 40px; --iron-icon-width: 40px;
--iron-icon-height: 40px; --iron-icon-height: 40px;