Improve card and badge edit mode (#22413)

This commit is contained in:
Paul Bottein 2024-10-17 18:16:30 +02:00 committed by GitHub
parent 6298534b9c
commit f93c7e1b6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 74 additions and 36 deletions

View File

@ -11,6 +11,7 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { repeat } from "lit/directives/repeat"; import { repeat } from "lit/directives/repeat";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/ha-ripple";
import "../../../components/ha-sortable"; import "../../../components/ha-sortable";
import type { HaSortableOptions } from "../../../components/ha-sortable"; import type { HaSortableOptions } from "../../../components/ha-sortable";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
@ -157,6 +158,7 @@ export class HuiViewBadges extends LitElement {
"ui.panel.lovelace.editor.section.add_badge" "ui.panel.lovelace.editor.section.add_badge"
)} )}
> >
<ha-ripple></ha-ripple>
<ha-svg-icon .path=${mdiPlus}></ha-svg-icon> <ha-svg-icon .path=${mdiPlus}></ha-svg-icon>
</button> </button>
` `
@ -208,6 +210,9 @@ export class HuiViewBadges extends LitElement {
--mdc-icon-size: 18px; --mdc-icon-size: 18px;
cursor: pointer; cursor: pointer;
color: var(--primary-text-color); 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 { .add:focus {
border-style: solid; border-style: solid;

View File

@ -2,10 +2,10 @@ import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import { import {
mdiContentCopy, mdiContentCopy,
mdiContentCut, mdiContentCut,
mdiContentDuplicate,
mdiDelete, mdiDelete,
mdiDotsVertical, mdiDotsVertical,
mdiPencil, mdiPencil,
mdiPlusCircleMultipleOutline,
} from "@mdi/js"; } from "@mdi/js";
import deepClone from "deep-clone-simple"; import deepClone from "deep-clone-simple";
import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit"; import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
@ -17,6 +17,7 @@ import "../../../components/ha-button-menu";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-list-item"; import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import { ensureBadgeConfig } from "../../../data/lovelace/config/badge";
import { LovelaceCardConfig } from "../../../data/lovelace/config/card"; import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
@ -28,7 +29,6 @@ import {
parseLovelaceCardPath, parseLovelaceCardPath,
} from "../editor/lovelace-path"; } from "../editor/lovelace-path";
import { Lovelace } from "../types"; import { Lovelace } from "../types";
import { ensureBadgeConfig } from "../../../data/lovelace/config/badge";
@customElement("hui-badge-edit-mode") @customElement("hui-badge-edit-mode")
export class HuiBadgeEditMode extends LitElement { export class HuiBadgeEditMode extends LitElement {
@ -111,8 +111,8 @@ export class HuiBadgeEditMode extends LitElement {
<div class="badge-overlay ${classMap({ visible: showOverlay })}"> <div class="badge-overlay ${classMap({ visible: showOverlay })}">
<div <div
class="edit" class="edit"
@click=${this._editBadge} @click=${this._handleOverlayClick}
@keydown=${this._editBadge} @keydown=${this._handleOverlayClick}
tabindex="0" tabindex="0"
> >
<div class="edit-overlay"></div> <div class="edit-overlay"></div>
@ -129,10 +129,14 @@ export class HuiBadgeEditMode extends LitElement {
> >
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}> <ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
</ha-icon-button> </ha-icon-button>
<ha-list-item graphic="icon">
<ha-svg-icon slot="graphic" .path=${mdiPencil}></ha-svg-icon>
${this.hass.localize("ui.panel.lovelace.editor.edit_card.edit")}
</ha-list-item>
<ha-list-item graphic="icon"> <ha-list-item graphic="icon">
<ha-svg-icon <ha-svg-icon
slot="graphic" slot="graphic"
.path=${mdiContentDuplicate} .path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon> ></ha-svg-icon>
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.duplicate" "ui.panel.lovelace.editor.edit_card.duplicate"
@ -168,18 +172,33 @@ export class HuiBadgeEditMode extends LitElement {
this._menuOpened = false; this._menuOpened = false;
} }
private _handleOverlayClick(ev): void {
if (ev.defaultPrevented) {
return;
}
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
return;
}
ev.preventDefault();
ev.stopPropagation();
this._editBadge();
}
private _handleAction(ev: CustomEvent<ActionDetail>) { private _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) { switch (ev.detail.index) {
case 0: case 0:
this._duplicateBadge(); this._editBadge();
break; break;
case 1: case 1:
this._copyBadge(); this._duplicateBadge();
break; break;
case 2: case 2:
this._cutBadge(); this._copyBadge();
break; break;
case 3: case 3:
this._cutBadge();
break;
case 4:
this._deleteBadge(); this._deleteBadge();
break; break;
} }
@ -208,15 +227,7 @@ export class HuiBadgeEditMode extends LitElement {
}); });
} }
private _editBadge(ev): void { private _editBadge(): void {
if (ev.defaultPrevented) {
return;
}
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
return;
}
ev.preventDefault();
ev.stopPropagation();
fireEvent(this, "ll-edit-badge", { path: this.path! }); fireEvent(this, "ll-edit-badge", { path: this.path! });
} }

