diff --git a/public/static/images/form/view_header_badges_position_bottom.svg b/public/static/images/form/view_header_badges_position_bottom.svg new file mode 100644 index 0000000000..8566c62f96 --- /dev/null +++ b/public/static/images/form/view_header_badges_position_bottom.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/images/form/view_header_badges_position_bottom_dark.svg b/public/static/images/form/view_header_badges_position_bottom_dark.svg new file mode 100644 index 0000000000..70424b9b45 --- /dev/null +++ b/public/static/images/form/view_header_badges_position_bottom_dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/images/form/view_header_badges_position_top.svg b/public/static/images/form/view_header_badges_position_top.svg new file mode 100644 index 0000000000..2e1842f076 --- /dev/null +++ b/public/static/images/form/view_header_badges_position_top.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/images/form/view_header_badges_position_top_dark.svg b/public/static/images/form/view_header_badges_position_top_dark.svg new file mode 100644 index 0000000000..4e8052f86e --- /dev/null +++ b/public/static/images/form/view_header_badges_position_top_dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/images/form/view_header_layout_center.svg b/public/static/images/form/view_header_layout_center.svg new file mode 100644 index 0000000000..bfa90a0912 --- /dev/null +++ b/public/static/images/form/view_header_layout_center.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/images/form/view_header_layout_center_dark.svg b/public/static/images/form/view_header_layout_center_dark.svg new file mode 100644 index 0000000000..5c07c8866e --- /dev/null +++ b/public/static/images/form/view_header_layout_center_dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/static/images/form/view_header_layout_responsive.svg b/public/static/images/form/view_header_layout_responsive.svg new file mode 100644 index 0000000000..c30aa083fc --- /dev/null +++ b/public/static/images/form/view_header_layout_responsive.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/static/images/form/view_header_layout_responsive_dark.svg b/public/static/images/form/view_header_layout_responsive_dark.svg new file mode 100644 index 0000000000..6edac7065c --- /dev/null +++ b/public/static/images/form/view_header_layout_responsive_dark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/public/static/images/form/view_header_layout_start.svg b/public/static/images/form/view_header_layout_start.svg new file mode 100644 index 0000000000..f1262284d6 --- /dev/null +++ b/public/static/images/form/view_header_layout_start.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/static/images/form/view_header_layout_start_dark.svg b/public/static/images/form/view_header_layout_start_dark.svg new file mode 100644 index 0000000000..36ceee734d --- /dev/null +++ b/public/static/images/form/view_header_layout_start_dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/data/lovelace/config/view.ts b/src/data/lovelace/config/view.ts index 915c5545cb..06f1456b0f 100644 --- a/src/data/lovelace/config/view.ts +++ b/src/data/lovelace/config/view.ts @@ -25,6 +25,12 @@ export interface LovelaceViewBackgroundConfig { attachment?: "scroll" | "fixed"; } +export interface LovelaceViewHeaderConfig { + card?: LovelaceCardConfig; + layout?: "start" | "center" | "responsive"; + badges_position?: "bottom" | "top"; +} + export interface LovelaceBaseViewConfig { index?: number; title?: string; @@ -46,6 +52,7 @@ export interface LovelaceViewConfig extends LovelaceBaseViewConfig { badges?: (string | Partial)[]; // Badge can be just an entity_id or without type cards?: LovelaceCardConfig[]; sections?: LovelaceSectionRawConfig[]; + header?: LovelaceViewHeaderConfig; } export interface LovelaceStrategyViewConfig extends LovelaceBaseViewConfig { diff --git a/src/panels/lovelace/badges/hui-view-badges.ts b/src/panels/lovelace/badges/hui-view-badges.ts index 8308c55776..312e953597 100644 --- a/src/panels/lovelace/badges/hui-view-badges.ts +++ b/src/panels/lovelace/badges/hui-view-badges.ts @@ -12,6 +12,7 @@ import "../../../components/ha-svg-icon"; import type { HomeAssistant } from "../../../types"; import "../components/hui-badge-edit-mode"; import { moveBadge } from "../editor/config-util"; +import type { LovelaceCardPath } from "../editor/lovelace-path"; import type { Lovelace } from "../types"; import type { HuiBadge } from "./hui-badge"; @@ -89,6 +90,20 @@ export class HuiViewBadges extends LitElement { this.lovelace!.saveConfig(newConfig); } + private _badgeAdded(ev) { + ev.stopPropagation(); + const { index, data } = ev.detail; + const oldPath = data as LovelaceCardPath; + const newPath = [this.viewIndex!, index] as LovelaceCardPath; + const newConfig = moveBadge(this.lovelace!.config, oldPath, newPath); + this.lovelace!.saveConfig(newConfig); + } + + private _badgeRemoved(ev) { + ev.stopPropagation(); + // Do nothing, it's handled by the "item-added" event from the new parent. + } + private _dragStart() { this._dragging = true; } @@ -114,6 +129,8 @@ export class HuiViewBadges extends LitElement { this._getBadgeKey(badge), - (badge, idx) => html` - ${editMode - ? html` - - ${badge} - - ` - : badge} - ` + (badge, idx) => { + const badgePath = [this.viewIndex, idx] as LovelaceCardPath; + return html` + ${editMode + ? html` + + ${badge} + + ` + : badge} + `; + } )} ${editMode ? html` @@ -179,8 +200,8 @@ export class HuiViewBadges extends LitElement { .badges { display: flex; align-items: flex-start; - flex-wrap: wrap; - justify-content: center; + flex-wrap: var(--badges-wrap, wrap); + justify-content: var(--badges-aligmnent, center); gap: 8px; margin: 0; } @@ -197,6 +218,7 @@ export class HuiViewBadges extends LitElement { display: flex; flex-direction: row; align-items: center; + outline: none; gap: 8px; height: 36px; padding: 6px 20px 6px 20px; diff --git a/src/panels/lovelace/components/hui-card-edit-mode.ts b/src/panels/lovelace/components/hui-card-edit-mode.ts index 8d88907260..19d4a7918a 100644 --- a/src/panels/lovelace/components/hui-card-edit-mode.ts +++ b/src/panels/lovelace/components/hui-card-edit-mode.ts @@ -50,6 +50,9 @@ export class HuiCardEditMode extends LitElement { @property({ type: Boolean, attribute: "no-duplicate" }) public noDuplicate = false; + @property({ type: Boolean, attribute: "no-move" }) + public noMove = false; + @state() public _menuOpened = false; @@ -179,23 +182,39 @@ export class HuiCardEditMode extends LitElement { )} `} - - - ${this.hass.localize("ui.panel.lovelace.editor.edit_card.copy")} - - - - ${this.hass.localize("ui.panel.lovelace.editor.edit_card.cut")} - -
  • + ${this.noMove + ? nothing + : html` + + + ${this.hass.localize( + "ui.panel.lovelace.editor.edit_card.copy" + )} + + + + ${this.hass.localize( + "ui.panel.lovelace.editor.edit_card.cut" + )} + + `} + ${this.noDuplicate && this.noEdit && this.noMove + ? nothing + : html`
  • `} + `; + } else { + content = html` + + `; + } + + const title = this.hass.localize( + "ui.panel.lovelace.editor.edit_view_header.header" + ); + + return html` + + + +

    ${title}

    + + + + ${this.hass!.localize( + `ui.panel.lovelace.editor.edit_view_header.edit_${!this._yamlMode ? "yaml" : "ui"}` + )} + + + +
    + ${content} + + ${this._saving + ? html`` + : nothing} + ${this.hass!.localize("ui.common.save")} +
    + `; + } + + private async _handleAction(ev: CustomEvent) { + ev.stopPropagation(); + ev.preventDefault(); + switch (ev.detail.index) { + case 0: + this._yamlMode = !this._yamlMode; + break; + } + } + + private _configChanged(ev: CustomEvent): void { + if ( + ev.detail && + ev.detail.config && + !deepEqual(this._config, ev.detail.config) + ) { + this._config = ev.detail.config; + this._dirty = true; + } + } + + private _viewYamlChanged(ev: CustomEvent) { + ev.stopPropagation(); + if (!ev.detail.isValid) { + return; + } + this._config = ev.detail.value; + this._dirty = true; + } + + private async _save(): Promise { + if (!this._params || !this._config) { + return; + } + + this._saving = true; + + try { + await this._params.saveConfig(this._config); + this.closeDialog(); + } catch (err: any) { + showAlertDialog(this, { + text: `${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view_header.saving_failed" + )}: ${err.message}`, + }); + } finally { + this._saving = false; + } + } + + static get styles(): CSSResultGroup { + return [ + haStyleDialog, + css` + ha-dialog { + /* Set the top top of the dialog to a fixed position, so it doesnt jump when the content changes size */ + --vertical-align-dialog: flex-start; + --dialog-surface-margin-top: 40px; + } + + @media all and (max-width: 450px), all and (max-height: 500px) { + /* When in fullscreen dialog should be attached to top */ + ha-dialog { + --dialog-surface-margin-top: 0px; + } + } + ha-dialog.yaml-mode { + --dialog-content-padding: 0; + } + h2 { + margin: 0; + font-size: inherit; + font-weight: inherit; + } + + @media all and (min-width: 600px) { + ha-dialog { + --mdc-dialog-min-width: 600px; + } + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-dialog-edit-view-header": HuiDialogEditViewHeader; + } +} diff --git a/src/panels/lovelace/editor/view-header/hui-view-header-settings-editor.ts b/src/panels/lovelace/editor/view-header/hui-view-header-settings-editor.ts new file mode 100644 index 0000000000..defde66bc9 --- /dev/null +++ b/src/panels/lovelace/editor/view-header/hui-view-header-settings-editor.ts @@ -0,0 +1,155 @@ +import { html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import type { LocalizeFunc } from "../../../../common/translations/localize"; +import { computeRTL } from "../../../../common/util/compute_rtl"; +import "../../../../components/ha-form/ha-form"; +import type { + HaFormSchema, + SchemaUnion, +} from "../../../../components/ha-form/types"; +import type { + LovelaceViewConfig, + LovelaceViewHeaderConfig, +} from "../../../../data/lovelace/config/view"; +import type { HomeAssistant } from "../../../../types"; +import { + DEFAULT_VIEW_HEADER_BADGES_POSITION, + DEFAULT_VIEW_HEADER_LAYOUT, +} from "../../views/hui-view-header"; +import { listenMediaQuery } from "../../../../common/dom/media_query"; + +@customElement("hui-view-header-settings-editor") +export class HuiViewHeaderSettingsEditor extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public config?: LovelaceViewHeaderConfig; + + @state({ attribute: false }) private narrow = false; + + private _unsubMql?: () => void; + + connectedCallback(): void { + super.connectedCallback(); + this._unsubMql = listenMediaQuery("(max-width: 600px)", (matches) => { + this.narrow = matches; + }); + } + + public disconnectedCallback() { + super.disconnectedCallback(); + this._unsubMql?.(); + this._unsubMql = undefined; + } + + private _schema = memoizeOne( + (localize: LocalizeFunc, isRTL: boolean, narrow: boolean) => + [ + { + name: "layout", + selector: { + select: { + mode: "box", + box_max_columns: narrow ? 1 : 3, + options: ["responsive", "start", "center"].map((value) => { + const labelKey = + value === "start" && isRTL ? `${value}_rtl` : value; + return { + value, + label: localize( + `ui.panel.lovelace.editor.edit_view_header.settings.layout_options.${labelKey}` + ), + description: localize( + `ui.panel.lovelace.editor.edit_view_header.settings.layout_options.${value}_description` + ), + image: { + src: `/static/images/form/view_header_layout_${value}.svg`, + src_dark: `/static/images/form/view_header_layout_${value}_dark.svg`, + flip_rtl: true, + }, + }; + }), + }, + }, + }, + { + name: "badges_position", + selector: { + select: { + mode: "box", + options: ["bottom", "top"].map((value) => ({ + value, + label: localize( + `ui.panel.lovelace.editor.edit_view_header.settings.badges_position_options.${value}` + ), + image: { + src: `/static/images/form/view_header_badges_position_${value}.svg`, + src_dark: `/static/images/form/view_header_badges_position_${value}_dark.svg`, + flip_rtl: true, + }, + })), + }, + }, + }, + ] as const satisfies HaFormSchema[] + ); + + protected render() { + if (!this.hass) { + return nothing; + } + + const data = { + layout: this.config?.layout || DEFAULT_VIEW_HEADER_LAYOUT, + badges_position: + this.config?.badges_position || DEFAULT_VIEW_HEADER_BADGES_POSITION, + }; + + const narrow = this.narrow; + const isRTL = computeRTL(this.hass); + const schema = this._schema(this.hass.localize, isRTL, narrow); + + return html` + + `; + } + + private _valueChanged(ev: CustomEvent): void { + ev.stopPropagation(); + const newData = ev.detail.value as LovelaceViewConfig; + + const config: LovelaceViewHeaderConfig = { + ...this.config, + ...newData, + }; + + fireEvent(this, "config-changed", { config }); + } + + private _computeLabel = ( + schema: SchemaUnion> + ) => { + switch (schema.name) { + case "layout": + case "badges_position": + return this.hass.localize( + `ui.panel.lovelace.editor.edit_view_header.settings.${schema.name}` + ); + default: + return ""; + } + }; +} + +declare global { + interface HTMLElementTagNameMap { + "hui-view-header-settings-editor": HuiViewHeaderSettingsEditor; + } +} diff --git a/src/panels/lovelace/editor/view-header/show-edit-view-header-dialog.ts b/src/panels/lovelace/editor/view-header/show-edit-view-header-dialog.ts new file mode 100644 index 0000000000..d2aef306c3 --- /dev/null +++ b/src/panels/lovelace/editor/view-header/show-edit-view-header-dialog.ts @@ -0,0 +1,18 @@ +import { fireEvent } from "../../../../common/dom/fire_event"; +import type { LovelaceViewHeaderConfig } from "../../../../data/lovelace/config/view"; + +export interface EditViewHeaderDialogParams { + saveConfig: (config: LovelaceViewHeaderConfig) => void; + config: LovelaceViewHeaderConfig; +} + +export const showEditViewHeaderDialog = ( + element: HTMLElement, + dialogParams: EditViewHeaderDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "hui-dialog-edit-view-header", + dialogImport: () => import("./hui-dialog-edit-view-header"), + dialogParams: dialogParams, + }); +}; diff --git a/src/panels/lovelace/sections/hui-grid-section.ts b/src/panels/lovelace/sections/hui-grid-section.ts index 059fe80852..4906c4d107 100644 --- a/src/panels/lovelace/sections/hui-grid-section.ts +++ b/src/panels/lovelace/sections/hui-grid-section.ts @@ -193,7 +193,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement { private _cardRemoved(ev) { ev.stopPropagation(); - // Do nothing, it's handle by the "card-added" event from the new parent. + // Do nothing, it's handled by the "item-added" event from the new parent. } private _dragStart() { diff --git a/src/panels/lovelace/views/hui-sections-view.ts b/src/panels/lovelace/views/hui-sections-view.ts index 21f108aa7e..ff27e131ca 100644 --- a/src/panels/lovelace/views/hui-sections-view.ts +++ b/src/panels/lovelace/views/hui-sections-view.ts @@ -25,7 +25,7 @@ import type { LovelaceViewConfig } from "../../../data/lovelace/config/view"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import type { HomeAssistant } from "../../../types"; import type { HuiBadge } from "../badges/hui-badge"; -import "../badges/hui-view-badges"; +import "./hui-view-header"; import type { HuiCard } from "../cards/hui-card"; import "../components/hui-badge-edit-mode"; import { @@ -61,10 +61,10 @@ export class SectionsView extends LitElement implements LovelaceViewElement { @property({ attribute: false }) public sections: HuiSection[] = []; - @property({ attribute: false }) public badges: HuiBadge[] = []; - @property({ attribute: false }) public cards: HuiCard[] = []; + @property({ attribute: false }) public badges: HuiBadge[] = []; + @state() private _config?: LovelaceViewConfig; @state() private _sectionColumnCount = 0; @@ -154,15 +154,16 @@ export class SectionsView extends LitElement implements LovelaceViewElement { const maxColumnCount = this._columnsController.value ?? 1; return html` - + > this._getSectionKey(section), (section, idx) => { - const sectionConfig = this._config?.sections?.[idx]; const columnSpan = Math.min( - sectionConfig?.column_span || 1, + section.config.column_span || 1, maxColumnCount ); - - const rowSpan = sectionConfig?.row_span || 1; + const rowSpan = section.config.row_span || 1; return html`
    badges.hidden); + this.toggleAttribute("hidden", allHidden); + } + + private _badgeVisibilityChanged = () => { + this._checkHidden(); + }; + + connectedCallback(): void { + super.connectedCallback(); + this.addEventListener( + "badge-visibility-changed", + this._badgeVisibilityChanged + ); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + this.removeEventListener( + "badge-visibility-changed", + this._badgeVisibilityChanged + ); + } + + willUpdate(changedProperties: PropertyValues): void { + if ( + changedProperties.has("badges") || + changedProperties.has("lovelace") || + changedProperties.has("card") + ) { + this._checkHidden(); + } + + if (changedProperties.has("config")) { + if (this.config?.card) { + this.card = this._createCardElement(this.config.card); + } else { + this.card = undefined; + } + return; + } + + if (this.card) { + if (changedProperties.has("hass")) { + this.card.hass = this.hass; + } + if (changedProperties.has("lovelace")) { + this.card.preview = this.lovelace.editMode; + } + } + } + + private _createCardElement(cardConfig: LovelaceCardConfig) { + const element = document.createElement("hui-card"); + element.hass = this.hass; + element.preview = this.lovelace.editMode; + element.config = cardConfig; + element.load(); + return element; + } + + private _addCard() { + const cardConfig: LovelaceCardConfig = { + type: "markdown", + text_only: true, + content: this.hass.localize( + "ui.panel.lovelace.editor.edit_view_header.default_title", + { user: "{{ user }}" } + ), + }; + + showEditCardDialog(this, { + cardConfig, + lovelaceConfig: this.lovelace.config, + saveCardConfig: (newCardConfig: LovelaceCardConfig) => { + const newConfig = { ...this.config }; + newConfig.card = newCardConfig; + this._saveHeaderConfig(newConfig); + }, + isNew: true, + }); + } + + private _deleteCard(ev) { + ev.stopPropagation(); + const newConfig = { ...this.config }; + delete newConfig.card; + this._saveHeaderConfig(newConfig); + } + + private _editCard(ev) { + ev.stopPropagation(); + const cardConfig = this.config!.card; + + if (!cardConfig) { + return; + } + + showEditCardDialog(this, { + cardConfig, + lovelaceConfig: this.lovelace.config, + saveCardConfig: (newCardConfig: LovelaceCardConfig) => { + const newConfig = { ...this.config }; + newConfig.card = newCardConfig; + this._saveHeaderConfig(newConfig); + }, + }); + } + + private _saveHeaderConfig(headerConfig: LovelaceViewHeaderConfig) { + const viewConfig = this.lovelace.config.views[ + this.viewIndex + ] as LovelaceViewConfig; + + const config = { ...viewConfig }; + config.header = headerConfig; + + const updatedConfig = replaceView( + this.hass, + this.lovelace.config, + this.viewIndex, + config + ); + this.lovelace.saveConfig(updatedConfig); + } + + private _configure = () => { + showEditViewHeaderDialog(this, { + config: this.config!, + saveConfig: (config: LovelaceViewHeaderConfig) => { + this._saveHeaderConfig(config); + }, + }); + }; + + render() { + if (!this.lovelace) return nothing; + + const editMode = Boolean(this.lovelace?.editMode); + + const card = this.card; + + const layout = this.config?.layout ?? DEFAULT_VIEW_HEADER_LAYOUT; + const badgesPosition = + this.config?.badges_position ?? DEFAULT_VIEW_HEADER_BADGES_POSITION; + + const hasHeading = card !== undefined; + const hasBadges = this.badges.length > 0; + + return html` + ${editMode + ? html` +
    +
    + +
    +
    + ` + : nothing} +
    +
    + ${card || editMode + ? html` +
    + ${editMode + ? card + ? html` + + ${card} + + ` + : html` + + ` + : card} +
    + ` + : nothing} + ${this.lovelace && (editMode || this.badges.length > 0) + ? html` +
    + +
    + ` + : nothing} +
    +
    + `; + } + + static styles = css` + :host([hidden]) { + display: none !important; + } + + .container { + position: relative; + } + + .actions-container { + position: relative; + height: 34px; + display: flex; + flex-direction: column; + justify-content: flex-end; + } + + .actions { + z-index: 1; + position: absolute; + height: 36px; + bottom: -2px; + right: 0; + inset-inline-end: 0; + inset-inline-start: initial; + opacity: 1; + display: flex; + align-items: center; + justify-content: center; + transition: opacity 0.2s ease-in-out; + border-radius: var(--ha-card-border-radius, 12px); + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + background: var(--secondary-background-color); + --mdc-icon-button-size: 36px; + --mdc-icon-size: 20px; + color: var(--primary-text-color); + } + + .layout { + position: relative; + display: flex; + flex-direction: column; + gap: 24px 8px; + --spacing: 24px; + } + + .layout.has-heading { + margin-top: var(--spacing); + } + + .heading { + position: relative; + flex: 1; + width: 100%; + max-width: 700px; + display: flex; + } + + .heading > * { + width: 100%; + height: 100%; + } + + .badges { + position: relative; + flex: 1; + display: flex; + } + + hui-view-badges { + width: 100%; + display: flex; + flex-direction: column; + justify-content: flex-end; + --badges-aligmnent: flex-start; + } + + /* Layout */ + .layout { + align-items: flex-start; + } + + .layout.center { + align-items: center; + } + + .layout .heading { + text-align: start; + } + + .layout.center .heading { + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + } + + .layout.center hui-view-badges { + --badges-aligmnent: center; + } + + @media (min-width: 768px) { + .layout.responsive.has-heading { + flex-direction: row; + align-items: flex-end; + } + .layout.responsive.has-heading hui-view-badges { + --badges-aligmnent: flex-end; + } + } + + .layout.badges-top { + flex-direction: column-reverse; + } + + .layout.badges-top.has-badges { + margin-top: 0; + } + + @media (min-width: 768px) { + .layout.responsive.badges-top.has-heading { + flex-direction: row; + align-items: flex-start; + margin-top: var(--spacing); + } + } + + .container.edit-mode { + padding: 8px; + border-radius: var(--ha-card-border-radius, 12px); + border: 2px dashed var(--divider-color); + border-start-end-radius: 0; + } + + .container.edit-mode .content { + min-height: 36px; + } + + .add { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + outline: none; + gap: 8px; + height: 36px; + padding: 6px 20px 6px 20px; + box-sizing: border-box; + width: auto; + border-radius: var(--ha-card-border-radius, 12px); + background-color: transparent; + border-width: 2px; + border-style: dashed; + border-color: var(--primary-color); + --mdc-icon-size: 18px; + cursor: pointer; + font-size: 14px; + color: var(--primary-text-color); + --ha-ripple-color: var(--primary-color); + --ha-ripple-hover-opacity: 0.04; + --ha-ripple-pressed-opacity: 0.12; + } + + .add:focus { + border-style: solid; + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "hui-view-header": HuiViewHeader; + } +} diff --git a/src/translations/en.json b/src/translations/en.json index 481fb27f08..5f8e990ca7 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -6575,6 +6575,31 @@ "error_same_url": "You cannot save a view with the same URL as a different existing view.", "move_to_dashboard": "Move to dashboard" }, + "edit_view_header": { + "add_title": "Add title", + "header": "Header settings", + "edit_ui": "[%key:ui::panel::lovelace::editor::edit_view::edit_ui%]", + "edit_yaml": "[%key:ui::panel::lovelace::editor::edit_view::edit_yaml%]", + "saving_failed": "[%key:ui::panel::lovelace::editor::edit_view::saving_failed%]", + "default_title": "# Hello {user}\nAdd your text here, template variables are supported ✨", + "settings": { + "layout": "Layout", + "layout_options": { + "responsive": "Responsive", + "responsive_description": "Stacked on mobile", + "start": "Left aligned", + "start_description": "Always stacked", + "start_rtl": "Right aligned", + "center": "Centered", + "center_description": "Always stacked" + }, + "badges_position": "Badges position", + "badges_position_options": { + "top": "Top", + "bottom": "Bottom" + } + } + }, "edit_badges": { "view_no_badges": "Badges are not be supported by the current view type." }, @@ -6694,8 +6719,6 @@ "edit_ui": "[%key:ui::panel::lovelace::editor::edit_view::edit_ui%]", "edit_yaml": "[%key:ui::panel::lovelace::editor::edit_view::edit_yaml%]", "settings": { - "title": "Title", - "title_helper": "The title will appear at the top of section. Leave empty to hide the title.", "column_span": "Width", "column_span_helper": "Larger sections will be made smaller to fit the display. (e.g. on mobile devices)" },