diff --git a/src/components/ha-md-dialog.ts b/src/components/ha-md-dialog.ts index e4636327c5..4e3f76d8a0 100644 --- a/src/components/ha-md-dialog.ts +++ b/src/components/ha-md-dialog.ts @@ -1,4 +1,9 @@ import { MdDialog } from "@material/web/dialog/dialog"; +import { + type DialogAnimation, + DIALOG_DEFAULT_CLOSE_ANIMATION, + DIALOG_DEFAULT_OPEN_ANIMATION, +} from "@material/web/dialog/internal/animations"; import { css } from "lit"; import { customElement, property } from "lit/decorators"; @@ -131,7 +136,7 @@ export class HaMdDialog extends MdDialog { ); min-height: 100%; max-height: 100%; - border-radius: 0; + --md-dialog-container-shape: 0; } } @@ -146,6 +151,58 @@ export class HaMdDialog extends MdDialog { ]; } +// by default the dialog open/close animation will be from/to the top +// but if we have a special mobile dialog which is at the bottom of the screen, an from bottom animation can be used: +const OPEN_FROM_BOTTOM_ANIMATION: DialogAnimation = { + ...DIALOG_DEFAULT_OPEN_ANIMATION, + dialog: [ + [ + // Dialog slide up + [{ transform: "translateY(50px)" }, { transform: "translateY(0)" }], + { duration: 500, easing: "cubic-bezier(.3,0,0,1)" }, + ], + ], + container: [ + [ + // Container fade in + [{ opacity: 0 }, { opacity: 1 }], + { duration: 50, easing: "linear", pseudoElement: "::before" }, + ], + ], +}; + +const CLOSE_TO_BOTTOM_ANIMATION: DialogAnimation = { + ...DIALOG_DEFAULT_CLOSE_ANIMATION, + dialog: [ + [ + // Dialog slide down + [{ transform: "translateY(0)" }, { transform: "translateY(50px)" }], + { duration: 150, easing: "cubic-bezier(.3,0,0,1)" }, + ], + ], + container: [ + [ + // Container fade out + [{ opacity: "1" }, { opacity: "0" }], + { delay: 100, duration: 50, easing: "linear", pseudoElement: "::before" }, + ], + ], +}; + +export const getMobileOpenFromBottomAnimation = () => { + const matches = window.matchMedia( + "all and (max-width: 450px), all and (max-height: 500px)" + ).matches; + return matches ? OPEN_FROM_BOTTOM_ANIMATION : DIALOG_DEFAULT_OPEN_ANIMATION; +}; + +export const getMobileCloseToBottomAnimation = () => { + const matches = window.matchMedia( + "all and (max-width: 450px), all and (max-height: 500px)" + ).matches; + return matches ? CLOSE_TO_BOTTOM_ANIMATION : DIALOG_DEFAULT_CLOSE_ANIMATION; +}; + declare global { interface HTMLElementTagNameMap { "ha-md-dialog": HaMdDialog; diff --git a/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts b/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts index c13bb56ea1..101157e6b2 100644 --- a/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts +++ b/src/dialogs/more-info/components/lights/dialog-light-color-favorite.ts @@ -1,15 +1,18 @@ import { mdiClose } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { customElement, property, state, query } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-button"; -import "../../../../components/ha-dialog"; +import { + getMobileOpenFromBottomAnimation, + getMobileCloseToBottomAnimation, +} from "../../../../components/ha-md-dialog"; +import type { HaMdDialog } from "../../../../components/ha-md-dialog"; import "../../../../components/ha-dialog-header"; import "../../../../components/ha-icon-button-toggle"; import type { EntityRegistryEntry } from "../../../../data/entity_registry"; import { - formatTempColor, LightColor, LightColorMode, LightEntity, @@ -38,15 +41,7 @@ class DialogLightColorFavorite extends LitElement { @state() private _modes: LightPickerMode[] = []; - @state() private _currentValue?: string; - - private _colorHovered(ev: CustomEvent) { - if (ev.detail && "color_temp_kelvin" in ev.detail) { - this._currentValue = formatTempColor(ev.detail.color_temp_kelvin); - } else { - this._currentValue = undefined; - } - } + @query("ha-md-dialog") private _dialog?: HaMdDialog; public async showDialog( dialogParams: LightColorFavoriteDialogParams @@ -58,10 +53,7 @@ class DialogLightColorFavorite extends LitElement { } public closeDialog(): void { - this._dialogParams = undefined; - this._entry = undefined; - this._color = undefined; - fireEvent(this, "dialog-closed", { dialog: this.localName }); + this._dialog?.close(); } private _updateModes() { @@ -130,9 +122,20 @@ class DialogLightColorFavorite extends LitElement { private async _cancel() { this._dialogParams?.cancel?.(); + } + + private _cancelDialog() { + this._cancel(); this.closeDialog(); } + private _dialogClosed(): void { + this._dialogParams = undefined; + this._entry = undefined; + this._color = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + private async _save() { if (!this._color) { this._cancel(); @@ -156,82 +159,83 @@ class DialogLightColorFavorite extends LitElement { } return html` - - + - ${this._dialogParams?.title} + ${this._dialogParams?.title} -
- ${this._currentValue} - ${this._modes.length > 1 - ? html` -
- ${this._modes.map( - (value) => html` - - - - ` - )} -
- ` - : nothing} +
+
+ ${this._modes.length > 1 + ? html` +
+ ${this._modes.map( + (value) => html` + + + + ` + )} +
+ ` + : nothing} +
+
+ ${this._mode === "color_temp" + ? html` + + + ` + : nothing} + ${this._mode === "color" + ? html` + + + ` + : nothing} +
- -
- ${this._mode === "color_temp" - ? html` - - - ` - : nothing} - ${this._mode === "color" - ? html` - - - ` - : nothing} +
+ + ${this.hass.localize("ui.common.cancel")} + + ${this.hass.localize("ui.common.save")}
- - ${this.hass.localize("ui.common.cancel")} - - ${this.hass.localize("ui.common.save")} - + `; } @@ -239,19 +243,23 @@ class DialogLightColorFavorite extends LitElement { return [ haStyleDialog, css` - ha-dialog { - --dialog-content-padding: 0; + ha-md-dialog { + min-width: 420px; /* prevent width jumps when switching modes */ + max-height: min( + 600px, + 100% - 48px + ); /* prevent scrolling on desktop */ } @media all and (max-width: 450px), all and (max-height: 500px) { - ha-dialog { - --dialog-surface-margin-top: 100px; - --mdc-dialog-min-height: auto; - --mdc-dialog-max-height: calc(100% - 100px); - --ha-dialog-border-radius: var( - --ha-dialog-bottom-sheet-border-radius, - 28px 28px 0 0 - ); + ha-md-dialog { + min-width: 100%; + min-height: auto; + max-height: calc(100% - 100px); + margin-bottom: 0; + + --md-dialog-container-shape-start-start: 28px; + --md-dialog-container-shape-start-end: 28px; } } @@ -287,21 +295,6 @@ class DialogLightColorFavorite extends LitElement { rgb(255, 160, 0) 100% ); } - .value { - pointer-events: none; - position: absolute; - top: 0; - left: 0; - right: 0; - margin: auto; - font-style: normal; - font-weight: 500; - font-size: 16px; - height: 48px; - line-height: 48px; - letter-spacing: 0.1px; - text-align: center; - } `, ]; }