mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-09 02:49:51 +00:00
Automation editor mobile bottom sheet (#26680)
This commit is contained in:
268
src/components/ha-bottom-sheet.ts
Normal file
268
src/components/ha-bottom-sheet.ts
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
import { css, html, LitElement } from "lit";
|
||||||
|
import { customElement, query, state } from "lit/decorators";
|
||||||
|
import { styleMap } from "lit/directives/style-map";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
|
||||||
|
const ANIMATION_DURATION_MS = 300;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bottom sheet component that slides up from the bottom of the screen.
|
||||||
|
*
|
||||||
|
* The bottom sheet provides a draggable interface that allows users to resize
|
||||||
|
* the sheet by dragging the handle at the top. It supports both mouse and touch
|
||||||
|
* interactions and automatically closes when dragged below a 20% of screen height.
|
||||||
|
*
|
||||||
|
* @fires bottom-sheet-closed - Fired when the bottom sheet is closed
|
||||||
|
*
|
||||||
|
* @cssprop --ha-bottom-sheet-border-width - Border width for the sheet
|
||||||
|
* @cssprop --ha-bottom-sheet-border-style - Border style for the sheet
|
||||||
|
* @cssprop --ha-bottom-sheet-border-color - Border color for the sheet
|
||||||
|
*/
|
||||||
|
@customElement("ha-bottom-sheet")
|
||||||
|
export class HaBottomSheet extends LitElement {
|
||||||
|
@query("dialog") private _dialog!: HTMLDialogElement;
|
||||||
|
|
||||||
|
private _dragging = false;
|
||||||
|
|
||||||
|
private _dragStartY = 0;
|
||||||
|
|
||||||
|
private _initialSize = 0;
|
||||||
|
|
||||||
|
@state() private _dialogMaxViewpointHeight = 70;
|
||||||
|
|
||||||
|
@state() private _dialogViewportHeight?: number;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`<dialog
|
||||||
|
open
|
||||||
|
@transitionend=${this._handleTransitionEnd}
|
||||||
|
style=${styleMap({
|
||||||
|
height: this._dialogViewportHeight
|
||||||
|
? `${this._dialogViewportHeight}vh`
|
||||||
|
: "auto",
|
||||||
|
maxHeight: `${this._dialogMaxViewpointHeight}vh`,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<div class="handle-wrapper">
|
||||||
|
<div
|
||||||
|
@mousedown=${this._handleMouseDown}
|
||||||
|
@touchstart=${this._handleTouchStart}
|
||||||
|
class="handle"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
|
</dialog>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected firstUpdated(changedProperties) {
|
||||||
|
super.firstUpdated(changedProperties);
|
||||||
|
this._openSheet();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _openSheet() {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
// trigger opening animation
|
||||||
|
this._dialog.classList.add("show");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeSheet() {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
this._dialog.classList.remove("show");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleTransitionEnd() {
|
||||||
|
if (this._dialog.classList.contains("show")) {
|
||||||
|
// after show animation is done
|
||||||
|
// - set the height to the natural height, to prevent content shift when switch content
|
||||||
|
// - set max height to 90vh, so it opens at max 70vh but can be resized to 90vh
|
||||||
|
this._dialogViewportHeight =
|
||||||
|
(this._dialog.offsetHeight / window.innerHeight) * 100;
|
||||||
|
this._dialogMaxViewpointHeight = 90;
|
||||||
|
} else {
|
||||||
|
// after close animation is done close dialog element and fire closed event
|
||||||
|
this._dialog.close();
|
||||||
|
fireEvent(this, "bottom-sheet-closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
|
||||||
|
// register event listeners for drag handling
|
||||||
|
document.addEventListener("mousemove", this._handleMouseMove);
|
||||||
|
document.addEventListener("mouseup", this._handleMouseUp);
|
||||||
|
document.addEventListener("touchmove", this._handleTouchMove, {
|
||||||
|
passive: false,
|
||||||
|
});
|
||||||
|
document.addEventListener("touchend", this._handleTouchEnd);
|
||||||
|
document.addEventListener("touchcancel", this._handleTouchEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
|
||||||
|
// unregister event listeners for drag handling
|
||||||
|
document.removeEventListener("mousemove", this._handleMouseMove);
|
||||||
|
document.removeEventListener("mouseup", this._handleMouseUp);
|
||||||
|
document.removeEventListener("touchmove", this._handleTouchMove);
|
||||||
|
document.removeEventListener("touchend", this._handleTouchEnd);
|
||||||
|
document.removeEventListener("touchcancel", this._handleTouchEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleMouseDown = (ev: MouseEvent) => {
|
||||||
|
this._startDrag(ev.clientY);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _handleTouchStart = (ev: TouchEvent) => {
|
||||||
|
// Prevent the browser from interpreting this as a scroll/PTR gesture.
|
||||||
|
ev.preventDefault();
|
||||||
|
this._startDrag(ev.touches[0].clientY);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _startDrag(clientY: number) {
|
||||||
|
this._dragging = true;
|
||||||
|
this._dragStartY = clientY;
|
||||||
|
this._initialSize = (this._dialog.offsetHeight / window.innerHeight) * 100;
|
||||||
|
document.body.style.setProperty("cursor", "grabbing");
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleMouseMove = (ev: MouseEvent) => {
|
||||||
|
if (!this._dragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._updateSize(ev.clientY);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _handleTouchMove = (ev: TouchEvent) => {
|
||||||
|
if (!this._dragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev.preventDefault(); // Prevent scrolling
|
||||||
|
this._updateSize(ev.touches[0].clientY);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _updateSize(clientY: number) {
|
||||||
|
const deltaY = this._dragStartY - clientY;
|
||||||
|
const viewportHeight = window.innerHeight;
|
||||||
|
const deltaVh = (deltaY / viewportHeight) * 100;
|
||||||
|
|
||||||
|
// Calculate new size and clamp between 10vh and 90vh
|
||||||
|
let newSize = this._initialSize + deltaVh;
|
||||||
|
newSize = Math.max(10, Math.min(90, newSize));
|
||||||
|
|
||||||
|
// on drag down and below 20vh
|
||||||
|
if (newSize < 20 && deltaY < 0) {
|
||||||
|
this._endDrag();
|
||||||
|
this.closeSheet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._dialogViewportHeight = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleMouseUp = () => {
|
||||||
|
this._endDrag();
|
||||||
|
};
|
||||||
|
|
||||||
|
private _handleTouchEnd = () => {
|
||||||
|
this._endDrag();
|
||||||
|
};
|
||||||
|
|
||||||
|
private _endDrag() {
|
||||||
|
if (!this._dragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._dragging = false;
|
||||||
|
document.body.style.removeProperty("cursor");
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
.handle-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: grab;
|
||||||
|
touch-action: none;
|
||||||
|
}
|
||||||
|
.handle-wrapper .handle {
|
||||||
|
height: 20px;
|
||||||
|
width: 200px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 7;
|
||||||
|
}
|
||||||
|
.handle-wrapper .handle::after {
|
||||||
|
content: "";
|
||||||
|
border-radius: 8px;
|
||||||
|
height: 4px;
|
||||||
|
background: var(--divider-color, #e0e0e0);
|
||||||
|
width: 80px;
|
||||||
|
}
|
||||||
|
.handle-wrapper .handle:active::after {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
dialog {
|
||||||
|
height: auto;
|
||||||
|
max-height: 70vh;
|
||||||
|
min-height: 30vh;
|
||||||
|
background-color: var(
|
||||||
|
--ha-dialog-surface-background,
|
||||||
|
var(--mdc-theme-surface, #fff)
|
||||||
|
);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
top: 0;
|
||||||
|
inset-inline-start: 0;
|
||||||
|
position: fixed;
|
||||||
|
width: calc(100% - 4px);
|
||||||
|
max-width: 100%;
|
||||||
|
border: none;
|
||||||
|
box-shadow: var(--wa-shadow-l);
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
top: auto;
|
||||||
|
inset-inline-end: auto;
|
||||||
|
bottom: 0;
|
||||||
|
inset-inline-start: 0;
|
||||||
|
box-shadow: 0px -8px 16px rgba(0, 0, 0, 0.2);
|
||||||
|
border-top-left-radius: var(
|
||||||
|
--ha-dialog-border-radius,
|
||||||
|
var(--ha-border-radius-2xl)
|
||||||
|
);
|
||||||
|
border-top-right-radius: var(
|
||||||
|
--ha-dialog-border-radius,
|
||||||
|
var(--ha-border-radius-2xl)
|
||||||
|
);
|
||||||
|
transform: translateY(100%);
|
||||||
|
transition: transform ${ANIMATION_DURATION_MS}ms ease;
|
||||||
|
border-top-width: var(--ha-bottom-sheet-border-width);
|
||||||
|
border-right-width: var(--ha-bottom-sheet-border-width);
|
||||||
|
border-left-width: var(--ha-bottom-sheet-border-width);
|
||||||
|
border-bottom-width: 0;
|
||||||
|
border-style: var(--ha-bottom-sheet-border-style);
|
||||||
|
border-color: var(--ha-bottom-sheet-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-bottom-sheet": HaBottomSheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"bottom-sheet-closed": undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -642,9 +642,6 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public openSidebar(action?: Action): void {
|
public openSidebar(action?: Action): void {
|
||||||
if (this.narrow) {
|
|
||||||
this.scrollIntoView();
|
|
||||||
}
|
|
||||||
const sidebarAction = action ?? this.action;
|
const sidebarAction = action ?? this.action;
|
||||||
const actionType = getAutomationActionType(sidebarAction);
|
const actionType = getAutomationActionType(sidebarAction);
|
||||||
|
|
||||||
@@ -670,6 +667,13 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
yamlMode: this._yamlMode,
|
yamlMode: this._yamlMode,
|
||||||
} satisfies ActionSidebarConfig);
|
} satisfies ActionSidebarConfig);
|
||||||
this._selected = true;
|
this._selected = true;
|
||||||
|
|
||||||
|
if (this.narrow) {
|
||||||
|
this.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public expand() {
|
public expand() {
|
||||||
|
|||||||
@@ -164,12 +164,15 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
!ACTION_BUILDING_BLOCKS.includes(type)
|
!ACTION_BUILDING_BLOCKS.includes(type)
|
||||||
) {
|
) {
|
||||||
row.openSidebar();
|
row.openSidebar();
|
||||||
|
if (this.narrow) {
|
||||||
|
row.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (!this.optionsInSidebar) {
|
} else if (!this.optionsInSidebar) {
|
||||||
row.expand();
|
row.expand();
|
||||||
}
|
}
|
||||||
if (this.narrow) {
|
|
||||||
row.scrollIntoView();
|
|
||||||
}
|
|
||||||
row.focus();
|
row.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -185,6 +188,10 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _addActionDialog() {
|
private _addActionDialog() {
|
||||||
|
if (this.narrow) {
|
||||||
|
fireEvent(this, "close-sidebar");
|
||||||
|
}
|
||||||
|
|
||||||
showAddAutomationElementDialog(this, {
|
showAddAutomationElementDialog(this, {
|
||||||
type: "action",
|
type: "action",
|
||||||
add: this._addAction,
|
add: this._addAction,
|
||||||
|
|||||||
@@ -599,10 +599,6 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public openSidebar(condition?: Condition): void {
|
public openSidebar(condition?: Condition): void {
|
||||||
if (this.narrow) {
|
|
||||||
this.scrollIntoView();
|
|
||||||
}
|
|
||||||
|
|
||||||
const sidebarCondition = condition || this.condition;
|
const sidebarCondition = condition || this.condition;
|
||||||
fireEvent(this, "open-sidebar", {
|
fireEvent(this, "open-sidebar", {
|
||||||
save: (value) => {
|
save: (value) => {
|
||||||
@@ -626,6 +622,13 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
yamlMode: this._yamlMode,
|
yamlMode: this._yamlMode,
|
||||||
} satisfies ConditionSidebarConfig);
|
} satisfies ConditionSidebarConfig);
|
||||||
this._selected = true;
|
this._selected = true;
|
||||||
|
|
||||||
|
if (this.narrow) {
|
||||||
|
this.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _uiSupported = memoizeOne(
|
private _uiSupported = memoizeOne(
|
||||||
|
|||||||
@@ -108,12 +108,15 @@ export default class HaAutomationCondition extends LitElement {
|
|||||||
!CONDITION_BUILDING_BLOCKS.includes(row.condition.condition)
|
!CONDITION_BUILDING_BLOCKS.includes(row.condition.condition)
|
||||||
) {
|
) {
|
||||||
row.openSidebar();
|
row.openSidebar();
|
||||||
|
if (this.narrow) {
|
||||||
|
row.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (!this.optionsInSidebar) {
|
} else if (!this.optionsInSidebar) {
|
||||||
row.expand();
|
row.expand();
|
||||||
}
|
}
|
||||||
if (this.narrow) {
|
|
||||||
row.scrollIntoView();
|
|
||||||
}
|
|
||||||
row.focus();
|
row.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -205,6 +208,9 @@ export default class HaAutomationCondition extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _addConditionDialog() {
|
private _addConditionDialog() {
|
||||||
|
if (this.narrow) {
|
||||||
|
fireEvent(this, "close-sidebar");
|
||||||
|
}
|
||||||
showAddAutomationElementDialog(this, {
|
showAddAutomationElementDialog(this, {
|
||||||
type: "condition",
|
type: "condition",
|
||||||
add: this._addCondition,
|
add: this._addCondition,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
import "../../../components/ha-bottom-sheet";
|
||||||
|
import type { HaBottomSheet } from "../../../components/ha-bottom-sheet";
|
||||||
import {
|
import {
|
||||||
isCondition,
|
isCondition,
|
||||||
isScriptField,
|
isScriptField,
|
||||||
@@ -13,14 +15,12 @@ import {
|
|||||||
} from "../../../data/automation";
|
} from "../../../data/automation";
|
||||||
import { isTriggerList } from "../../../data/trigger";
|
import { isTriggerList } from "../../../data/trigger";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import type HaAutomationConditionEditor from "./condition/ha-automation-condition-editor";
|
|
||||||
import "./sidebar/ha-automation-sidebar-action";
|
import "./sidebar/ha-automation-sidebar-action";
|
||||||
import "./sidebar/ha-automation-sidebar-condition";
|
import "./sidebar/ha-automation-sidebar-condition";
|
||||||
import "./sidebar/ha-automation-sidebar-option";
|
import "./sidebar/ha-automation-sidebar-option";
|
||||||
import "./sidebar/ha-automation-sidebar-script-field";
|
import "./sidebar/ha-automation-sidebar-script-field";
|
||||||
import "./sidebar/ha-automation-sidebar-script-field-selector";
|
import "./sidebar/ha-automation-sidebar-script-field-selector";
|
||||||
import "./sidebar/ha-automation-sidebar-trigger";
|
import "./sidebar/ha-automation-sidebar-trigger";
|
||||||
import type HaAutomationTriggerEditor from "./trigger/ha-automation-trigger-editor";
|
|
||||||
|
|
||||||
@customElement("ha-automation-sidebar")
|
@customElement("ha-automation-sidebar")
|
||||||
export default class HaAutomationSidebar extends LitElement {
|
export default class HaAutomationSidebar extends LitElement {
|
||||||
@@ -32,92 +32,101 @@ export default class HaAutomationSidebar extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _yamlMode = false;
|
@state() private _yamlMode = false;
|
||||||
|
|
||||||
@query(".sidebar-editor")
|
@query("ha-bottom-sheet") private _bottomSheetElement?: HaBottomSheet;
|
||||||
public editor?: HaAutomationTriggerEditor | HaAutomationConditionEditor;
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
if (!this.config) {
|
|
||||||
return nothing;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private _renderContent() {
|
||||||
// get config type
|
// get config type
|
||||||
const type = this._getType();
|
const type = this._getType();
|
||||||
|
|
||||||
if (type === "trigger") {
|
if (type === "trigger") {
|
||||||
return html`
|
return html`
|
||||||
<ha-automation-sidebar-trigger
|
<ha-automation-sidebar-trigger
|
||||||
|
class="sidebar-content"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.yamlMode=${this._yamlMode}
|
.yamlMode=${this._yamlMode}
|
||||||
@toggle-yaml-mode=${this._toggleYamlMode}
|
@toggle-yaml-mode=${this._toggleYamlMode}
|
||||||
@close-sidebar=${this._closeSidebar}
|
@close-sidebar=${this._handleCloseSidebar}
|
||||||
></ha-automation-sidebar-trigger>
|
></ha-automation-sidebar-trigger>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
if (type === "condition") {
|
if (type === "condition") {
|
||||||
return html`
|
return html`
|
||||||
<ha-automation-sidebar-condition
|
<ha-automation-sidebar-condition
|
||||||
|
class="sidebar-content"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.yamlMode=${this._yamlMode}
|
.yamlMode=${this._yamlMode}
|
||||||
@toggle-yaml-mode=${this._toggleYamlMode}
|
@toggle-yaml-mode=${this._toggleYamlMode}
|
||||||
@close-sidebar=${this._closeSidebar}
|
@close-sidebar=${this._handleCloseSidebar}
|
||||||
></ha-automation-sidebar-condition>
|
></ha-automation-sidebar-condition>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
if (type === "action") {
|
if (type === "action") {
|
||||||
return html`
|
return html`
|
||||||
<ha-automation-sidebar-action
|
<ha-automation-sidebar-action
|
||||||
|
class="sidebar-content"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.yamlMode=${this._yamlMode}
|
.yamlMode=${this._yamlMode}
|
||||||
@toggle-yaml-mode=${this._toggleYamlMode}
|
@toggle-yaml-mode=${this._toggleYamlMode}
|
||||||
@close-sidebar=${this._closeSidebar}
|
@close-sidebar=${this._handleCloseSidebar}
|
||||||
></ha-automation-sidebar-action>
|
></ha-automation-sidebar-action>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
if (type === "option") {
|
if (type === "option") {
|
||||||
return html`
|
return html`
|
||||||
<ha-automation-sidebar-option
|
<ha-automation-sidebar-option
|
||||||
|
class="sidebar-content"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@close-sidebar=${this._closeSidebar}
|
@close-sidebar=${this._handleCloseSidebar}
|
||||||
></ha-automation-sidebar-option>
|
></ha-automation-sidebar-option>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
if (type === "script-field-selector") {
|
if (type === "script-field-selector") {
|
||||||
return html`
|
return html`
|
||||||
<ha-automation-sidebar-script-field-selector
|
<ha-automation-sidebar-script-field-selector
|
||||||
|
class="sidebar-content"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.yamlMode=${this._yamlMode}
|
.yamlMode=${this._yamlMode}
|
||||||
@toggle-yaml-mode=${this._toggleYamlMode}
|
@toggle-yaml-mode=${this._toggleYamlMode}
|
||||||
@close-sidebar=${this._closeSidebar}
|
@close-sidebar=${this._handleCloseSidebar}
|
||||||
></ha-automation-sidebar-script-field-selector>
|
></ha-automation-sidebar-script-field-selector>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
if (type === "script-field") {
|
if (type === "script-field") {
|
||||||
return html`
|
return html`
|
||||||
<ha-automation-sidebar-script-field
|
<ha-automation-sidebar-script-field
|
||||||
|
class="sidebar-content"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.yamlMode=${this._yamlMode}
|
.yamlMode=${this._yamlMode}
|
||||||
@toggle-yaml-mode=${this._toggleYamlMode}
|
@toggle-yaml-mode=${this._toggleYamlMode}
|
||||||
@close-sidebar=${this._closeSidebar}
|
@close-sidebar=${this._handleCloseSidebar}
|
||||||
></ha-automation-sidebar-script-field>
|
></ha-automation-sidebar-script-field>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -125,6 +134,22 @@ export default class HaAutomationSidebar extends LitElement {
|
|||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this.config) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.narrow) {
|
||||||
|
return html`
|
||||||
|
<ha-bottom-sheet @bottom-sheet-closed=${this._closeSidebar}>
|
||||||
|
${this._renderContent()}
|
||||||
|
</ha-bottom-sheet>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._renderContent();
|
||||||
|
}
|
||||||
|
|
||||||
private _getType() {
|
private _getType() {
|
||||||
if (
|
if (
|
||||||
(this.config as TriggerSidebarConfig)?.config &&
|
(this.config as TriggerSidebarConfig)?.config &&
|
||||||
@@ -157,8 +182,17 @@ export default class HaAutomationSidebar extends LitElement {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _closeSidebar(ev: CustomEvent) {
|
private _handleCloseSidebar(ev: CustomEvent) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
|
if (this.narrow) {
|
||||||
|
this._bottomSheetElement?.closeSheet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._closeSidebar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _closeSidebar() {
|
||||||
this.config?.close();
|
this.config?.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +214,15 @@ export default class HaAutomationSidebar extends LitElement {
|
|||||||
var(--ha-border-radius-2xl)
|
var(--ha-border-radius-2xl)
|
||||||
);
|
);
|
||||||
border-radius: var(--ha-card-border-radius);
|
border-radius: var(--ha-card-border-radius);
|
||||||
|
--ha-bottom-sheet-border-width: 2px;
|
||||||
|
--ha-bottom-sheet-border-style: solid;
|
||||||
|
--ha-bottom-sheet-border-color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 870px) {
|
||||||
|
.sidebar-content {
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { HassEntity } from "home-assistant-js-websocket";
|
|||||||
import { load } from "js-yaml";
|
import { load } from "js-yaml";
|
||||||
import type { CSSResultGroup } from "lit";
|
import type { CSSResultGroup } from "lit";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import {
|
import {
|
||||||
any,
|
any,
|
||||||
@@ -84,6 +84,9 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
|
|
||||||
@state() private _sidebarConfig?: SidebarConfig;
|
@state() private _sidebarConfig?: SidebarConfig;
|
||||||
|
|
||||||
|
@query(".content")
|
||||||
|
private _contentElement?: HTMLDivElement;
|
||||||
|
|
||||||
private _previousConfig?: ManualAutomationConfig;
|
private _previousConfig?: ManualAutomationConfig;
|
||||||
|
|
||||||
public connectedCallback() {
|
public connectedCallback() {
|
||||||
@@ -273,10 +276,11 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
class=${classMap({
|
class=${classMap({
|
||||||
sidebar: true,
|
sidebar: true,
|
||||||
hidden: !this._sidebarConfig,
|
hidden: !this._sidebarConfig,
|
||||||
overlay: !this.isWide,
|
overlay: !this.isWide && !this.narrow,
|
||||||
})}
|
})}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.config=${this._sidebarConfig}
|
.config=${this._sidebarConfig}
|
||||||
@value-changed=${this._sidebarConfigChanged}
|
@value-changed=${this._sidebarConfigChanged}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@@ -313,6 +317,8 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
|
|
||||||
private _handleCloseSidebar() {
|
private _handleCloseSidebar() {
|
||||||
this._sidebarConfig = undefined;
|
this._sidebarConfig = undefined;
|
||||||
|
// fix content shift when bottom rows are scrolled into view
|
||||||
|
this._contentElement?.scrollIntoView();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _triggerChanged(ev: CustomEvent): void {
|
private _triggerChanged(ev: CustomEvent): void {
|
||||||
@@ -612,26 +618,23 @@ export class HaManualAutomationEditor extends LitElement {
|
|||||||
|
|
||||||
.sidebar.overlay {
|
.sidebar.overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 8px;
|
||||||
right: 0;
|
right: 8px;
|
||||||
height: calc(100% - 64px);
|
height: calc(100% - 70px);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
box-shadow: -8px 0 16px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 870px) {
|
@media all and (max-width: 870px) {
|
||||||
.sidebar.overlay {
|
.split-view {
|
||||||
max-height: 70vh;
|
gap: 0;
|
||||||
max-height: 70dvh;
|
margin-right: -8px;
|
||||||
height: auto;
|
|
||||||
width: 100%;
|
|
||||||
box-shadow: 0px -8px 16px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
}
|
||||||
}
|
.sidebar {
|
||||||
|
|
||||||
@media all and (max-width: 870px) {
|
|
||||||
.sidebar.overlay.hidden {
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
flex: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -343,10 +343,6 @@ export default class HaAutomationOptionRow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public openSidebar(): void {
|
public openSidebar(): void {
|
||||||
if (this.narrow) {
|
|
||||||
this.scrollIntoView();
|
|
||||||
}
|
|
||||||
|
|
||||||
fireEvent(this, "open-sidebar", {
|
fireEvent(this, "open-sidebar", {
|
||||||
close: () => {
|
close: () => {
|
||||||
this._selected = false;
|
this._selected = false;
|
||||||
@@ -359,6 +355,13 @@ export default class HaAutomationOptionRow extends LitElement {
|
|||||||
delete: this._removeOption,
|
delete: this._removeOption,
|
||||||
} satisfies OptionSidebarConfig);
|
} satisfies OptionSidebarConfig);
|
||||||
this._selected = true;
|
this._selected = true;
|
||||||
|
|
||||||
|
if (this.narrow) {
|
||||||
|
this.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public expand() {
|
public expand() {
|
||||||
|
|||||||
@@ -132,10 +132,11 @@ export default class HaAutomationOption extends LitElement {
|
|||||||
row.updateComplete.then(() => {
|
row.updateComplete.then(() => {
|
||||||
if (!this.optionsInSidebar) {
|
if (!this.optionsInSidebar) {
|
||||||
row.expand();
|
row.expand();
|
||||||
}
|
} else if (this.narrow) {
|
||||||
|
row.scrollIntoView({
|
||||||
if (this.narrow) {
|
block: "start",
|
||||||
row.scrollIntoView();
|
behavior: "smooth",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
row.focus();
|
row.focus();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ export default class HaAutomationSidebarAction extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _warnings?: string[];
|
@state() private _warnings?: string[];
|
||||||
|
|
||||||
@query(".sidebar-editor")
|
@query(".sidebar-editor")
|
||||||
@@ -85,6 +87,7 @@ export default class HaAutomationSidebarAction extends LitElement {
|
|||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.yamlMode=${this.yamlMode}
|
.yamlMode=${this.yamlMode}
|
||||||
.warnings=${this._warnings}
|
.warnings=${this._warnings}
|
||||||
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<span slot="title">${title}</span>
|
<span slot="title">${title}</span>
|
||||||
<span slot="subtitle">${subtitle}</span>
|
<span slot="subtitle">${subtitle}</span>
|
||||||
@@ -133,8 +136,9 @@ export default class HaAutomationSidebarAction extends LitElement {
|
|||||||
)}
|
)}
|
||||||
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
||||||
</ha-md-menu-item>
|
</ha-md-menu-item>
|
||||||
${description ||
|
${description && !this.yamlMode
|
||||||
html`<ha-automation-action-editor
|
? html`<div class="description">${description}</div>`
|
||||||
|
: html`<ha-automation-action-editor
|
||||||
class="sidebar-editor"
|
class="sidebar-editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.action=${this.config.config}
|
.action=${this.config.config}
|
||||||
@@ -179,6 +183,9 @@ export default class HaAutomationSidebarAction extends LitElement {
|
|||||||
.sidebar-editor {
|
.sidebar-editor {
|
||||||
padding-top: 64px;
|
padding-top: 64px;
|
||||||
}
|
}
|
||||||
|
.description {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { mdiClose, mdiDotsVertical } from "@mdi/js";
|
import { mdiClose, mdiDotsVertical } from "@mdi/js";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import {
|
||||||
|
customElement,
|
||||||
|
eventOptions,
|
||||||
|
property,
|
||||||
|
query,
|
||||||
|
state,
|
||||||
|
} from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||||
@@ -33,6 +39,12 @@ export default class HaAutomationSidebarCard extends LitElement {
|
|||||||
|
|
||||||
@property({ attribute: false }) public warnings?: string[];
|
@property({ attribute: false }) public warnings?: string[];
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
|
@state() private _contentScrolled = false;
|
||||||
|
|
||||||
|
@query(".card-content") private _contentElement?: HTMLDivElement;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`
|
return html`
|
||||||
<ha-card
|
<ha-card
|
||||||
@@ -42,7 +54,9 @@ export default class HaAutomationSidebarCard extends LitElement {
|
|||||||
yaml: this.yamlMode,
|
yaml: this.yamlMode,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ha-dialog-header>
|
<ha-dialog-header
|
||||||
|
class=${classMap({ scrolled: this._contentScrolled })}
|
||||||
|
>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
slot="navigationIcon"
|
slot="navigationIcon"
|
||||||
.label=${this.hass.localize("ui.common.close")}
|
.label=${this.hass.localize("ui.common.close")}
|
||||||
@@ -56,7 +70,7 @@ export default class HaAutomationSidebarCard extends LitElement {
|
|||||||
@click=${this._openOverflowMenu}
|
@click=${this._openOverflowMenu}
|
||||||
@keydown=${stopPropagation}
|
@keydown=${stopPropagation}
|
||||||
@closed=${stopPropagation}
|
@closed=${stopPropagation}
|
||||||
positioning="fixed"
|
.positioning=${this.narrow ? "absolute" : "fixed"}
|
||||||
>
|
>
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
slot="trigger"
|
slot="trigger"
|
||||||
@@ -74,13 +88,19 @@ export default class HaAutomationSidebarCard extends LitElement {
|
|||||||
>
|
>
|
||||||
</ha-automation-editor-warning>`
|
</ha-automation-editor-warning>`
|
||||||
: nothing}
|
: nothing}
|
||||||
<div class="card-content">
|
<div class="card-content" @scroll=${this._onScroll}>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</ha-card>
|
</ha-card>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@eventOptions({ passive: true })
|
||||||
|
private _onScroll() {
|
||||||
|
const top = this._contentElement?.scrollTop ?? 0;
|
||||||
|
this._contentScrolled = top > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private _closeSidebar() {
|
private _closeSidebar() {
|
||||||
fireEvent(this, "close-sidebar");
|
fireEvent(this, "close-sidebar");
|
||||||
}
|
}
|
||||||
@@ -98,25 +118,33 @@ export default class HaAutomationSidebarCard extends LitElement {
|
|||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
ha-card.mobile {
|
|
||||||
border-bottom-right-radius: var(--ha-border-radius-square);
|
|
||||||
border-bottom-left-radius: var(--ha-border-radius-square);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 870px) {
|
@media all and (max-width: 870px) {
|
||||||
ha-card.mobile {
|
ha-card.mobile {
|
||||||
max-height: 70vh;
|
border: none;
|
||||||
max-height: 70dvh;
|
|
||||||
border-width: 2px 2px 0;
|
|
||||||
}
|
}
|
||||||
ha-card.mobile.yaml {
|
ha-card.mobile {
|
||||||
height: 70vh;
|
border-bottom-right-radius: var(--ha-border-radius-square);
|
||||||
height: 70dvh;
|
border-bottom-left-radius: var(--ha-border-radius-square);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ha-dialog-header {
|
ha-dialog-header {
|
||||||
border-radius: var(--ha-card-border-radius);
|
border-radius: var(--ha-card-border-radius);
|
||||||
|
box-shadow: none;
|
||||||
|
transition: box-shadow 180ms ease-in-out;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
z-index: 6;
|
||||||
|
position: relative;
|
||||||
|
background-color: var(
|
||||||
|
--ha-dialog-surface-background,
|
||||||
|
var(--mdc-theme-surface, #fff)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ha-dialog-header.scrolled {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-content {
|
.card-content {
|
||||||
@@ -130,17 +158,6 @@ export default class HaAutomationSidebarCard extends LitElement {
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 870px) {
|
|
||||||
ha-card.mobile .card-content {
|
|
||||||
max-height: calc(
|
|
||||||
70vh - 88px - max(var(--safe-area-inset-bottom), 16px)
|
|
||||||
);
|
|
||||||
max-height: calc(
|
|
||||||
70dvh - 88px - max(var(--safe-area-inset-bottom), 16px)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export default class HaAutomationSidebarCondition extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _warnings?: string[];
|
@state() private _warnings?: string[];
|
||||||
|
|
||||||
@query(".sidebar-editor")
|
@query(".sidebar-editor")
|
||||||
@@ -74,6 +76,7 @@ export default class HaAutomationSidebarCondition extends LitElement {
|
|||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.yamlMode=${this.yamlMode}
|
.yamlMode=${this.yamlMode}
|
||||||
.warnings=${this._warnings}
|
.warnings=${this._warnings}
|
||||||
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<span slot="title">${title}</span>
|
<span slot="title">${title}</span>
|
||||||
<span slot="subtitle">${subtitle}</span>
|
<span slot="subtitle">${subtitle}</span>
|
||||||
@@ -122,8 +125,9 @@ export default class HaAutomationSidebarCondition extends LitElement {
|
|||||||
)}
|
)}
|
||||||
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
||||||
</ha-md-menu-item>
|
</ha-md-menu-item>
|
||||||
${description ||
|
${description && !this.yamlMode
|
||||||
html`<ha-automation-condition-editor
|
? html`<div class="description">${description}</div>`
|
||||||
|
: html`<ha-automation-condition-editor
|
||||||
class="sidebar-editor"
|
class="sidebar-editor"
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.condition=${this.config.config}
|
.condition=${this.config.config}
|
||||||
@@ -166,6 +170,9 @@ export default class HaAutomationSidebarCondition extends LitElement {
|
|||||||
.sidebar-editor {
|
.sidebar-editor {
|
||||||
padding-top: 64px;
|
padding-top: 64px;
|
||||||
}
|
}
|
||||||
|
.description {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ export default class HaAutomationSidebarOption extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@query(".sidebar-editor")
|
@query(".sidebar-editor")
|
||||||
public editor?: HaAutomationConditionEditor;
|
public editor?: HaAutomationConditionEditor;
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ export default class HaAutomationSidebarOption extends LitElement {
|
|||||||
return html`<ha-automation-sidebar-card
|
return html`<ha-automation-sidebar-card
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<span slot="title">${title}</span>
|
<span slot="title">${title}</span>
|
||||||
<span slot="subtitle">${subtitle}</span>
|
<span slot="subtitle">${subtitle}</span>
|
||||||
@@ -66,7 +69,7 @@ export default class HaAutomationSidebarOption extends LitElement {
|
|||||||
)}
|
)}
|
||||||
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
<ha-svg-icon slot="start" .path=${mdiDelete}></ha-svg-icon>
|
||||||
</ha-md-menu-item>
|
</ha-md-menu-item>
|
||||||
${description}
|
<div class="description">${description}</div>
|
||||||
</ha-automation-sidebar-card>`;
|
</ha-automation-sidebar-card>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +77,9 @@ export default class HaAutomationSidebarOption extends LitElement {
|
|||||||
.sidebar-editor {
|
.sidebar-editor {
|
||||||
padding-top: 64px;
|
padding-top: 64px;
|
||||||
}
|
}
|
||||||
|
.description {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ export default class HaAutomationSidebarScriptFieldSelector extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _warnings?: string[];
|
@state() private _warnings?: string[];
|
||||||
|
|
||||||
@query(".sidebar-editor")
|
@query(".sidebar-editor")
|
||||||
@@ -53,6 +55,7 @@ export default class HaAutomationSidebarScriptFieldSelector extends LitElement {
|
|||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.yamlMode=${this.yamlMode}
|
.yamlMode=${this.yamlMode}
|
||||||
.warnings=${this._warnings}
|
.warnings=${this._warnings}
|
||||||
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<span slot="title">${title}</span>
|
<span slot="title">${title}</span>
|
||||||
<span slot="subtitle">${subtitle}</span>
|
<span slot="subtitle">${subtitle}</span>
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export default class HaAutomationSidebarScriptField extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _warnings?: string[];
|
@state() private _warnings?: string[];
|
||||||
|
|
||||||
@query(".sidebar-editor")
|
@query(".sidebar-editor")
|
||||||
@@ -47,6 +49,7 @@ export default class HaAutomationSidebarScriptField extends LitElement {
|
|||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.yamlMode=${this.yamlMode}
|
.yamlMode=${this.yamlMode}
|
||||||
.warnings=${this._warnings}
|
.warnings=${this._warnings}
|
||||||
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<span slot="title">${title}</span>
|
<span slot="title">${title}</span>
|
||||||
<ha-md-menu-item
|
<ha-md-menu-item
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ export default class HaAutomationSidebarTrigger extends LitElement {
|
|||||||
|
|
||||||
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
@property({ type: Boolean, attribute: "yaml-mode" }) public yamlMode = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public narrow = false;
|
||||||
|
|
||||||
@state() private _requestShowId = false;
|
@state() private _requestShowId = false;
|
||||||
|
|
||||||
@state() private _warnings?: string[];
|
@state() private _warnings?: string[];
|
||||||
@@ -71,6 +73,7 @@ export default class HaAutomationSidebarTrigger extends LitElement {
|
|||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.yamlMode=${this.yamlMode}
|
.yamlMode=${this.yamlMode}
|
||||||
.warnings=${this._warnings}
|
.warnings=${this._warnings}
|
||||||
|
.narrow=${this.narrow}
|
||||||
>
|
>
|
||||||
<span slot="title">${title}</span>
|
<span slot="title">${title}</span>
|
||||||
<span slot="subtitle">${subtitle}</span>
|
<span slot="subtitle">${subtitle}</span>
|
||||||
|
|||||||
@@ -469,9 +469,6 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public openSidebar(trigger?: Trigger): void {
|
public openSidebar(trigger?: Trigger): void {
|
||||||
if (this.narrow) {
|
|
||||||
this.scrollIntoView();
|
|
||||||
}
|
|
||||||
fireEvent(this, "open-sidebar", {
|
fireEvent(this, "open-sidebar", {
|
||||||
save: (value) => {
|
save: (value) => {
|
||||||
fireEvent(this, "value-changed", { value });
|
fireEvent(this, "value-changed", { value });
|
||||||
@@ -494,6 +491,13 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
yamlMode: this._yamlMode,
|
yamlMode: this._yamlMode,
|
||||||
} satisfies TriggerSidebarConfig);
|
} satisfies TriggerSidebarConfig);
|
||||||
this._selected = true;
|
this._selected = true;
|
||||||
|
|
||||||
|
if (this.narrow) {
|
||||||
|
this.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setClipboard() {
|
private _setClipboard() {
|
||||||
|
|||||||
@@ -135,6 +135,9 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _addTriggerDialog() {
|
private _addTriggerDialog() {
|
||||||
|
if (this.narrow) {
|
||||||
|
fireEvent(this, "close-sidebar");
|
||||||
|
}
|
||||||
showAddAutomationElementDialog(this, {
|
showAddAutomationElementDialog(this, {
|
||||||
type: "trigger",
|
type: "trigger",
|
||||||
add: this._addTrigger,
|
add: this._addTrigger,
|
||||||
@@ -177,12 +180,15 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
row.updateComplete.then(() => {
|
row.updateComplete.then(() => {
|
||||||
if (this.optionsInSidebar) {
|
if (this.optionsInSidebar) {
|
||||||
row.openSidebar();
|
row.openSidebar();
|
||||||
|
if (this.narrow) {
|
||||||
|
row.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
row.expand();
|
row.expand();
|
||||||
}
|
}
|
||||||
if (this.narrow) {
|
|
||||||
row.scrollIntoView();
|
|
||||||
}
|
|
||||||
row.focus();
|
row.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,9 +187,6 @@ export default class HaScriptFieldRow extends LitElement {
|
|||||||
if (!selectorEditor) {
|
if (!selectorEditor) {
|
||||||
this._selected = true;
|
this._selected = true;
|
||||||
}
|
}
|
||||||
if (this.narrow) {
|
|
||||||
this.scrollIntoView();
|
|
||||||
}
|
|
||||||
|
|
||||||
fireEvent(this, "open-sidebar", {
|
fireEvent(this, "open-sidebar", {
|
||||||
save: (value) => {
|
save: (value) => {
|
||||||
@@ -216,6 +213,13 @@ export default class HaScriptFieldRow extends LitElement {
|
|||||||
},
|
},
|
||||||
yamlMode: this._yamlMode,
|
yamlMode: this._yamlMode,
|
||||||
} satisfies ScriptFieldSidebarConfig);
|
} satisfies ScriptFieldSidebarConfig);
|
||||||
|
|
||||||
|
if (this.narrow) {
|
||||||
|
this.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _toggleYamlMode = () => {
|
private _toggleYamlMode = () => {
|
||||||
|
|||||||
@@ -75,11 +75,14 @@ export default class HaScriptFields extends LitElement {
|
|||||||
)!;
|
)!;
|
||||||
row.updateComplete.then(() => {
|
row.updateComplete.then(() => {
|
||||||
row.openSidebar();
|
row.openSidebar();
|
||||||
|
row.focus();
|
||||||
|
|
||||||
if (this.narrow) {
|
if (this.narrow) {
|
||||||
row.scrollIntoView();
|
row.scrollIntoView({
|
||||||
|
block: "start",
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
row.focus();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ export class HaManualScriptEditor extends LitElement {
|
|||||||
hidden: !this._sidebarConfig,
|
hidden: !this._sidebarConfig,
|
||||||
overlay: !this.isWide,
|
overlay: !this.isWide,
|
||||||
})}
|
})}
|
||||||
|
.narrow=${this.narrow}
|
||||||
.isWide=${this.isWide}
|
.isWide=${this.isWide}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.config=${this._sidebarConfig}
|
.config=${this._sidebarConfig}
|
||||||
@@ -511,18 +512,14 @@ export class HaManualScriptEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 870px) {
|
@media all and (max-width: 870px) {
|
||||||
.sidebar.overlay {
|
.split-view {
|
||||||
max-height: 70vh;
|
gap: 0;
|
||||||
max-height: 70dvh;
|
margin-right: -8px;
|
||||||
height: auto;
|
|
||||||
width: 100%;
|
|
||||||
box-shadow: 0px -8px 16px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
}
|
||||||
}
|
.sidebar {
|
||||||
|
|
||||||
@media all and (max-width: 870px) {
|
|
||||||
.sidebar.overlay.hidden {
|
|
||||||
height: 0;
|
height: 0;
|
||||||
|
width: 0;
|
||||||
|
flex: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ export const waMainStyles = css`
|
|||||||
--wa-focus-ring-offset: 2px;
|
--wa-focus-ring-offset: 2px;
|
||||||
--wa-focus-ring: var(--wa-focus-ring-style) var(--wa-focus-ring-width)
|
--wa-focus-ring: var(--wa-focus-ring-style) var(--wa-focus-ring-width)
|
||||||
var(--wa-focus-ring-color);
|
var(--wa-focus-ring-color);
|
||||||
|
|
||||||
|
--wa-space-l: 24px;
|
||||||
|
--wa-shadow-l: 0 8px 8px -4px rgba(0, 0, 0, 0.2);
|
||||||
|
--wa-form-control-padding-block: 0.75em;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user