Add dark mode toggle to gallery cards (#7532)

This commit is contained in:
Bram Kragten 2020-11-02 10:46:52 +01:00 committed by GitHub
parent 57500f6c97
commit da12233ade
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 131 additions and 129 deletions

View File

@ -5,11 +5,16 @@ import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../src/components/ha-switch";
import "../../../src/components/ha-formfield";
import "./demo-card";
import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element";
class DemoCards extends PolymerElement {
static get template() {
return html`
<style>
#container {
min-height: calc(100vh - 128px);
background: var(--primary-background-color);
}
.cards {
display: flex;
flex-wrap: wrap;
@ -24,6 +29,9 @@ class DemoCards extends PolymerElement {
.filters {
margin-left: 60px;
}
ha-formfield {
margin-right: 16px;
}
</style>
<app-toolbar>
<div class="filters">
@ -31,16 +39,21 @@ class DemoCards extends PolymerElement {
<ha-switch checked="[[_showConfig]]" on-change="_showConfigToggled">
</ha-switch>
</ha-formfield>
<ha-formfield label="Dark theme">
<ha-switch on-change="_darkThemeToggled"> </ha-switch>
</ha-formfield>
</div>
</app-toolbar>
<div class="cards">
<template is="dom-repeat" items="[[configs]]">
<demo-card
config="[[item]]"
show-config="[[_showConfig]]"
hass="[[hass]]"
></demo-card>
</template>
<div id="container">
<div class="cards">
<template is="dom-repeat" items="[[configs]]">
<demo-card
config="[[item]]"
show-config="[[_showConfig]]"
hass="[[hass]]"
></demo-card>
</template>
</div>
</div>
`;
}
@ -59,6 +72,12 @@ class DemoCards extends PolymerElement {
_showConfigToggled(ev) {
this._showConfig = ev.target.checked;
}
_darkThemeToggled(ev) {
applyThemesOnElement(this.$.container, { themes: {} }, "default", {
dark: ev.target.checked,
});
}
}
customElements.define("demo-cards", DemoCards);

View File

@ -3,7 +3,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "../../../src/components/ha-card";
import "../../../src/state-summary/state-card-content";
import "./more-info-content";
import "../../../src/dialogs/more-info/more-info-content";
class DemoMoreInfo extends PolymerElement {
static get template() {
@ -16,15 +16,12 @@ class DemoMoreInfo extends PolymerElement {
ha-card {
width: 333px;
padding: 20px 24px;
}
state-card-content {
display: block;
padding: 16px;
}
more-info-content {
padding: 0 16px;
margin-bottom: 16px;
}
pre {

View File

@ -1,73 +0,0 @@
import { HassEntity } from "home-assistant-js-websocket";
import { property, PropertyValues, UpdatingElement } from "lit-element";
import dynamicContentUpdater from "../../../src/common/dom/dynamic_content_updater";
import { stateMoreInfoType } from "../../../src/dialogs/more-info/state_more_info_control";
import "../../../src/dialogs/more-info/controls/more-info-alarm_control_panel";
import "../../../src/dialogs/more-info/controls/more-info-automation";
import "../../../src/dialogs/more-info/controls/more-info-camera";
import "../../../src/dialogs/more-info/controls/more-info-climate";
import "../../../src/dialogs/more-info/controls/more-info-configurator";
import "../../../src/dialogs/more-info/controls/more-info-counter";
import "../../../src/dialogs/more-info/controls/more-info-cover";
import "../../../src/dialogs/more-info/controls/more-info-default";
import "../../../src/dialogs/more-info/controls/more-info-fan";
import "../../../src/dialogs/more-info/controls/more-info-group";
import "../../../src/dialogs/more-info/controls/more-info-humidifier";
import "../../../src/dialogs/more-info/controls/more-info-input_datetime";
import "../../../src/dialogs/more-info/controls/more-info-light";
import "../../../src/dialogs/more-info/controls/more-info-lock";
import "../../../src/dialogs/more-info/controls/more-info-media_player";
import "../../../src/dialogs/more-info/controls/more-info-person";
import "../../../src/dialogs/more-info/controls/more-info-script";
import "../../../src/dialogs/more-info/controls/more-info-sun";
import "../../../src/dialogs/more-info/controls/more-info-timer";
import "../../../src/dialogs/more-info/controls/more-info-vacuum";
import "../../../src/dialogs/more-info/controls/more-info-water_heater";
import "../../../src/dialogs/more-info/controls/more-info-weather";
import { HomeAssistant } from "../../../src/types";
class MoreInfoContent extends UpdatingElement {
@property({ attribute: false }) public hass?: HomeAssistant;
@property() public stateObj?: HassEntity;
private _detachedChild?: ChildNode;
protected firstUpdated(): void {
this.style.position = "relative";
this.style.display = "block";
}
// This is not a lit element, but an updating element, so we implement update
protected update(changedProps: PropertyValues): void {
super.update(changedProps);
const stateObj = this.stateObj;
const hass = this.hass;
if (!stateObj || !hass) {
if (this.lastChild) {
this._detachedChild = this.lastChild;
// Detach child to prevent it from doing work.
this.removeChild(this.lastChild);
}
return;
}
if (this._detachedChild) {
this.appendChild(this._detachedChild);
this._detachedChild = undefined;
}
const moreInfoType =
stateObj.attributes && "custom_ui_more_info" in stateObj.attributes
? stateObj.attributes.custom_ui_more_info
: "more-info-" + stateMoreInfoType(stateObj);
dynamicContentUpdater(this, moreInfoType.toUpperCase(), {
hass,
stateObj,
});
}
}
customElements.define("more-info-content", MoreInfoContent);

View File

@ -15,6 +15,10 @@ const ENTITIES = [
getEntity("alarm_control_panel", "unavailable", "unavailable", {
friendly_name: "Alarm",
}),
getEntity("alarm_control_panel", "alarm_code", "disarmed", {
friendly_name: "Alarm",
code_format: "number",
}),
];
const CONFIGS = [
@ -30,7 +34,14 @@ const CONFIGS = [
config: `
- type: alarm-panel
entity: alarm_control_panel.alarm_armed
title: My Alarm
name: My Alarm
`,
},
{
heading: "Code Example",
config: `
- type: alarm-panel
entity: alarm_control_panel.alarm_code
`,
},
{
@ -83,8 +94,12 @@ class DemoAlarmPanelEntity extends PolymerElement {
public ready() {
super.ready();
this._setupDemo();
}
private async _setupDemo() {
const hass = provideHass(this.$.demos);
hass.updateTranslations(null, "en");
await hass.updateTranslations(null, "en");
hass.addEntities(ENTITIES);
}
}

View File

@ -98,4 +98,4 @@ class DemoButtonEntity extends PolymerElement {
}
}
customElements.define("demo-hui-button-card", DemoButtonEntity);
customElements.define("demo-hui-entity-button-card", DemoButtonEntity);

View File

@ -6,7 +6,7 @@ import { SUPPORT_BRIGHTNESS } from "../../../src/data/light";
import { getEntity } from "../../../src/fake_data/entity";
import { provideHass } from "../../../src/fake_data/provide_hass";
import "../components/demo-more-infos";
import "../components/more-info-content";
import "../../../src/dialogs/more-info/more-info-content";
const ENTITIES = [
getEntity("light", "bed_light", "on", {
@ -40,8 +40,12 @@ class DemoMoreInfoLight extends PolymerElement {
public ready() {
super.ready();
this._setupDemo();
}
private async _setupDemo() {
const hass = provideHass(this);
hass.updateTranslations(null, "en");
await hass.updateTranslations(null, "en");
hass.addEntities(ENTITIES);
}
}

View File

@ -17,14 +17,10 @@ import {
DOMAINS_MORE_INFO_NO_HISTORY,
DOMAINS_WITH_MORE_INFO,
} from "../../common/const";
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../common/dom/fire_event";
import { computeDomain } from "../../common/entity/compute_domain";
import { computeStateName } from "../../common/entity/compute_state_name";
import {
stateMoreInfoType,
importMoreInfoControl,
} from "./state_more_info_control";
import { navigate } from "../../common/navigate";
import "../../components/ha-dialog";
import "../../components/ha-header-bar";
@ -39,6 +35,7 @@ import "./ha-more-info-history";
import "./ha-more-info-logbook";
import "./controls/more-info-default";
import { CONTINUOUS_DOMAINS } from "../../data/logbook";
import "./more-info-content";
const DOMAINS_NO_INFO = ["camera", "configurator"];
/**
@ -63,8 +60,6 @@ export class MoreInfoDialog extends LitElement {
@internalProperty() private _entityId?: string | null;
@internalProperty() private _moreInfoType?: string;
@internalProperty() private _currTabIndex = 0;
public showDialog(params: MoreInfoDialogParams) {
@ -74,18 +69,6 @@ export class MoreInfoDialog extends LitElement {
return;
}
this.large = false;
const stateObj = this.hass.states[this._entityId];
if (!stateObj) {
return;
}
if (stateObj.attributes && "custom_ui_more_info" in stateObj.attributes) {
this._moreInfoType = stateObj.attributes.custom_ui_more_info;
} else {
const type = stateMoreInfoType(stateObj);
importMoreInfoControl(type);
this._moreInfoType = type === "hidden" ? undefined : `more-info-${type}`;
}
}
public closeDialog() {
@ -218,12 +201,10 @@ export class MoreInfoDialog extends LitElement {
.hass=${this.hass}
.entityId=${this._entityId}
></ha-more-info-logbook>`}
${this._moreInfoType
? dynamicElement(this._moreInfoType, {
hass: this.hass,
stateObj,
})
: ""}
<more-info-content
.stateObj=${stateObj}
.hass=${this.hass}
></more-info-content>
${stateObj.attributes.restored
? html`
<p>

View File

@ -0,0 +1,57 @@
import { HassEntity } from "home-assistant-js-websocket";
import { property, PropertyValues, UpdatingElement } from "lit-element";
import { HomeAssistant } from "../../types";
import dynamicContentUpdater from "../../common/dom/dynamic_content_updater";
import { stateMoreInfoType } from "./state_more_info_control";
import { importMoreInfoControl } from "../../panels/lovelace/custom-card-helpers";
class MoreInfoContent extends UpdatingElement {
@property({ attribute: false }) public hass?: HomeAssistant;
@property() public stateObj?: HassEntity;
private _detachedChild?: ChildNode;
// This is not a lit element, but an updating element, so we implement update
protected update(changedProps: PropertyValues): void {
super.update(changedProps);
const stateObj = this.stateObj;
const hass = this.hass;
if (!stateObj || !hass) {
if (this.lastChild) {
this._detachedChild = this.lastChild;
// Detach child to prevent it from doing work.
this.removeChild(this.lastChild);
}
return;
}
if (this._detachedChild) {
this.appendChild(this._detachedChild);
this._detachedChild = undefined;
}
let moreInfoType: string | undefined;
if (stateObj.attributes && "custom_ui_more_info" in stateObj.attributes) {
moreInfoType = stateObj.attributes.custom_ui_more_info;
} else {
const type = stateMoreInfoType(stateObj);
importMoreInfoControl(type);
moreInfoType = type === "hidden" ? undefined : `more-info-${type}`;
}
if (!moreInfoType) {
return;
}
dynamicContentUpdater(this, moreInfoType.toUpperCase(), {
hass,
stateObj,
});
}
}
customElements.define("more-info-content", MoreInfoContent);

View File

@ -53,19 +53,21 @@ export const provideHass = (
} = {};
const entities = {};
function updateTranslations(fragment: null | string, language?: string) {
async function updateTranslations(
fragment: null | string,
language?: string
) {
const lang = language || getLocalLanguage();
getTranslation(fragment, lang).then(async (translation) => {
const resources = {
[lang]: {
...(hass().resources && hass().resources[lang]),
...translation.data,
},
};
hass().updateHass({
resources,
localize: await computeLocalize(elements[0], lang, resources),
});
const translation = await getTranslation(fragment, lang);
const resources = {
[lang]: {
...(hass().resources && hass().resources[lang]),
...translation.data,
},
};
hass().updateHass({
resources,
localize: await computeLocalize(elements[0], lang, resources),
});
}