View File

@ -3,10 +3,10 @@ import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import { import {
mdiContentCopy, mdiContentCopy,
mdiContentCut, mdiContentCut,
mdiContentDuplicate,
mdiDelete, mdiDelete,
mdiDotsVertical, mdiDotsVertical,
mdiPencil, mdiPencil,
mdiPlusCircleMultipleOutline,
} from "@mdi/js"; } from "@mdi/js";
import deepClone from "deep-clone-simple"; import deepClone from "deep-clone-simple";
import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit"; import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit";
@ -111,8 +111,8 @@ export class HuiCardEditMode extends LitElement {
<div class="card-overlay ${classMap({ visible: showOverlay })}"> <div class="card-overlay ${classMap({ visible: showOverlay })}">
<div <div
class="edit" class="edit"
@click=${this._editCard} @click=${this._handleOverlayClick}
@keydown=${this._editCard} @keydown=${this._handleOverlayClick}
tabindex="0" tabindex="0"
> >
<div class="edit-overlay"></div> <div class="edit-overlay"></div>
@ -129,10 +129,14 @@ export class HuiCardEditMode extends LitElement {
> >
<ha-icon-button slot="trigger" .path=${mdiDotsVertical}> <ha-icon-button slot="trigger" .path=${mdiDotsVertical}>
</ha-icon-button> </ha-icon-button>
<ha-list-item graphic="icon">
<ha-svg-icon slot="graphic" .path=${mdiPencil}></ha-svg-icon>
${this.hass.localize("ui.panel.lovelace.editor.edit_card.edit")}
</ha-list-item>
<ha-list-item graphic="icon"> <ha-list-item graphic="icon">
<ha-svg-icon <ha-svg-icon
slot="graphic" slot="graphic"
.path=${mdiContentDuplicate} .path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon> ></ha-svg-icon>
${this.hass.localize( ${this.hass.localize(
"ui.panel.lovelace.editor.edit_card.duplicate" "ui.panel.lovelace.editor.edit_card.duplicate"
@ -168,18 +172,33 @@ export class HuiCardEditMode extends LitElement {
this._menuOpened = false; this._menuOpened = false;
} }
private _handleOverlayClick(ev): void {
if (ev.defaultPrevented) {
return;
}
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
return;
}
ev.preventDefault();
ev.stopPropagation();
this._editCard();
}
private _handleAction(ev: CustomEvent<ActionDetail>) { private _handleAction(ev: CustomEvent<ActionDetail>) {
switch (ev.detail.index) { switch (ev.detail.index) {
case 0: case 0:
this._duplicateCard(); this._editCard();
break; break;
case 1: case 1:
this._copyCard(); this._duplicateCard();
break; break;
case 2: case 2:
this._cutCard(); this._copyCard();
break; break;
case 3: case 3:
this._cutCard();
break;
case 4:
this._deleteCard(true); this._deleteCard(true);
break; break;
} }
@ -197,15 +216,7 @@ export class HuiCardEditMode extends LitElement {
}); });
} }
private _editCard(ev): void { private _editCard(): void {
if (ev.defaultPrevented) {
return;
}
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
return;
}
ev.preventDefault();
ev.stopPropagation();
fireEvent(this, "ll-edit-card", { path: this.path! }); fireEvent(this, "ll-edit-card", { path: this.path! });
} }

View File

