Skip to content

Commit

Permalink
add title card
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Feb 6, 2022
1 parent d2209d8 commit ac335a4
Show file tree
Hide file tree
Showing 14 changed files with 395 additions and 9 deletions.
3 changes: 2 additions & 1 deletion .hass_dev/lovelace-mushroom-showcase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ views:
- !include views/fan-view.yaml
- !include views/template-view.yaml
- !include views/entity-view.yaml
- !include views/chips-view.yaml
- !include views/chips-view.yaml
- !include views/title-view.yaml
4 changes: 1 addition & 3 deletions .hass_dev/views/template-view.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@


title: Switch
title: Template
icon: mdi:card-text
cards:
- type: grid
Expand Down
17 changes: 17 additions & 0 deletions .hass_dev/views/title-view.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
title: Template
icon: mdi:card-text
cards:
- type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: Hello, {{user}}
subtitle: How are you?
- type: custom:mushroom-title-card
title: Number of entities
subtitle: |
{{ states | count }} entities
- type: custom:mushroom-title-card
title: Title only
- type: custom:mushroom-title-card
subtitle: Subtitle only

18 changes: 18 additions & 0 deletions docs/cards/title.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Title card

![Title light](../images/title-light.png)
![Title dark](../images/title-dark.png)

## Description

A Title block to separate sections of cards

## Configuration variables

All the options are available in the lovelace editor but you can use `yaml` if you want.

| Name | Type | Default | Description |
| :---------- | :-------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------- |
| `title` | string | Optional | Title to render. May contain [templates](https://www.home-assistant.io/docs/configuration/templating/). |
| `subtitle` | string | Optional | Subtitle to render. May contain [templates](https://www.home-assistant.io/docs/configuration/templating/). |
| `entity_id` | `string` `list` | Optional | Only reacts to the state changes of these entities. This can be used if the automatic analysis fails to find all relevant entities. |
Binary file added docs/images/title-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/title-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/cards/chips-card/chips/template-chip-editor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fireEvent, HomeAssistant } from "custom-card-helpers";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import setupCustomLocalize from "../../../localize";
import setupCustomlocalize from "../../../localize";
import { configElementStyle } from "../../../utils/editor-styles";
import { TemplateChipConfig } from "../../../utils/lovelace/chip/types";
import { EditorTarget } from "../../../utils/lovelace/editor/types";
Expand All @@ -25,7 +25,7 @@ export class EntityChipEditor extends LitElement implements LovelaceChipEditor {
return html``;
}

const customLocalize = setupCustomLocalize(this.hass);
const customLocalize = setupCustomlocalize(this.hass);

return html`
<div class="card-config">
Expand Down
4 changes: 2 additions & 2 deletions src/cards/template-card/template-card-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { assert } from "superstruct";
import setupcustomLocalize from "../../localize";
import setupCustomlocalize from "../../localize";
import { configElementStyle } from "../../utils/editor-styles";
import { EditorTarget } from "../../utils/lovelace/editor/types";
import { TEMPLATE_CARD_EDITOR_NAME } from "./const";
Expand Down Expand Up @@ -38,7 +38,7 @@ export class TemplateCardEditor
}

const dir = computeRTLDirection(this.hass);
const customLocalize = setupcustomLocalize(this.hass);
const customLocalize = setupCustomlocalize(this.hass);

return html`
<div class="card-config">
Expand Down
4 changes: 4 additions & 0 deletions src/cards/title-card/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { PREFIX_NAME } from "../../const";

export const TITLE_CARD_NAME = `${PREFIX_NAME}-title-card`;
export const TITLE_CARD_EDITOR_NAME = `${TITLE_CARD_NAME}-editor`;
16 changes: 16 additions & 0 deletions src/cards/title-card/title-card-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { LovelaceCardConfig } from "custom-card-helpers";
import { assign, object, optional, string } from "superstruct";
import { baseLovelaceCardConfig } from "../../utils/editor-styles";

export interface TitleCardConfig extends LovelaceCardConfig {
title?: string;
subtitle?: string;
}

export const titleCardConfigStruct = assign(
baseLovelaceCardConfig,
object({
title: optional(string()),
subtitle: optional(string()),
})
);
102 changes: 102 additions & 0 deletions src/cards/title-card/title-card-editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {
fireEvent,
HomeAssistant,
LovelaceCardEditor,
} from "custom-card-helpers";
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { assert } from "superstruct";
import setupCustomlocalize from "../../localize";
import { configElementStyle } from "../../utils/editor-styles";
import { EditorTarget } from "../../utils/lovelace/editor/types";
import { TITLE_CARD_EDITOR_NAME } from "./const";
import { TitleCardConfig, titleCardConfigStruct } from "./title-card-config";

@customElement(TITLE_CARD_EDITOR_NAME)
export class TitleCardEditor extends LitElement implements LovelaceCardEditor {
@property({ attribute: false }) public hass?: HomeAssistant;

@state() private _config?: TitleCardConfig;

public setConfig(config: TitleCardConfig): void {
assert(config, titleCardConfigStruct);
this._config = config;
}

protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;
}

const customLocalize = setupCustomlocalize(this.hass);

return html`
<div class="card-config">
<paper-textarea
.label="${customLocalize(
"editor.card.generic.title"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._config.title}
.configValue=${"title"}
@keydown=${this._ignoreKeydown}
@value-changed=${this._valueChanged}
autocapitalize="none"
autocomplete="off"
spellcheck="false"
></paper-textarea>
<paper-textarea
.label="${customLocalize(
"editor.card.generic.subtitle"
)} (${this.hass.localize(
"ui.panel.lovelace.editor.card.config.optional"
)})"
.value=${this._config.subtitle}
.configValue=${"subtitle"}
@keydown=${this._ignoreKeydown}
@value-changed=${this._valueChanged}
autocapitalize="none"
autocomplete="off"
spellcheck="false"
></paper-textarea>
</div>
`;
}

private _ignoreKeydown(ev: KeyboardEvent) {
// Stop keyboard events from the paper-textarea from propagating to avoid accidentally closing the dialog when the user presses Enter.
ev.stopPropagation();
}

private _valueChanged(ev: CustomEvent): void {
if (!this._config || !this.hass) {
return;
}
const target = ev.target! as EditorTarget;
const value =
target.checked !== undefined ? target.checked : ev.detail.value;

if (this[`_${target.configValue}`] === value) {
return;
}

let newConfig;
if (target.configValue) {
if (!value) {
newConfig = { ...this._config };
delete newConfig[target.configValue!];
} else {
newConfig = {
...this._config,
[target.configValue!]: value,
};
}
}
fireEvent(this, "config-changed", { config: newConfig });
}

static get styles(): CSSResultGroup {
return configElementStyle;
}
}
Loading

0 comments on commit ac335a4

Please sign in to comment.