Revive automation row overflow menu (#27093)

This commit is contained in:
Wendelin
2025-09-22 16:46:35 +02:00
committed by GitHub
parent 1e2d144d26
commit 95a0fe335f
13 changed files with 881 additions and 474 deletions

View File

@@ -1,6 +1,7 @@
import { consume } from "@lit/context";
import {
mdiAlertCircleCheck,
mdiAppleKeyboardCommand,
mdiArrowDown,
mdiArrowUp,
mdiContentCopy,
@@ -16,7 +17,7 @@ import {
} from "@mdi/js";
import deepClone from "deep-clone-simple";
import { dump } from "js-yaml";
import type { PropertyValues } from "lit";
import type { PropertyValues, TemplateResult } from "lit";
import { LitElement, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one";
@@ -73,9 +74,10 @@ import {
showPromptDialog,
} from "../../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import { showToast } from "../../../../util/toast";
import "../ha-automation-editor-warning";
import { rowStyles } from "../styles";
import { overflowStyles, rowStyles } from "../styles";
import "./ha-automation-action-editor";
import type HaAutomationActionEditor from "./ha-automation-action-editor";
import "./types/ha-automation-action-choose";
@@ -225,6 +227,20 @@ export default class HaAutomationActionRow extends LitElement {
}
}
private _renderOverflowLabel(label: string, shortcut?: TemplateResult) {
return html`
<div class="overflow-label">
${label}
${this.optionsInSidebar && !this.narrow
? shortcut ||
html`<span
class="shortcut-placeholder ${isMac ? "mac" : ""}"
></span>`
: nothing}
</div>
`;
}
private _renderRow() {
const type = getAutomationActionType(this.action);
@@ -272,8 +288,8 @@ export default class HaAutomationActionRow extends LitElement {
)}
</ha-tooltip>`
: nothing}
${!this.optionsInSidebar
? html`<ha-md-button-menu
<ha-md-button-menu
quick
slot="icons"
@click=${preventDefaultStopPropagation}
@@ -290,62 +306,102 @@ export default class HaAutomationActionRow extends LitElement {
></ha-icon-button>
<ha-md-menu-item .clickAction=${this._runAction}>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.run"
)}
<ha-svg-icon slot="start" .path=${mdiPlay}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize("ui.panel.config.automation.editor.actions.run")
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._renameAction}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.rename"
)}
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.rename"
)
)}
</ha-md-menu-item>
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
<ha-md-menu-item
.clickAction=${this._duplicateAction}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)}
<ha-svg-icon
slot="start"
.path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._copyAction}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.copy"
)}
<ha-svg-icon slot="start" .path=${mdiContentCopy}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.copy"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span>C</span>
</span>`
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._cutAction}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.cut"
)}
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.cut"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span>X</span>
</span>`
)}
</ha-md-menu-item>
${!this.optionsInSidebar
? html`
<ha-md-menu-item
.clickAction=${this._moveUp}
.disabled=${this.disabled || !!this.first}
>
${this.hass.localize("ui.panel.config.automation.editor.move_up")}
${this.hass.localize(
"ui.panel.config.automation.editor.move_up"
)}
<ha-svg-icon slot="start" .path=${mdiArrowUp}></ha-svg-icon
></ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._moveDown}
.disabled=${this.disabled || !!this.last}
@@ -355,15 +411,19 @@ export default class HaAutomationActionRow extends LitElement {
)}
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
></ha-md-menu-item>
`
: nothing}
<ha-md-menu-item
.clickAction=${this._toggleYamlMode}
.disabled=${!this._uiModeAvailable || !!this._warnings}
>
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
)}
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
)
)}
</ha-md-menu-item>
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
@@ -372,36 +432,56 @@ export default class HaAutomationActionRow extends LitElement {
.clickAction=${this._onDisable}
.disabled=${this.disabled}
>
${this.action.enabled === false
? this.hass.localize(
"ui.panel.config.automation.editor.actions.enable"
)
: this.hass.localize(
"ui.panel.config.automation.editor.actions.disable"
)}
<ha-svg-icon
slot="start"
.path=${this.action.enabled === false
? mdiPlayCircleOutline
: mdiStopCircleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
`ui.panel.config.automation.editor.actions.${this.action.enabled === false ? "enable" : "disable"}`
)
)}
</ha-md-menu-item>
<ha-md-menu-item
class="warning"
.clickAction=${this._onDelete}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
<ha-svg-icon
class="warning"
slot="start"
.path=${mdiDelete}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span
>${this.hass.localize(
"ui.panel.config.automation.editor.del"
)}</span
>
</span>`
)}
</ha-md-menu-item>
</ha-md-button-menu>`
: nothing}
</ha-md-button-menu>
${!this.optionsInSidebar
? html`${this._warnings
? html`<ha-automation-editor-warning
@@ -680,7 +760,7 @@ export default class HaAutomationActionRow extends LitElement {
fireEvent(this, "move-down");
};
private _toggleYamlMode = () => {
private _toggleYamlMode = (item?: HTMLElement) => {
if (this._yamlMode) {
this._switchUiMode();
} else {
@@ -689,6 +769,8 @@ export default class HaAutomationActionRow extends LitElement {
if (!this.optionsInSidebar) {
this.expand();
} else if (item) {
this.openSidebar();
}
};
@@ -804,7 +886,7 @@ export default class HaAutomationActionRow extends LitElement {
this._automationRowElement?.focus();
}
static styles = rowStyles;
static styles = [rowStyles, overflowStyles];
}
declare global {

View File

@@ -1,5 +1,6 @@
import { consume } from "@lit/context";
import {
mdiAppleKeyboardCommand,
mdiArrowDown,
mdiArrowUp,
mdiContentCopy,
@@ -15,7 +16,7 @@ import {
} from "@mdi/js";
import deepClone from "deep-clone-simple";
import { dump } from "js-yaml";
import type { CSSResultGroup, PropertyValues } from "lit";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
@@ -56,9 +57,10 @@ import {
showPromptDialog,
} from "../../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import { showToast } from "../../../../util/toast";
import "../ha-automation-editor-warning";
import { rowStyles } from "../styles";
import { overflowStyles, rowStyles } from "../styles";
import "./ha-automation-condition-editor";
import type HaAutomationConditionEditor from "./ha-automation-condition-editor";
import "./types/ha-automation-condition-and";
@@ -162,6 +164,20 @@ export default class HaAutomationConditionRow extends LitElement {
return this._selected;
}
private _renderOverflowLabel(label: string, shortcut?: TemplateResult) {
return html`
<div class="overflow-label">
${label}
${this.optionsInSidebar && !this.narrow
? shortcut ||
html`<span
class="shortcut-placeholder ${isMac ? "mac" : ""}"
></span>`
: nothing}
</div>
`;
}
private _renderRow() {
return html`
<ha-svg-icon
@@ -177,8 +193,7 @@ export default class HaAutomationConditionRow extends LitElement {
<slot name="icons" slot="icons"></slot>
${!this.optionsInSidebar
? html`<ha-md-button-menu
<ha-md-button-menu
quick
slot="icons"
@click=${preventDefaultStopPropagation}
@@ -196,19 +211,23 @@ export default class HaAutomationConditionRow extends LitElement {
</ha-icon-button>
<ha-md-menu-item .clickAction=${this._testCondition}>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.test"
)}
<ha-svg-icon slot="start" .path=${mdiFlask}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.conditions.test"
)
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._renameCondition}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.conditions.rename"
)}
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.conditions.rename"
)
)}
</ha-md-menu-item>
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
@@ -217,43 +236,80 @@ export default class HaAutomationConditionRow extends LitElement {
.clickAction=${this._duplicateCondition}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)}
<ha-svg-icon
slot="start"
.path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._copyCondition}
.disabled=${this.disabled}
>
${this.hass.localize(
<ha-svg-icon slot="start" .path=${mdiContentCopy}></ha-svg-icon
>${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.copy"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span>C</span>
</span>`
)}
<ha-svg-icon slot="start" .path=${mdiContentCopy}></ha-svg-icon>
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._cutCondition}
.disabled=${this.disabled}
>
${this.hass.localize(
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon
>${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.cut"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span>X</span>
</span>`
)}
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon>
</ha-md-menu-item>
${!this.optionsInSidebar
? html`
<ha-md-menu-item
.clickAction=${this._moveUp}
.disabled=${this.disabled || this.first}
>
${this.hass.localize("ui.panel.config.automation.editor.move_up")}
${this.hass.localize(
"ui.panel.config.automation.editor.move_up"
)}
<ha-svg-icon slot="start" .path=${mdiArrowUp}></ha-svg-icon
></ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._moveDown}
.disabled=${this.disabled || this.last}
@@ -263,16 +319,16 @@ export default class HaAutomationConditionRow extends LitElement {
)}
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
></ha-md-menu-item>
`
: nothing}
<ha-md-menu-item
.clickAction=${this._toggleYamlMode}
.disabled=${this._uiSupported(this.condition.condition) ||
!!this._warnings}
>
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
)}
<ha-md-menu-item .clickAction=${this._toggleYamlMode}>
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
)
)}
</ha-md-menu-item>
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
@@ -281,36 +337,54 @@ export default class HaAutomationConditionRow extends LitElement {
.clickAction=${this._onDisable}
.disabled=${this.disabled}
>
${this.condition.enabled === false
? this.hass.localize(
"ui.panel.config.automation.editor.actions.enable"
)
: this.hass.localize(
"ui.panel.config.automation.editor.actions.disable"
)}
<ha-svg-icon
slot="start"
.path=${this.condition.enabled === false
? mdiPlayCircleOutline
: mdiStopCircleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
`ui.panel.config.automation.editor.actions.${this.condition.enabled === false ? "enable" : "disable"}`
)
)}
</ha-md-menu-item>
<ha-md-menu-item
class="warning"
.clickAction=${this._onDelete}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
<ha-svg-icon
class="warning"
slot="start"
.path=${mdiDelete}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span
>${this.hass.localize(
"ui.panel.config.automation.editor.del"
)}</span
>
</span>`
)}
</ha-md-menu-item>
</ha-md-button-menu>`
: nothing}
</ha-md-button-menu>
${!this.optionsInSidebar
? html`${this._warnings
? html`<ha-automation-editor-warning
@@ -490,9 +564,9 @@ export default class HaAutomationConditionRow extends LitElement {
this._testing = true;
const condition = this.condition;
requestAnimationFrame(() => {
// @ts-ignore is supported in all browsers expect firefox
// @ts-ignore is supported in all browsers except firefox
if (this.scrollIntoViewIfNeeded) {
// @ts-ignore is supported in all browsers expect firefox
// @ts-ignore is supported in all browsers except firefox
this.scrollIntoViewIfNeeded();
return;
}
@@ -626,7 +700,7 @@ export default class HaAutomationConditionRow extends LitElement {
fireEvent(this, "move-down");
};
private _toggleYamlMode = () => {
private _toggleYamlMode = (item?: HTMLElement) => {
if (this._yamlMode) {
this._switchUiMode();
} else {
@@ -635,6 +709,8 @@ export default class HaAutomationConditionRow extends LitElement {
if (!this.optionsInSidebar) {
this.expand();
} else if (item) {
this.openSidebar();
}
};
@@ -742,6 +818,7 @@ export default class HaAutomationConditionRow extends LitElement {
static get styles(): CSSResultGroup {
return [
rowStyles,
overflowStyles,
css`
.testing {
position: absolute;

View File

@@ -1,5 +1,6 @@
import { consume } from "@lit/context";
import {
mdiAppleKeyboardCommand,
mdiArrowDown,
mdiArrowUp,
mdiDelete,
@@ -7,7 +8,7 @@ import {
mdiPlusCircleMultipleOutline,
mdiRenameBox,
} from "@mdi/js";
import type { CSSResultGroup } from "lit";
import type { CSSResultGroup, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
@@ -37,11 +38,17 @@ import {
showPromptDialog,
} from "../../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import "../action/ha-automation-action";
import type HaAutomationAction from "../action/ha-automation-action";
import "../condition/ha-automation-condition";
import type HaAutomationCondition from "../condition/ha-automation-condition";
import { editorStyles, indentStyle, rowStyles } from "../styles";
import {
editorStyles,
indentStyle,
overflowStyles,
rowStyles,
} from "../styles";
@customElement("ha-automation-option-row")
export default class HaAutomationOptionRow extends LitElement {
@@ -119,6 +126,20 @@ export default class HaAutomationOptionRow extends LitElement {
return str;
}
private _renderOverflowLabel(label: string, shortcut?: TemplateResult) {
return html`
<div class="overflow-label">
${label}
${this.optionsInSidebar && !this.narrow
? shortcut ||
html`<span
class="shortcut-placeholder ${isMac ? "mac" : ""}"
></span>`
: nothing}
</div>
`;
}
private _renderRow() {
return html`
<h3 slot="header">
@@ -134,7 +155,7 @@ export default class HaAutomationOptionRow extends LitElement {
<slot name="icons" slot="icons"></slot>
${this.option && !this.optionsInSidebar
${this.option
? html`
<ha-md-button-menu
quick
@@ -156,58 +177,92 @@ export default class HaAutomationOptionRow extends LitElement {
@click=${this._renameOption}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.rename"
)}
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.rename"
)
)}
</ha-md-menu-item>
<ha-md-menu-item
@click=${this._duplicateOption}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)}
<ha-svg-icon
slot="start"
.path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)
)}
</ha-md-menu-item>
${!this.optionsInSidebar
? html`
<ha-md-menu-item
@click=${this._moveUp}
.disabled=${this.disabled || this.first}
.clickAction=${this._moveUp}
.disabled=${this.disabled || !!this.first}
>
${this.hass.localize(
"ui.panel.config.automation.editor.move_up"
)}
<ha-svg-icon slot="start" .path=${mdiArrowUp}></ha-svg-icon>
</ha-md-menu-item>
<ha-svg-icon
slot="start"
.path=${mdiArrowUp}
></ha-svg-icon
></ha-md-menu-item>
<ha-md-menu-item
@click=${this._moveDown}
.disabled=${this.disabled || this.last}
.clickAction=${this._moveDown}
.disabled=${this.disabled || !!this.last}
>
${this.hass.localize(
"ui.panel.config.automation.editor.move_down"
)}
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon>
</ha-md-menu-item>
<ha-svg-icon
slot="start"
.path=${mdiArrowDown}
></ha-svg-icon
></ha-md-menu-item>
`
: nothing}
<ha-md-menu-item
@click=${this._removeOption}
class="warning"
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.remove_option"
)}
<ha-svg-icon
class="warning"
slot="start"
.path=${mdiDelete}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.type.choose.remove_option"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span
>${this.hass.localize(
"ui.panel.config.automation.editor.del"
)}</span
>
</span>`
)}
</ha-md-menu-item>
</ha-md-button-menu>
`
@@ -459,6 +514,7 @@ export default class HaAutomationOptionRow extends LitElement {
return [
rowStyles,
editorStyles,
overflowStyles,
indentStyle,
css`
li[role="separator"] {

View File

@@ -26,7 +26,7 @@ import { isMac } from "../../../../util/is_mac";
import type HaAutomationConditionEditor from "../action/ha-automation-action-editor";
import { getAutomationActionType } from "../action/ha-automation-action-row";
import { getRepeatType } from "../action/types/ha-automation-action-repeat";
import { sidebarEditorStyles } from "../styles";
import { overflowStyles, sidebarEditorStyles } from "../styles";
import "../trigger/ha-automation-trigger-editor";
import "./ha-automation-sidebar-card";
@@ -324,7 +324,7 @@ export default class HaAutomationSidebarAction extends LitElement {
fireEvent(this, "toggle-yaml-mode");
};
static styles = sidebarEditorStyles;
static styles = [sidebarEditorStyles, overflowStyles];
}
declare global {

View File

@@ -27,7 +27,7 @@ import { isMac } from "../../../../util/is_mac";
import { showAlertDialog } from "../../../lovelace/custom-card-helpers";
import "../condition/ha-automation-condition-editor";
import type HaAutomationConditionEditor from "../condition/ha-automation-condition-editor";
import { sidebarEditorStyles } from "../styles";
import { overflowStyles, sidebarEditorStyles } from "../styles";
import "./ha-automation-sidebar-card";
@customElement("ha-automation-sidebar-condition")
@@ -364,6 +364,7 @@ export default class HaAutomationSidebarCondition extends LitElement {
} finally {
setTimeout(() => {
this._testing = false;
this._testingResult = undefined;
}, 2500);
}
};
@@ -402,6 +403,7 @@ export default class HaAutomationSidebarCondition extends LitElement {
static styles = [
sidebarEditorStyles,
overflowStyles,
css`
ha-automation-sidebar-card {
position: relative;

View File

@@ -10,7 +10,7 @@ import type { OptionSidebarConfig } from "../../../../data/automation";
import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import type HaAutomationConditionEditor from "../action/ha-automation-action-editor";
import { sidebarEditorStyles } from "../styles";
import { overflowStyles, sidebarEditorStyles } from "../styles";
import "./ha-automation-sidebar-card";
@customElement("ha-automation-sidebar-option")
@@ -127,7 +127,7 @@ export default class HaAutomationSidebarOption extends LitElement {
</ha-automation-sidebar-card>`;
}
static styles = sidebarEditorStyles;
static styles = [sidebarEditorStyles, overflowStyles];
}
declare global {

View File

@@ -8,7 +8,7 @@ import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import "../../script/ha-script-field-editor";
import type HaAutomationConditionEditor from "../action/ha-automation-action-editor";
import { sidebarEditorStyles } from "../styles";
import { overflowStyles, sidebarEditorStyles } from "../styles";
import "./ha-automation-sidebar-card";
@customElement("ha-automation-sidebar-script-field")
@@ -153,7 +153,7 @@ export default class HaAutomationSidebarScriptField extends LitElement {
fireEvent(this, "toggle-yaml-mode");
};
static styles = sidebarEditorStyles;
static styles = [sidebarEditorStyles, overflowStyles];
}
declare global {

View File

@@ -3,7 +3,6 @@ import {
mdiContentCopy,
mdiContentCut,
mdiDelete,
mdiIdentifier,
mdiPlayCircleOutline,
mdiPlaylistEdit,
mdiPlusCircleMultipleOutline,
@@ -19,7 +18,7 @@ import type { TriggerSidebarConfig } from "../../../../data/automation";
import { isTriggerList } from "../../../../data/trigger";
import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import { sidebarEditorStyles } from "../styles";
import { overflowStyles, sidebarEditorStyles } from "../styles";
import "../trigger/ha-automation-trigger-editor";
import type HaAutomationTriggerEditor from "../trigger/ha-automation-trigger-editor";
import "./ha-automation-sidebar-card";
@@ -40,8 +39,6 @@ export default class HaAutomationSidebarTrigger extends LitElement {
@property({ attribute: "sidebar-key" }) public sidebarKey?: string;
@state() private _requestShowId = false;
@state() private _warnings?: string[];
@query(".sidebar-editor")
@@ -49,7 +46,6 @@ export default class HaAutomationSidebarTrigger extends LitElement {
protected willUpdate(changedProperties) {
if (changedProperties.has("config")) {
this._requestShowId = false;
this._warnings = undefined;
if (this.config) {
this.yamlMode = this.config.yamlMode;
@@ -103,23 +99,6 @@ export default class HaAutomationSidebarTrigger extends LitElement {
<span class="shortcut-placeholder ${isMac ? "mac" : ""}"></span>
</div>
</ha-md-menu-item>
${!this.yamlMode &&
!("id" in this.config.config) &&
!this._requestShowId
? html`<ha-md-menu-item
slot="menu-items"
.clickAction=${this._showTriggerId}
.disabled=${this.disabled || type === "list"}
>
<ha-svg-icon slot="start" .path=${mdiIdentifier}></ha-svg-icon>
<div class="overflow-label">
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.edit_id"
)}
<span class="shortcut-placeholder ${isMac ? "mac" : ""}"></span>
</div>
</ha-md-menu-item>`
: nothing}
<ha-md-divider
slot="menu-items"
@@ -270,7 +249,6 @@ export default class HaAutomationSidebarTrigger extends LitElement {
@value-changed=${this._valueChangedSidebar}
@yaml-changed=${this._yamlChangedSidebar}
.uiSupported=${this.config.uiSupported}
.showId=${this._requestShowId}
.yamlMode=${this.yamlMode}
.disabled=${this.disabled}
@ui-mode-not-available=${this._handleUiModeNotAvailable}
@@ -313,11 +291,7 @@ export default class HaAutomationSidebarTrigger extends LitElement {
fireEvent(this, "toggle-yaml-mode");
};
private _showTriggerId = () => {
this._requestShowId = true;
};
static styles = sidebarEditorStyles;
static styles = [sidebarEditorStyles, overflowStyles];
}
declare global {

View File

@@ -238,6 +238,9 @@ export const sidebarEditorStyles = css`
.description {
padding-top: 16px;
}
`;
export const overflowStyles = css`
.overflow-label {
display: flex;
justify-content: space-between;

View File

@@ -27,8 +27,6 @@ export default class HaAutomationTriggerEditor extends LitElement {
@property({ type: Boolean, attribute: "supported" }) public uiSupported =
false;
@property({ type: Boolean, attribute: "show-id" }) public showId = false;
@property({ type: Boolean, attribute: "sidebar" }) public inSidebar = false;
@query("ha-yaml-editor") public yamlEditor?: HaYamlEditor;
@@ -37,7 +35,6 @@ export default class HaAutomationTriggerEditor extends LitElement {
const type = isTriggerList(this.trigger) ? "list" : this.trigger.trigger;
const yamlMode = this.yamlMode || !this.uiSupported;
const showId = "id" in this.trigger || this.showId;
return html`
<div
@@ -73,19 +70,23 @@ export default class HaAutomationTriggerEditor extends LitElement {
></ha-yaml-editor>
`
: html`
${showId && !isTriggerList(this.trigger)
${!isTriggerList(this.trigger)
? html`
<ha-textfield
.label=${this.hass.localize(
.label=${`${this.hass.localize(
"ui.panel.config.automation.editor.triggers.id"
)}
)} (${this.hass.localize(
"ui.panel.config.automation.editor.triggers.optional"
)})`}
.value=${this.trigger.id || ""}
.disabled=${this.disabled}
@change=${this._idChanged}
>
</ha-textfield>
.helper=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.id_helper"
)}
></ha-textfield>
`
: ""}
: nothing}
<div @value-changed=${this._onUiChanged}>
${dynamicElement(`ha-automation-trigger-${type}`, {
hass: this.hass,

View File

@@ -1,12 +1,13 @@
import { consume } from "@lit/context";
import {
mdiAppleKeyboardCommand,
mdiArrowDown,
mdiArrowUp,
mdiContentCopy,
mdiContentCut,
mdiDelete,
mdiDotsVertical,
mdiIdentifier,
mdiInformation,
mdiPlayCircleOutline,
mdiPlaylistEdit,
mdiPlusCircleMultipleOutline,
@@ -15,7 +16,7 @@ import {
} from "@mdi/js";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import { dump } from "js-yaml";
import type { CSSResultGroup, PropertyValues } from "lit";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
@@ -38,6 +39,7 @@ import "../../../../components/ha-icon-button";
import "../../../../components/ha-md-button-menu";
import "../../../../components/ha-md-divider";
import "../../../../components/ha-md-menu-item";
import "../../../../components/ha-svg-icon";
import type {
AutomationClipboard,
Trigger,
@@ -55,9 +57,10 @@ import {
showPromptDialog,
} from "../../../../dialogs/generic/show-dialog-box";
import type { HomeAssistant } from "../../../../types";
import { isMac } from "../../../../util/is_mac";
import { showToast } from "../../../../util/toast";
import "../ha-automation-editor-warning";
import { rowStyles } from "../styles";
import { overflowStyles, rowStyles } from "../styles";
import "./ha-automation-trigger-editor";
import type HaAutomationTriggerEditor from "./ha-automation-trigger-editor";
import "./types/ha-automation-trigger-calendar";
@@ -133,8 +136,6 @@ export default class HaAutomationTriggerRow extends LitElement {
@state() private _selected = false;
@state() private _requestShowId = false;
@state() private _warnings?: string[];
@property({ type: Boolean }) public narrow = false;
@@ -163,6 +164,20 @@ export default class HaAutomationTriggerRow extends LitElement {
private _triggerUnsub?: Promise<UnsubscribeFunc>;
private _renderOverflowLabel(label: string, shortcut?: TemplateResult) {
return html`
<div class="overflow-label">
${label}
${this.optionsInSidebar && !this.narrow
? shortcut ||
html`<span
class="shortcut-placeholder ${isMac ? "mac" : ""}"
></span>`
: nothing}
</div>
`;
}
private _renderRow() {
const type = this._getType(this.trigger);
@@ -182,8 +197,7 @@ export default class HaAutomationTriggerRow extends LitElement {
<slot name="icons" slot="icons"></slot>
${!this.optionsInSidebar
? html`<ha-md-button-menu
<ha-md-button-menu
quick
slot="icons"
@click=${preventDefaultStopPropagation}
@@ -202,20 +216,12 @@ export default class HaAutomationTriggerRow extends LitElement {
.clickAction=${this._renameTrigger}
.disabled=${this.disabled || type === "list"}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.rename"
)}
<ha-svg-icon slot="start" .path=${mdiRenameBox}></ha-svg-icon>
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._showTriggerId}
.disabled=${this.disabled || type === "list"}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.edit_id"
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.rename"
)
)}
<ha-svg-icon slot="start" .path=${mdiIdentifier}></ha-svg-icon>
</ha-md-menu-item>
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
@@ -224,61 +230,103 @@ export default class HaAutomationTriggerRow extends LitElement {
.clickAction=${this._duplicateTrigger}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.duplicate"
)}
<ha-svg-icon
slot="start"
.path=${mdiPlusCircleMultipleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.duplicate"
)
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._copyTrigger}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.copy"
)}
<ha-svg-icon slot="start" .path=${mdiContentCopy}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.copy"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span>C</span>
</span>`
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._cutTrigger}
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.cut"
)}
<ha-svg-icon slot="start" .path=${mdiContentCut}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.triggers.cut"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span>X</span>
</span>`
)}
</ha-md-menu-item>
${!this.optionsInSidebar
? html`
<ha-md-menu-item
.clickAction=${this._moveUp}
.disabled=${this.disabled || this.first}
.disabled=${this.disabled || !!this.first}
>
${this.hass.localize("ui.panel.config.automation.editor.move_up")}
${this.hass.localize(
"ui.panel.config.automation.editor.move_up"
)}
<ha-svg-icon slot="start" .path=${mdiArrowUp}></ha-svg-icon
></ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._moveDown}
.disabled=${this.disabled || this.last}
.disabled=${this.disabled || !!this.last}
>
${this.hass.localize(
"ui.panel.config.automation.editor.move_down"
)}
<ha-svg-icon slot="start" .path=${mdiArrowDown}></ha-svg-icon
></ha-md-menu-item>
`
: nothing}
<ha-md-menu-item
.clickAction=${this._toggleYamlMode}
.disabled=${!supported || !!this._warnings}
>
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${!yamlMode ? "yaml" : "ui"}`
)}
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
`ui.panel.config.automation.editor.edit_${!yamlMode ? "yaml" : "ui"}`
)
)}
</ha-md-menu-item>
<ha-md-divider role="separator" tabindex="-1"></ha-md-divider>
@@ -287,37 +335,54 @@ export default class HaAutomationTriggerRow extends LitElement {
.clickAction=${this._onDisable}
.disabled=${this.disabled || type === "list"}
>
${"enabled" in this.trigger && this.trigger.enabled === false
? this.hass.localize(
"ui.panel.config.automation.editor.actions.enable"
)
: this.hass.localize(
"ui.panel.config.automation.editor.actions.disable"
)}
<ha-svg-icon
slot="start"
.path=${"enabled" in this.trigger &&
this.trigger.enabled === false
.path=${"enabled" in this.trigger && this.trigger.enabled === false
? mdiPlayCircleOutline
: mdiStopCircleOutline}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
`ui.panel.config.automation.editor.actions.${"enabled" in this.trigger && this.trigger.enabled === false ? "enable" : "disable"}`
)
)}
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._onDelete}
class="warning"
.disabled=${this.disabled}
>
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
<ha-svg-icon
class="warning"
slot="start"
.path=${mdiDelete}
></ha-svg-icon>
${this._renderOverflowLabel(
this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
),
html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span
>${this.hass.localize(
"ui.panel.config.automation.editor.del"
)}</span
>
</span>`
)}
</ha-md-menu-item>
</ha-md-button-menu>`
: nothing}
</ha-md-button-menu>
${!this.optionsInSidebar
? html`${this._warnings
? html`<ha-automation-editor-warning
@@ -331,7 +396,6 @@ export default class HaAutomationTriggerRow extends LitElement {
.trigger=${this.trigger}
.disabled=${this.disabled}
.yamlMode=${this._yamlMode}
.showId=${this._requestShowId}
.uiSupported=${supported}
@ui-mode-not-available=${this._handleUiModeNotAvailable}
></ha-automation-trigger-editor>`
@@ -380,6 +444,7 @@ export default class HaAutomationTriggerRow extends LitElement {
${this.hass.localize(
"ui.panel.config.automation.editor.triggers.triggered"
)}
<ha-svg-icon .path=${mdiInformation}></ha-svg-icon>
</div>
</ha-card>
`;
@@ -630,14 +695,6 @@ export default class HaAutomationTriggerRow extends LitElement {
}
};
private _showTriggerId = () => {
this._requestShowId = true;
if (!this.optionsInSidebar) {
this.expand();
}
};
private _duplicateTrigger = () => {
fireEvent(this, "duplicate");
};
@@ -682,7 +739,7 @@ export default class HaAutomationTriggerRow extends LitElement {
fireEvent(this, "move-down");
};
private _toggleYamlMode = () => {
private _toggleYamlMode = (item?: HTMLElement) => {
if (this._yamlMode) {
this._switchUiMode();
} else {
@@ -691,6 +748,8 @@ export default class HaAutomationTriggerRow extends LitElement {
if (!this.optionsInSidebar) {
this.expand();
} else if (item) {
this.openSidebar();
}
};
@@ -716,6 +775,7 @@ export default class HaAutomationTriggerRow extends LitElement {
static get styles(): CSSResultGroup {
return [
rowStyles,
overflowStyles,
css`
.triggered {
cursor: pointer;
@@ -740,9 +800,20 @@ export default class HaAutomationTriggerRow extends LitElement {
--ha-card-border-radius,
var(--ha-border-radius-lg)
);
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
line-height: 1;
padding: 0;
}
.triggered ha-svg-icon {
--mdc-icon-size: 16px;
}
.triggered.active {
max-height: 100px;
padding: 4px;
}
.triggered:hover {
opacity: 0.8;

View File

@@ -1,19 +1,30 @@
import {
mdiAppleKeyboardCommand,
mdiDelete,
mdiDotsVertical,
mdiPlaylistEdit,
} from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { fireEvent } from "../../../common/dom/fire_event";
import { preventDefaultStopPropagation } from "../../../common/dom/prevent_default_stop_propagation";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import type { LocalizeKeys } from "../../../common/translations/localize";
import "../../../components/ha-automation-row";
import type { HaAutomationRow } from "../../../components/ha-automation-row";
import "../../../components/ha-card";
import "../../../components/ha-md-button-menu";
import "../../../components/ha-md-menu-item";
import type { ScriptFieldSidebarConfig } from "../../../data/automation";
import type { Field } from "../../../data/script";
import { SELECTOR_SELECTOR_BUILDING_BLOCKS } from "../../../data/selector/selector_selector";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types";
import { indentStyle } from "../automation/styles";
import { isMac } from "../../../util/is_mac";
import { indentStyle, overflowStyles } from "../automation/styles";
import "./ha-script-field-selector-editor";
import type HaScriptFieldSelectorEditor from "./ha-script-field-selector-editor";
@@ -66,6 +77,64 @@ export default class HaScriptFieldRow extends LitElement {
.highlight=${this.highlight}
@delete-row=${this._onDelete}
>
<ha-md-button-menu
quick
slot="icons"
@click=${preventDefaultStopPropagation}
@keydown=${stopPropagation}
@closed=${stopPropagation}
positioning="fixed"
anchor-corner="end-end"
menu-corner="start-end"
>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-md-menu-item .clickAction=${this._toggleYamlMode}>
<ha-svg-icon slot="start" .path=${mdiPlaylistEdit}></ha-svg-icon>
<div class="overflow-label">
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
)}
<span class="shortcut-placeholder ${isMac ? "mac" : ""}"></span>
</div>
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._onDelete}
.disabled=${this.disabled}
class="warning"
>
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
<div class="overflow-label">
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
${!this.narrow
? html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span
>${this.hass.localize(
"ui.panel.config.automation.editor.del"
)}</span
>
</span>`
: nothing}
</div>
</ha-md-menu-item>
</ha-md-button-menu>
<h3 slot="header">${this.key}</h3>
<slot name="icons" slot="icons"></slot>
@@ -97,6 +166,71 @@ export default class HaScriptFieldRow extends LitElement {
"ui.panel.config.script.editor.field.selector"
)}
</h3>
<ha-md-button-menu
quick
slot="icons"
@click=${preventDefaultStopPropagation}
@keydown=${stopPropagation}
@closed=${stopPropagation}
positioning="fixed"
anchor-corner="end-end"
menu-corner="start-end"
>
<ha-icon-button
slot="trigger"
.label=${this.hass.localize("ui.common.menu")}
.path=${mdiDotsVertical}
></ha-icon-button>
<ha-md-menu-item
.clickAction=${this._toggleYamlMode}
selector-row
>
<ha-svg-icon
slot="start"
.path=${mdiPlaylistEdit}
></ha-svg-icon>
<div class="overflow-label">
${this.hass.localize(
`ui.panel.config.automation.editor.edit_${!this._yamlMode ? "yaml" : "ui"}`
)}
<span
class="shortcut-placeholder ${isMac ? "mac" : ""}"
></span>
</div>
</ha-md-menu-item>
<ha-md-menu-item
.clickAction=${this._onDelete}
.disabled=${this.disabled}
class="warning"
>
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
<div class="overflow-label">
${this.hass.localize(
"ui.panel.config.automation.editor.actions.delete"
)}
${!this.narrow
? html`<span class="shortcut">
<span
>${isMac
? html`<ha-svg-icon
slot="start"
.path=${mdiAppleKeyboardCommand}
></ha-svg-icon>`
: this.hass.localize(
"ui.panel.config.automation.editor.ctrl"
)}</span
>
<span>+</span>
<span
>${this.hass.localize(
"ui.panel.config.automation.editor.del"
)}</span
>
</span>`
: nothing}
</div>
</ha-md-menu-item>
</ha-md-button-menu>
</ha-automation-row>
</ha-card>
${typeof this.field.selector === "object" &&
@@ -243,8 +377,12 @@ export default class HaScriptFieldRow extends LitElement {
}
}
private _toggleYamlMode = () => {
private _toggleYamlMode = (item?: HTMLElement) => {
this._yamlMode = !this._yamlMode;
if (item) {
this.openSidebar(item.hasAttribute("selector-row"));
}
};
private _onDelete = () => {
@@ -279,6 +417,7 @@ export default class HaScriptFieldRow extends LitElement {
return [
haStyle,
indentStyle,
overflowStyles,
css`
.disabled {
opacity: 0.5;

View File

@@ -3883,6 +3883,8 @@
"add": "Add trigger",
"search": "Search trigger",
"id": "Trigger ID",
"id_helper": "Helps identify each run based on which trigger fired.",
"optional": "Optional",
"edit_id": "Edit ID",
"duplicate": "[%key:ui::common::duplicate%]",
"re_order": "Re-order",
@@ -4287,7 +4289,7 @@
},
"trigger": {
"label": "Triggered by",
"no_triggers": "No triggers have an ID set. Use the three-dot menu on a trigger and select Edit ID to assign one.",
"no_triggers": "There are no triggers with ID's set in this automation. Edit a trigger and give it a Trigger ID name.",
"id": "Trigger",
"description": {
"picker": "If the automation has been triggered by a specific trigger.",