@ -3,12 +3,12 @@ import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import { import {
mdiContentCopy, mdiContentCopy,
mdiContentCut, mdiContentCut,
mdiContentDuplicate,
mdiDelete, mdiDelete,
mdiDotsVertical, mdiDotsVertical,
mdiFileMoveOutline, mdiFileMoveOutline,
mdiMinus, mdiMinus,
mdiPlus, mdiPlus,
mdiPlusCircleMultipleOutline,
} from "@mdi/js"; } from "@mdi/js";
import deepClone from "deep-clone-simple"; import deepClone from "deep-clone-simple";
import { import {
@ -158,7 +158,7 @@ export class HuiCardOptions extends LitElement {
<ha-list-item graphic="icon"> <ha-list-item graphic="icon">
<ha-svg-icon <ha-svg-icon
slot="graphic" slot="graphic"
.path=${mdiContentDuplicate} .path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon> ></ha-svg-icon>
${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.editor.edit_card.duplicate" "ui.panel.lovelace.editor.edit_card.duplicate"

View File

@ -4,6 +4,7 @@ import { property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { repeat } from "lit/directives/repeat"; import { repeat } from "lit/directives/repeat";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import "../../../components/ha-ripple";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import type { HaSortableOptions } from "../../../components/ha-sortable"; import type { HaSortableOptions } from "../../../components/ha-sortable";
import { LovelaceSectionElement } from "../../../data/lovelace"; import { LovelaceSectionElement } from "../../../data/lovelace";
@ -12,10 +13,10 @@ import type { LovelaceSectionConfig } from "../../../data/lovelace/config/sectio
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types"; import type { HomeAssistant } from "../../../types";
import { HuiCard } from "../cards/hui-card"; import { HuiCard } from "../cards/hui-card";
import { computeCardGridSize } from "../common/compute-card-grid-size";
import "../components/hui-card-edit-mode"; import "../components/hui-card-edit-mode";
import { moveCard } from "../editor/config-util"; import { moveCard } from "../editor/config-util";
import type { Lovelace } from "../types"; import type { Lovelace } from "../types";
import { computeCardGridSize } from "../common/compute-card-grid-size";
const CARD_SORTABLE_OPTIONS: HaSortableOptions = { const CARD_SORTABLE_OPTIONS: HaSortableOptions = {
delay: 100, delay: 100,
@ -128,6 +129,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
"ui.panel.lovelace.editor.section.add_card" "ui.panel.lovelace.editor.section.add_card"
)} )}
> >
<ha-ripple></ha-ripple>
<ha-svg-icon .path=${mdiPlus}></ha-svg-icon> <ha-svg-icon .path=${mdiPlus}></ha-svg-icon>
</button> </button>
` `
@ -229,6 +231,7 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
} }
.add { .add {
position: relative;
outline: none; outline: none;
grid-row: span var(--row-size, 1); grid-row: span var(--row-size, 1);
grid-column: span var(--column-size, 2); grid-column: span var(--column-size, 2);
@ -238,6 +241,9 @@ export class GridSection extends LitElement implements LovelaceSectionElement {
border: 2px dashed var(--primary-color); border: 2px dashed var(--primary-color);
height: var(--row-height); height: var(--row-height);
order: 1; order: 1;
--ha-ripple-color: var(--primary-color);
--ha-ripple-hover-opacity: 0.04;
--ha-ripple-pressed-opacity: 0.12;
} }
.add:focus { .add:focus {
border-style: solid; border-style: solid;

View File

@ -16,6 +16,7 @@ import { clamp } from "../../../common/number/clamp";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-sortable"; import "../../../components/ha-sortable";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import "../../../components/ha-ripple";
import type { LovelaceViewElement } from "../../../data/lovelace"; import type { LovelaceViewElement } from "../../../data/lovelace";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view"; import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box"; import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
@ -234,6 +235,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
"ui.panel.lovelace.editor.section.create_section" "ui.panel.lovelace.editor.section.create_section"
)} )}
> >
<ha-ripple></ha-ripple>
<ha-svg-icon .path=${mdiViewGridPlus}></ha-svg-icon> <ha-svg-icon .path=${mdiViewGridPlus}></ha-svg-icon>
</button> </button>
` `
@ -382,6 +384,9 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
height: calc(var(--row-height) + 2 * (var(--row-gap) + 2px)); height: calc(var(--row-height) + 2 * (var(--row-gap) + 2px));
padding: 8px; padding: 8px;
box-sizing: border-box; box-sizing: border-box;
--ha-ripple-color: var(--primary-color);
--ha-ripple-hover-opacity: 0.04;
--ha-ripple-pressed-opacity: 0.12;
} }
.create-section:focus { .create-section:focus {