-
-
- ${this._group
- ? groupName
- : this.hass.localize(
- `ui.panel.config.automation.editor.${this._params.type}s.add`
- )}
- ${this._group && this._group !== this._params.group
- ? html``
- : html``}
-
-
-
+
+
+ ${this._narrow && this._selectedGroup
+ ? groupName
+ : typeTitle}
+
+ ${this._narrow && this._selectedGroup
+ ? html`${typeTitle}`
+ : nothing}
+ ${this._narrow && this._selectedGroup
+ ? html``
+ : html``}
+
+ ${!this._narrow || !this._selectedGroup
+ ? html`
+
+ `
+ : nothing}
+ ${this._params?.type !== "trigger" &&
+ !this._filter &&
+ (!this._narrow || !this._selectedGroup)
+ ? html``
+ : nothing}
+
+
- ${this._params.clipboardItem &&
- !this._filter &&
- (!this._group ||
- items.find((item) => item.key === this._params!.clipboardItem))
+ ${this._params!.clipboardItem && !this._filter
? html`
${this.hass.localize(
- `ui.panel.config.automation.editor.${this._params.type}s.paste`
+ `ui.panel.config.automation.editor.${automationElementType}s.paste`
)}
${this.hass.localize(
// @ts-ignore
- `ui.panel.config.automation.editor.${this._params.type}s.type.${this._params.clipboardItem}.label`
+ `ui.panel.config.automation.editor.${automationElementType}s.type.${this._params.clipboardItem}.label`
)}
@@ -611,74 +799,213 @@ class DialogAddAutomationElement
slot="start"
.path=${mdiContentPaste}
>
+ >
`
: nothing}
- ${repeat(
- items,
- (item) => item.key,
- (item) => html`
-
- ${item.name}
- ${item.description}
- ${item.icon
- ? html`${item.icon}`
- : item.iconPath
- ? html``
- : nothing}
- ${item.group
- ? html``
- : html``}
-
+ ${collections.map(
+ (collection, index) => html`
+ ${collection.titleKey
+ ? html`
+ ${this.hass.localize(collection.titleKey)}
+
`
+ : nothing}
+ ${repeat(
+ collection.groups,
+ (item) => item.key,
+ (item) => html`
+
+ ${item.name}
+ ${item.icon
+ ? html`${item.icon}`
+ : item.iconPath
+ ? html``
+ : nothing}
+
+ `
+ )}
`
)}
-
+
+ ${filteredBlockItems && filteredBlockItems.length
+ ? this._renderItemList(
+ this.hass.localize(`ui.panel.config.automation.editor.blocks`),
+ filteredBlockItems
+ )
+ : nothing}
+ ${this._tab === "groups" && !this._selectedGroup && !this._filter
+ ? this.hass.localize(
+ `ui.panel.config.automation.editor.${automationElementType}s.select`
+ )
+ : !items?.length &&
+ this._filter &&
+ (!filteredBlockItems || !filteredBlockItems.length)
+ ? html`${this.hass.localize(
+ `ui.panel.config.automation.editor.${automationElementType}s.empty_search`,
+ {
+ term: html`‘${this._filter}’`,
+ }
+ )}`
+ : this._renderItemList(
+ this.hass.localize(
+ `ui.panel.config.automation.editor.${automationElementType}s.name`
+ ),
+ items
+ )}
+
+
`;
}
+ private _renderItemList(title, items?: ListItem[]) {
+ if (!items) {
+ return nothing;
+ }
+
+ return html`
+
+ ${title}
+
+
+ ${repeat(
+ items,
+ (item) => item.key,
+ (item) => html`
+
+ ${item.name}
+ ${item.description}
+ ${item.icon
+ ? html`${item.icon}`
+ : item.iconPath
+ ? html``
+ : nothing}
+ ${item.group
+ ? html``
+ : html``}
+
+ `
+ )}
+
+ `;
+ }
+
+ protected render() {
+ if (!this._params) {
+ return nothing;
+ }
+
+ if (this._bottomSheetMode) {
+ return html`
+
+ ${this._renderContent()}
+
+ `;
+ }
+
+ return html`
+
+ ${this._renderContent()}
+
+ `;
+ }
+
+ public disconnectedCallback(): void {
+ super.disconnectedCallback();
+ window.removeEventListener("resize", this._updateNarrow);
+ this._removeSearchKeybindings();
+ }
+
+ private _updateNarrow = () => {
+ this._narrow =
+ window.matchMedia("(max-width: 870px)").matches ||
+ window.matchMedia("(max-height: 500px)").matches;
+ };
+
+ private _close() {
+ this._open = false;
+ }
+
private _back() {
- this._dialog!.scrollToPos(0, 0);
- if (this._filter) {
- this._filter = "";
+ this._selectedGroup = undefined;
+ }
+
+ private _groupSelected(ev) {
+ const group = ev.currentTarget;
+ if (this._selectedGroup === group.value) {
+ this._selectedGroup = undefined;
+ this._selectedCollectionIndex = undefined;
return;
}
- if (this._prev) {
- this._group = this._prev;
- this._prev = undefined;
- return;
- }
- this._group = undefined;
+ this._selectedGroup = group.value;
+ this._selectedCollectionIndex = ev.currentTarget.index;
+ requestAnimationFrame(() => {
+ this._itemsListElement?.scrollTo(0, 0);
+ });
}
private _selected(ev) {
- this._dialog!.scrollToPos(0, 0);
const item = ev.currentTarget;
- if (item.group) {
- this._prev = this._group;
- this._group = item.value;
- return;
- }
this._params!.add(item.value);
this.closeDialog();
}
- private _filterChanged(ev) {
+ private _debounceFilterChanged = debounce(
+ (ev) => this._filterChanged(ev),
+ 200
+ );
+
+ private _filterChanged = (ev) => {
this._filter = ev.detail.value;
- }
+ };
private _addClipboard = () => {
if (this._params?.clipboardItem) {
@@ -704,37 +1031,220 @@ class DialogAddAutomationElement
};
}
+ private _switchTab(ev) {
+ this._tab = ev.detail.value;
+ }
+
+ @eventOptions({ passive: true })
+ private _onItemsScroll(ev) {
+ const top = ev.target.scrollTop ?? 0;
+ this._itemsScrolled = top > 0;
+ }
+
+ private _onSearchFocus(ev) {
+ this._removeKeyboardShortcuts = tinykeys(ev.target, {
+ ArrowDown: this._focusSearchList,
+ });
+ }
+
+ private _removeSearchKeybindings() {
+ this._removeKeyboardShortcuts?.();
+ }
+
+ private _focusSearchList = (ev) => {
+ if (!this._filter || !this._itemsListFirstElement) {
+ return;
+ }
+
+ ev.preventDefault();
+ this._itemsListFirstElement.focus();
+ };
+
static get styles(): CSSResultGroup {
return [
- haStyle,
- haStyleDialog,
css`
- ha-dialog {
- --dialog-content-padding: 0;
- --mdc-dialog-max-height: 60vh;
- --mdc-dialog-max-height: 60dvh;
+ ha-bottom-sheet {
+ --ha-bottom-sheet-height: 90vh;
+ --ha-bottom-sheet-height: calc(100dvh - var(--ha-space-12));
+ --ha-bottom-sheet-max-height: var(--ha-bottom-sheet-height);
+ --ha-bottom-sheet-max-width: 888px;
+ --ha-bottom-sheet-padding: var(--ha-space-0);
+ --ha-bottom-sheet-surface-background: var(--card-background-color);
}
- @media all and (min-width: 550px) {
- ha-dialog {
- --mdc-dialog-min-width: 500px;
- }
- }
- ha-icon-next {
- width: 24px;
- }
- ha-md-list {
- max-height: 468px;
- max-width: 100vw;
- --md-list-item-leading-space: 24px;
- --md-list-item-trailing-space: 24px;
- --md-list-item-supporting-text-font: var(--ha-font-size-s);
- }
- ha-md-list-item img {
- width: 24px;
+
+ ha-wa-dialog {
+ --dialog-content-padding: var(--ha-space-0);
+ --ha-dialog-width-md: 888px;
+ --ha-dialog-min-height: min(
+ 648px,
+ calc(
+ 100vh - max(
+ var(--safe-area-inset-bottom),
+ var(--ha-space-4)
+ ) - max(var(--safe-area-inset-top), var(--ha-space-4))
+ )
+ );
+ --ha-dialog-min-height: min(
+ 648px,
+ calc(
+ 100dvh - max(
+ var(--safe-area-inset-bottom),
+ var(--ha-space-4)
+ ) - max(var(--safe-area-inset-top), var(--ha-space-4))
+ )
+ );
+ --ha-dialog-max-height: var(--ha-dialog-min-height);
}
+
search-input {
display: block;
- margin: 0 16px;
+ margin: var(--ha-space-0) var(--ha-space-4);
+ }
+
+ ha-button-toggle-group {
+ --ha-button-toggle-group-padding: var(--ha-space-3) var(--ha-space-4)
+ 0;
+ }
+
+ .content {
+ flex: 1;
+ min-height: 0;
+ height: 100%;
+ display: flex;
+ }
+
+ ha-md-list {
+ padding: 0;
+ }
+
+ .items ha-md-list,
+ .groups {
+ padding-bottom: max(var(--safe-area-inset-bottom), var(--ha-space-3));
+ }
+
+ .groups {
+ overflow: auto;
+ flex: 3;
+ border-radius: var(--ha-border-radius-xl);
+ border: 1px solid var(--ha-color-border-neutral-quiet);
+ margin: var(--ha-space-3);
+ margin-inline-end: var(--ha-space-0);
+ --md-list-item-leading-space: var(--ha-space-3);
+ --md-list-item-trailing-space: var(--md-list-item-leading-space);
+ --md-list-item-bottom-space: var(--ha-space-1);
+ --md-list-item-top-space: var(--md-list-item-bottom-space);
+ --md-list-item-supporting-text-font: var(--ha-font-size-s);
+ --md-list-item-one-line-container-height: var(--ha-space-10);
+ }
+ ha-bottom-sheet .groups {
+ margin: var(--ha-space-3);
+ }
+ .groups .selected {
+ background-color: var(--ha-color-fill-primary-normal-active);
+ --md-list-item-label-text-color: var(--primary-color);
+ --icon-primary-color: var(--primary-color);
+ }
+ .groups .selected ha-svg-icon {
+ color: var(--primary-color);
+ }
+
+ .collection-title {
+ background-color: var(--ha-color-fill-neutral-quiet-resting);
+ padding: var(--ha-space-1) var(--ha-space-2);
+ font-weight: var(--ha-font-weight-bold);
+ color: var(--secondary-text-color);
+ top: 0;
+ position: sticky;
+ min-height: var(--ha-space-6);
+ display: flex;
+ align-items: center;
+ z-index: 1;
+ }
+
+ .items {
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ flex: 7;
+ }
+
+ ha-wa-dialog .items {
+ margin-top: var(--ha-space-3);
+ }
+
+ ha-bottom-sheet .groups {
+ padding-bottom: max(var(--safe-area-inset-bottom), var(--ha-space-4));
+ }
+
+ .items.hidden,
+ .groups.hidden {
+ display: none;
+ }
+ .items.blank,
+ .items.empty-search {
+ border-radius: var(--ha-border-radius-xl);
+ background-color: var(--ha-color-surface-default);
+ align-items: center;
+ color: var(--ha-color-text-secondary);
+ padding: var(--ha-space-0);
+ margin: var(--ha-space-3) var(--ha-space-4)
+ max(var(--safe-area-inset-bottom), var(--ha-space-3));
+ }
+
+ .items ha-md-list {
+ --md-list-item-two-line-container-height: var(--ha-space-12);
+ --md-list-item-leading-space: var(--ha-space-3);
+ --md-list-item-trailing-space: var(--md-list-item-leading-space);
+ --md-list-item-bottom-space: var(--ha-space-2);
+ --md-list-item-top-space: var(--md-list-item-bottom-space);
+ --md-list-item-supporting-text-font: var(--ha-font-size-s);
+ gap: var(--ha-space-2);
+ padding: var(--ha-space-0) var(--ha-space-4);
+ }
+ .items ha-md-list ha-md-list-item {
+ border-radius: var(--ha-border-radius-lg);
+ border: 1px solid var(--ha-color-border-neutral-quiet);
+ }
+
+ .items.blank {
+ justify-content: center;
+ }
+ .items.empty-search {
+ padding-top: var(--ha-space-6);
+ justify-content: start;
+ }
+
+ .items-title {
+ position: sticky;
+ display: flex;
+ align-items: center;
+ font-weight: var(--ha-font-weight-medium);
+ padding-top: var(--ha-space-2);
+ padding-bottom: var(--ha-space-2);
+ padding-inline-start: var(--ha-space-8);
+ padding-inline-end: var(--ha-space-3);
+ top: 0;
+ z-index: 1;
+ background-color: var(--card-background-color);
+ }
+ ha-bottom-sheet .items-title {
+ padding-top: var(--ha-space-3);
+ }
+ .items-title.scrolled:first-of-type {
+ box-shadow: var(--bar-box-shadow);
+ border-bottom: 1px solid var(--ha-color-border-neutral-quiet);
+ }
+
+ ha-icon-next {
+ width: var(--ha-space-6);
+ }
+
+ ha-md-list-item.paste {
+ border-bottom: 1px solid var(--ha-color-border-neutral-quiet);
+ }
+
+ ha-svg-icon.plus {
+ color: var(--primary-color);
}
.shortcut-label {
display: flex;
@@ -746,7 +1256,7 @@ class DialogAddAutomationElement
font-size: var(--ha-font-size-s);
}
.shortcut-label .shortcut {
- --mdc-icon-size: 12px;
+ --mdc-icon-size: var(--ha-space-3);
display: inline-flex;
flex-direction: row;
align-items: center;
diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts
index c7cb37057f..755abe29da 100644
--- a/src/panels/config/automation/condition/ha-automation-condition.ts
+++ b/src/panels/config/automation/condition/ha-automation-condition.ts
@@ -214,17 +214,6 @@ export default class HaAutomationCondition extends LitElement {
"ui.panel.config.automation.editor.conditions.add"
)}
-
-
- ${this.hass.localize(
- "ui.panel.config.automation.editor.conditions.add_building_block"
- )}
-
@@ -242,15 +231,6 @@ export default class HaAutomationCondition extends LitElement {
});
}
- private _addConditionBuildingBlockDialog() {
- showAddAutomationElementDialog(this, {
- type: "condition",
- add: this._addCondition,
- clipboardItem: this._clipboard?.condition?.condition,
- group: "building_blocks",
- });
- }
-
private _addCondition = (value) => {
let conditions: Condition[];
if (value === PASTE_VALUE) {
diff --git a/src/panels/config/automation/show-add-automation-element-dialog.ts b/src/panels/config/automation/show-add-automation-element-dialog.ts
index 99c014c748..90a4ab417c 100644
--- a/src/panels/config/automation/show-add-automation-element-dialog.ts
+++ b/src/panels/config/automation/show-add-automation-element-dialog.ts
@@ -1,45 +1,11 @@
import { fireEvent } from "../../../common/dom/fire_event";
-import type { ACTION_GROUPS } from "../../../data/action";
-import type { ActionType } from "../../../data/script";
export const PASTE_VALUE = "__paste__";
-// These will be replaced with the correct action
-export const VIRTUAL_ACTIONS: Record<
- keyof (typeof ACTION_GROUPS)["building_blocks"]["members"],
- ActionType
-> = {
- repeat_count: {
- repeat: {
- count: 2,
- sequence: [],
- },
- },
- repeat_while: {
- repeat: {
- while: [],
- sequence: [],
- },
- },
- repeat_until: {
- repeat: {
- until: [],
- sequence: [],
- },
- },
- repeat_for_each: {
- repeat: {
- for_each: {},
- sequence: [],
- },
- },
-} as const;
-
export interface AddAutomationElementDialogParams {
type: "trigger" | "condition" | "action";
add: (key: string) => void;
clipboardItem: string | undefined;
- group?: string;
}
const loadDialog = () => import("./add-automation-element-dialog");
diff --git a/src/translations/en.json b/src/translations/en.json
index 7eed0ebf66..cd87c5f678 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -3918,7 +3918,6 @@
"edit_yaml": "Edit in YAML",
"edit_ui": "Edit in visual editor",
"copy_to_clipboard": "Copy to clipboard",
- "search_in": "Search · {group}",
"unknown_entity": "unknown entity",
"edit_unknown_device": "Editor not available for unknown device",
"switch_ui_yaml_error": "There are currently YAML errors in the automation, and it cannot be parsed. Switching to UI mode may cause pending changes to be lost. Press cancel to correct any errors before proceeding to prevent loss of pending changes, or continue if you are sure.",
@@ -3933,6 +3932,7 @@
"item_pasted": "{item} pasted",
"ctrl": "Ctrl",
"del": "Del",
+ "blocks": "Blocks",
"triggers": {
"name": "Triggers",
"header": "When",
@@ -3940,7 +3940,7 @@
"learn_more": "Learn more about triggers",
"triggered": "Triggered",
"add": "Add trigger",
- "search": "Search trigger",
+ "empty_search": "No triggers found for {term}",
"id": "Trigger ID",
"id_helper": "Helps identify each run based on which trigger fired.",
"optional": "Optional",
@@ -3961,14 +3961,16 @@
"trigger": "Trigger",
"copied_to_clipboard": "Trigger copied to clipboard",
"cut_to_clipboard": "Trigger cut to clipboard",
+ "select": "Select a trigger",
"groups": {
+ "device": {
+ "label": "Device"
+ },
"entity": {
- "label": "Entity",
- "description": "When something happens to an entity."
+ "label": "Entity"
},
"time_location": {
- "label": "Time and location",
- "description": "When someone enters or leaves a zone, or at a specific time."
+ "label": "Time and location"
},
"other": {
"label": "Other triggers"
@@ -4201,7 +4203,7 @@
"description": "All conditions added here need to be satisfied for the automation to run. A condition can be satisfied or not at any given time, for example: ''If {user} is home''. You can use building blocks to create more complex conditions.",
"learn_more": "Learn more about conditions",
"add": "Add condition",
- "search": "Search condition",
+ "empty_search": "No conditions and blocks found for {term}",
"add_building_block": "Add building block",
"test": "Test",
"testing_error": "Condition did not pass",
@@ -4223,21 +4225,22 @@
"condition": "Condition",
"copied_to_clipboard": "Condition copied to clipboard",
"cut_to_clipboard": "Condition cut to clipboard",
+ "select": "Select a condition",
"groups": {
+ "device": {
+ "label": "Device"
+ },
"entity": {
- "label": "Entity",
- "description": "If an entity is in a specific state."
+ "label": "Entity"
},
"time_location": {
- "label": "Time and location",
- "description": "If someone is in a zone or if the current time is before or after a specified time."
+ "label": "Time and location"
},
"other": {
"label": "Other conditions"
},
"building_blocks": {
- "label": "Building blocks",
- "description": "Build more complex conditions."
+ "label": "Building blocks"
}
},
"type": {
@@ -4368,7 +4371,7 @@
"description": "All actions added here will be performed in sequence when the automation runs. An action usually controls one of your areas, devices, or entities, for example: 'Turn on the lights'. You can use building blocks to create more complex sequences of actions.",
"learn_more": "Learn more about actions",
"add": "Add action",
- "search": "Search action",
+ "empty_search": "No actions and blocks found for {term}",
"add_building_block": "Add building block",
"invalid_action": "Invalid action",
"run": "Run action",
@@ -4392,7 +4395,11 @@
"action": "Action",
"copied_to_clipboard": "Action copied to clipboard",
"cut_to_clipboard": "Action cut to clipboard",
+ "select": "Select an action",
"groups": {
+ "device_id": {
+ "label": "Device"
+ },
"helpers": {
"label": "Helpers"
},
@@ -4400,8 +4407,7 @@
"label": "Other actions"
},
"building_blocks": {
- "label": "Building blocks",
- "description": "Build more complex sequences of actions."
+ "label": "Building blocks"
}
},
"type": {