Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c8e2a2a
Set minimum safe areas in ha-wa-dialog
timmo001 Nov 27, 2025
57a5b6e
Add debug section to dialog
timmo001 Nov 27, 2025
eb92e3a
Add type to wa-dialog
timmo001 Nov 27, 2025
b11f866
Move custom logic for close button to alert type in wa
timmo001 Nov 27, 2025
6db2b02
Safe width
timmo001 Nov 27, 2025
9f2abcf
Safe width on standard dialog
timmo001 Nov 27, 2025
64b6411
Flip
timmo001 Nov 27, 2025
a337d4d
Safe area on standard dialog (actual)
timmo001 Nov 27, 2025
e5d33ee
Move safe area 0px clamp to globals
timmo001 Nov 27, 2025
d7238a0
Create safe width and height globals
timmo001 Nov 27, 2025
5302eb9
Dont rely on ha-vars
timmo001 Nov 27, 2025
d5a8511
Remove use of svh/svw, use globals
timmo001 Nov 27, 2025
53b66db
Fix
timmo001 Nov 27, 2025
2b89e31
Fix
timmo001 Nov 27, 2025
9c22e3a
Remove test
timmo001 Nov 27, 2025
888f055
Revert "Add debug section to dialog"
timmo001 Nov 27, 2025
dc17ac6
Apply suggestion from @bramkragten
timmo001 Nov 27, 2025
1e947a4
Use transform to move dialog based on offset x
timmo001 Nov 27, 2025
e38a31a
Translate X and Y
timmo001 Nov 27, 2025
a261696
Revert unwanted changes to dialog-box
timmo001 Nov 27, 2025
eceec1a
Remove extra fallback
timmo001 Nov 27, 2025
32dbd2a
Format
timmo001 Nov 27, 2025
0b6abb5
Cleanup
timmo001 Nov 27, 2025
1844680
Explain
timmo001 Nov 27, 2025
9dfe9f4
Align title to content
timmo001 Nov 27, 2025
20fc34d
Remove clamp on safe areas
timmo001 Nov 27, 2025
c7a9553
Fix fullscreen
timmo001 Nov 27, 2025
2ee6b2c
Explain transform
timmo001 Nov 27, 2025
af7c6d9
Restore old fullscreen heights
timmo001 Nov 27, 2025
44c366f
Add rtl support
piitaya Nov 27, 2025
71ad83b
Compensate mobile margin
piitaya Nov 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 45 additions & 30 deletions src/components/ha-wa-dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type DialogWidth = "small" | "medium" | "large" | "full";
* @cssprop --dialog-surface-margin-top - Top margin for the dialog surface.
*
* @attr {boolean} open - Controls the dialog open state.
* @attr {("alert"|"standard")} type - Dialog type. Defaults to "standard".
* @attr {("small"|"medium"|"large"|"full")} width - Preferred dialog width preset. Defaults to "medium".
* @attr {boolean} prevent-scrim-close - Prevents closing the dialog by clicking the scrim/overlay. Defaults to false.
* @attr {string} header-title - Header title text. If not set, the headerTitle slot is used.
Expand Down Expand Up @@ -84,6 +85,9 @@ export class HaWaDialog extends LitElement {
@property({ type: Boolean, reflect: true })
public open = false;

@property({ reflect: true })
public type: "alert" | "standard" = "standard";

@property({ type: String, reflect: true, attribute: "width" })
public width: DialogWidth = "medium";

Expand Down Expand Up @@ -198,18 +202,7 @@ export class HaWaDialog extends LitElement {
haStyleScrollbar,
css`
wa-dialog {
--full-width: var(
--ha-dialog-width-full,
min(
95vw,
calc(
100vw - var(--safe-area-inset-left, var(--ha-space-0)) - var(
--safe-area-inset-right,
var(--ha-space-0)
)
)
)
);
--full-width: var(--ha-dialog-width-full, min(95vw, var(--safe-width)));
--width: min(var(--ha-dialog-width-md, 580px), var(--full-width));
--spacing: var(--dialog-content-padding, var(--ha-space-6));
--show-duration: var(--ha-dialog-show-duration, 200ms);
Expand All @@ -226,8 +219,7 @@ export class HaWaDialog extends LitElement {
--ha-dialog-border-radius,
var(--ha-border-radius-3xl)
);
max-width: var(--ha-dialog-max-width, 100vw);
max-width: var(--ha-dialog-max-width, 100svw);
max-width: var(--ha-dialog-max-width, var(--safe-width));
}

:host([width="small"]) wa-dialog {
Expand All @@ -247,34 +239,57 @@ export class HaWaDialog extends LitElement {
max-width: var(--width, var(--full-width));
max-height: var(
--ha-dialog-max-height,
calc(100% - var(--ha-space-20))
calc(var(--safe-height) - var(--ha-space-20))
);
min-height: var(--ha-dialog-min-height);
position: var(--dialog-surface-position, relative);
margin-top: var(--dialog-surface-margin-top, auto);
/* Used to offset the dialog from the safe areas when space is limited */
transform: translate(
calc(
var(--safe-area-offset-left, var(--ha-space-0)) - var(
--safe-area-offset-right,
var(--ha-space-0)
)
),
calc(
var(--safe-area-offset-top, var(--ha-space-0)) - var(
--safe-area-offset-bottom,
var(--ha-space-0)
)
)
);
display: flex;
flex-direction: column;
overflow: hidden;
}

@media all and (max-width: 450px), all and (max-height: 500px) {
:host {
:host([type="standard"]) {
--ha-dialog-border-radius: var(--ha-space-0);
}

wa-dialog {
--full-width: var(--ha-dialog-width-full, 100vw);
}

wa-dialog::part(dialog) {
min-height: var(--ha-dialog-min-height, 100vh);
min-height: var(--ha-dialog-min-height, 100svh);
max-height: var(--ha-dialog-max-height, 100vh);
max-height: var(--ha-dialog-max-height, 100svh);
padding-top: var(--safe-area-inset-top, var(--ha-space-0));
padding-bottom: var(--safe-area-inset-bottom, var(--ha-space-0));
padding-left: var(--safe-area-inset-left, var(--ha-space-0));
padding-right: var(--safe-area-inset-right, var(--ha-space-0));
wa-dialog {
/* Make the container fill the whole screen width and not the safe width */
--full-width: var(--ha-dialog-width-full, 100vw);
--width: var(--full-width);
}

wa-dialog::part(dialog) {
/* Make the dialog fill the whole screen height and not the safe height */
min-height: var(--ha-dialog-min-height, 100vh);
min-height: var(--ha-dialog-min-height, 100dvh);
max-height: var(--ha-dialog-max-height, 100vh);
max-height: var(--ha-dialog-max-height, 100dvh);
margin-top: 0;
margin-bottom: 0;
/* Use safe area as padding instead of the container size */
padding-top: var(--safe-area-inset-top);
padding-bottom: var(--safe-area-inset-bottom);
padding-left: var(--safe-area-inset-left);
padding-right: var(--safe-area-inset-right);
/* Reset the transform to center the dialog */
transform: none;
}
}
}

Expand Down
16 changes: 15 additions & 1 deletion src/dialogs/generic/dialog-box.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mdiAlertOutline, mdiClose } from "@mdi/js";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-button";
Expand Down Expand Up @@ -64,6 +65,7 @@ class DialogBox extends LitElement {
<ha-wa-dialog
.hass=${this.hass}
.open=${this._open}
type=${confirmPrompt ? "alert" : "standard"}
?prevent-scrim-close=${confirmPrompt}
@closed=${this._dialogClosed}
aria-labelledby="dialog-box-title"
Expand All @@ -79,7 +81,11 @@ class DialogBox extends LitElement {
></ha-icon-button
></slot>`
: nothing}
<span slot="title" id="dialog-box-title">
<span
class=${classMap({ title: true, alert: confirmPrompt })}
slot="title"
id="dialog-box-title"
>
${this._params.warning
? html`<ha-svg-icon
.path=${mdiAlertOutline}
Expand Down Expand Up @@ -199,6 +205,14 @@ class DialogBox extends LitElement {
ha-textfield {
width: 100%;
}
.title.alert {
padding: 0 var(--ha-space-2);
}
@media all and (min-width: 450px) and (min-height: 500px) {
.title.alert {
padding: 0 var(--ha-space-1);
}
}
`;
}

Expand Down
25 changes: 19 additions & 6 deletions src/resources/theme/main.globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,27 @@ export const mainStyles = css`
--margin-title-ltr: 0 0 0 24px;
--margin-title-rtl: 0 24px 0 0;

/* safe-area-insets */
--safe-area-inset-top: var(--app-safe-area-inset-top, env(safe-area-inset-top, 0));
--safe-area-inset-bottom: var(--app-safe-area-inset-bottom, env(safe-area-inset-bottom, 0));
--safe-area-inset-left: var(--app-safe-area-inset-left, env(safe-area-inset-left, 0));
--safe-area-inset-right: var(--app-safe-area-inset-right, env(safe-area-inset-right, 0));
/* Safe area insets */
--safe-area-inset-top: var(--app-safe-area-inset-top, env(safe-area-inset-top, 0px));
--safe-area-inset-bottom: var(--app-safe-area-inset-bottom, env(safe-area-inset-bottom, 0px));
--safe-area-inset-left: var(--app-safe-area-inset-left, env(safe-area-inset-left, 0px));
--safe-area-inset-right: var(--app-safe-area-inset-right, env(safe-area-inset-right, 0px));

--safe-area-inset-y: calc(var(--safe-area-inset-top, 0px) + var(--safe-area-inset-bottom, 0px));
/* Safe area inset x and y */
--safe-area-inset-x: calc(var(--safe-area-inset-left, 0px) + var(--safe-area-inset-right, 0px));
--safe-area-inset-y: calc(var(--safe-area-inset-top, 0px) + var(--safe-area-inset-bottom, 0px));

/* Offsets for centering elements within asymmetric safe areas */
--safe-area-offset-left: calc(max(var(--safe-area-inset-left, 0px) - var(--safe-area-inset-right, 0px), 0px) / 2);
--safe-area-offset-right: calc(max(var(--safe-area-inset-right, 0px) - var(--safe-area-inset-left, 0px), 0px) / 2);
--safe-area-offset-top: calc(max(var(--safe-area-inset-top, 0px) - var(--safe-area-inset-bottom, 0px), 0px) / 2);
--safe-area-offset-bottom: calc(max(var(--safe-area-inset-bottom, 0px) - var(--safe-area-inset-top, 0px), 0px) / 2);

/* Safe width and height for use instead of 100vw and 100vh
* when working with areas like dialogs which need to fill the entire safe area.
*/
--safe-width: calc(100vw - var(--safe-area-inset-left) - var(--safe-area-inset-right));
--safe-height: calc(100vh - var(--safe-area-inset-top) - var(--safe-area-inset-bottom));
}
`;

Expand Down
Loading