Compare commits

...

12 Commits

Author SHA1 Message Date
Aidan Timson
0f5029f2b0 Reset on view change 2026-02-27 16:09:05 +00:00
Aidan Timson
a283aaad4c Fix 2026-02-27 16:06:42 +00:00
Aidan Timson
2656df7f76 Restore fullscreen on more info dialog 2026-02-27 16:05:58 +00:00
Aidan Timson
6777b0d656 Use public property 2026-02-27 15:57:51 +00:00
Aidan Timson
0fea57a062 Remove this._fullscreen, no longer used 2026-02-27 15:57:51 +00:00
Aidan Timson
530feb49d4 Use an in-dialog flag 2026-02-27 15:57:51 +00:00
Aidan Timson
b74de6c7d0 Handle fullscreen mode internally in code editor 2026-02-27 15:57:51 +00:00
Aidan Timson
df4fbc43d8 Add view transitions to mode swaps 2026-02-27 15:57:51 +00:00
Aidan Timson
d079e8bbd5 Remove fullscreen when switching back to normal mode 2026-02-27 15:57:51 +00:00
Aidan Timson
9e1fb2648f Add view transition 2026-02-27 15:57:51 +00:00
Aidan Timson
6ec20ca1a6 Fix for code editor 2026-02-27 15:57:51 +00:00
Aidan Timson
2d3abf1a63 Setup fullscreen event 2026-02-27 15:57:50 +00:00
13 changed files with 144 additions and 7 deletions

View File

@@ -84,6 +84,9 @@ export class HaCodeEditor extends ReactiveElement {
@property({ type: Boolean, attribute: "disable-fullscreen" })
public disableFullscreen = false;
@property({ type: Boolean, attribute: "in-dialog" })
public inDialog = false;
@property({ type: Boolean, attribute: "has-toolbar" })
public hasToolbar = true;
@@ -132,6 +135,7 @@ export class HaCodeEditor extends ReactiveElement {
public connectedCallback() {
super.connectedCallback();
this.classList.toggle("in-dialog", this.inDialog);
// Force update on reconnection so editor is recreated
if (this.hasUpdated) {
this.requestUpdate();
@@ -150,6 +154,7 @@ export class HaCodeEditor extends ReactiveElement {
}
public disconnectedCallback() {
fireEvent(this, "dialog-set-fullscreen", false);
super.disconnectedCallback();
this.removeEventListener("keydown", stopPropagation);
this.removeEventListener("keydown", this._handleKeyDown);
@@ -216,6 +221,9 @@ export class HaCodeEditor extends ReactiveElement {
if (changedProps.has("error")) {
this.classList.toggle("error-state", this.error);
}
if (changedProps.has("inDialog")) {
this.classList.toggle("in-dialog", this.inDialog);
}
if (changedProps.has("_isFullscreen")) {
this.classList.toggle("fullscreen", this._isFullscreen);
this._updateToolbarButtons();
@@ -434,10 +442,19 @@ export class HaCodeEditor extends ReactiveElement {
private _updateFullscreenState(
fullscreen: boolean = this._isFullscreen
): boolean {
const previousFullscreen = this._isFullscreen;
this.classList.toggle("in-dialog", this.inDialog);
// Update the current fullscreen state based on selected value. If fullscreen
// is disabled, or we have no toolbar, ensure we are not in fullscreen mode.
this._isFullscreen =
fullscreen && !this.disableFullscreen && this.hasToolbar;
if (previousFullscreen !== this._isFullscreen) {
fireEvent(this, "dialog-set-fullscreen", this._isFullscreen);
}
// Return whether successfully in requested state
return this._isFullscreen === fullscreen;
}
@@ -846,10 +863,10 @@ export class HaCodeEditor extends ReactiveElement {
:host(.fullscreen) {
position: fixed !important;
top: calc(var(--header-height, 56px) + 8px) !important;
left: 8px !important;
right: 8px !important;
bottom: 8px !important;
top: calc(var(--header-height, 56px) + var(--ha-space-2)) !important;
left: var(--ha-space-2) !important;
right: var(--ha-space-2) !important;
bottom: var(--ha-space-2) !important;
z-index: 6;
border-radius: var(--ha-border-radius-lg) !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3) !important;
@@ -867,6 +884,17 @@ export class HaCodeEditor extends ReactiveElement {
display: block !important;
}
:host(.in-dialog.fullscreen) {
position: absolute !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
border-radius: 0 !important;
box-shadow: none !important;
padding: 0 !important;
}
:host(.hasToolbar) .cm-editor {
padding-top: var(--code-editor-toolbar-height);
}

View File

@@ -10,7 +10,9 @@ import {
state,
} from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import type { HASSDomEvent } from "../common/dom/fire_event";
import { fireEvent } from "../common/dom/fire_event";
import { withViewTransition } from "../common/util/view-transition";
import { ScrollableFadeMixin } from "../mixins/scrollable-fade-mixin";
import { haStyleScrollbar } from "../resources/styles";
import type { HomeAssistant } from "../types";
@@ -127,6 +129,14 @@ export class HaDialog extends ScrollableFadeMixin(LitElement) {
private _escapePressed = false;
public connectedCallback(): void {
super.connectedCallback();
this.addEventListener(
"dialog-set-fullscreen",
this._handleFullscreenChanged as EventListener
);
}
protected get scrollableElement(): HTMLElement | null {
return this.bodyContainer;
}
@@ -227,15 +237,36 @@ export class HaDialog extends ScrollableFadeMixin(LitElement) {
private _handleAfterHide = (ev: DialogHideEvent) => {
if (ev.eventPhase === Event.AT_TARGET) {
this._open = false;
this._setFullscreen(false);
fireEvent(this, "closed");
}
};
public disconnectedCallback(): void {
this.removeEventListener(
"dialog-set-fullscreen",
this._handleFullscreenChanged as EventListener
);
this._setFullscreen(false);
super.disconnectedCallback();
this._open = false;
}
private _handleFullscreenChanged(ev: HASSDomEvent<boolean>): void {
if (!this._open) {
this._setFullscreen(ev.detail);
return;
}
withViewTransition(() => {
this._setFullscreen(ev.detail);
});
}
private _setFullscreen(fullscreen: boolean): void {
this.toggleAttribute("fullscreen", fullscreen);
}
@eventOptions({ passive: true })
private _handleBodyScroll(ev: Event) {
this._bodyScrolled = (ev.target as HTMLDivElement).scrollTop > 0;
@@ -301,10 +332,27 @@ export class HaDialog extends ScrollableFadeMixin(LitElement) {
--width: min(var(--ha-dialog-width-lg, 1024px), var(--full-width));
}
:host([width="full"]) wa-dialog {
:host([width="full"]) wa-dialog,
:host([fullscreen]) wa-dialog {
--width: var(--full-width);
}
:host([fullscreen]) wa-dialog::part(dialog) {
min-height: var(--safe-height);
max-height: var(--safe-height);
margin-top: 0;
transform: none;
}
:host([fullscreen]) .content-wrapper {
overflow: hidden;
}
:host([fullscreen]) .body {
overflow: hidden;
padding: 0;
}
wa-dialog::part(dialog) {
-webkit-backdrop-filter: var(
--ha-dialog-surface-backdrop-filter,
@@ -465,6 +513,7 @@ declare global {
}
interface HASSDomEvents {
"dialog-set-fullscreen": boolean;
opened: undefined;
"after-show": undefined;
closed: undefined;

View File

@@ -47,6 +47,9 @@ export class HaYamlEditor extends LitElement {
@property({ type: Boolean, attribute: "disable-fullscreen" })
public disableFullscreen = false;
@property({ type: Boolean, attribute: "in-dialog" })
public inDialog = false;
@property({ type: Boolean }) public required = false;
@property({ attribute: "copy-clipboard", type: Boolean })
@@ -101,6 +104,13 @@ export class HaYamlEditor extends LitElement {
}
}
public disableCodeEditorFullscreen(): void {
this.disableFullscreen = true;
if (this._codeEditor) {
this._codeEditor.disableFullscreen = true;
}
}
protected render() {
if (this._yaml === undefined) {
return nothing;
@@ -114,6 +124,7 @@ export class HaYamlEditor extends LitElement {
.value=${this._yaml}
.readOnly=${this.readOnly}
.disableFullscreen=${this.disableFullscreen}
.inDialog=${this.inDialog}
mode="yaml"
autocomplete-entities
autocomplete-icons

View File

@@ -61,6 +61,7 @@ class HaMoreInfoDetails extends LitElement {
.value=${yamlData}
read-only
auto-update
.inDialog=${true}
></ha-yaml-editor>`
: html`
<section class="section">

View File

@@ -119,6 +119,8 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
@query(".content") private _contentElement?: HTMLDivElement;
@query("ha-adaptive-dialog") private _dialogElement?: HTMLElement;
@state() private _entityId?: string | null;
@state() private _data?: Record<string, any>;
@@ -177,6 +179,10 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
}
public closeDialog() {
const dialog = this._dialogElement?.shadowRoot?.querySelector("ha-dialog");
if (dialog) {
fireEvent(dialog as HTMLElement, "dialog-set-fullscreen", false);
}
this._open = false;
}
@@ -254,6 +260,11 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
private _goBack() {
if (this._childView) {
const dialog =
this._dialogElement?.shadowRoot?.querySelector("ha-dialog");
if (dialog) {
fireEvent(dialog as HTMLElement, "dialog-set-fullscreen", false);
}
this._childView = undefined;
this._detailsYamlMode = false;
return;
@@ -320,6 +331,10 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
}
private _toggleDetailsYamlMode() {
const dialog = this._dialogElement?.shadowRoot?.querySelector("ha-dialog");
if (dialog) {
fireEvent(dialog as HTMLElement, "dialog-set-fullscreen", false);
}
this._detailsYamlMode = !this._detailsYamlMode;
}
@@ -749,6 +764,21 @@ export class MoreInfoDialog extends ScrollableFadeMixin(LitElement) {
protected updated(changedProps: PropertyValues) {
super.updated(changedProps);
const previousChildView = changedProps.get("_childView") as
| ChildView
| undefined;
if (
previousChildView?.viewTag === "ha-more-info-details" &&
this._childView?.viewTag !== "ha-more-info-details"
) {
const dialog =
this._dialogElement?.shadowRoot?.querySelector("ha-dialog");
if (dialog) {
fireEvent(dialog as HTMLElement, "dialog-set-fullscreen", false);
}
}
if (changedProps.has("_currView")) {
this._childView = undefined;
this._infoEditMode = false;

View File

@@ -226,6 +226,7 @@ export class HuiDialogEditBadge
.hass=${this.hass}
.lovelace=${this._params.lovelaceConfig}
.value=${this._badgeConfig}
.inDialog=${true}
@config-changed=${this._handleConfigChanged}
@GUImode-changed=${this._handleGUIModeChanged}
@editor-save=${this._save}
@@ -314,7 +315,9 @@ export class HuiDialogEditBadge
}
private _toggleMode(): void {
this._badgeEditorEl?.toggleMode();
withViewTransition(() => {
this._badgeEditorEl?.toggleMode();
});
}
private _opened() {

View File

@@ -97,6 +97,7 @@ export class HuiDialogSuggestBadge extends LitElement {
<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this._badgeConfig}
.inDialog=${true}
></ha-yaml-editor>
</div>
`

View File

@@ -203,6 +203,7 @@ export class HuiDialogEditCard
.hass=${this.hass}
.lovelace=${this._params.lovelaceConfig}
.value=${this._cardConfig}
.inDialog=${true}
@config-changed=${this._handleConfigChanged}
@GUImode-changed=${this._handleGUIModeChanged}
@editor-save=${this._save}
@@ -297,7 +298,9 @@ export class HuiDialogEditCard
}
private _toggleMode(): void {
this._cardEditorEl?.toggleMode();
withViewTransition(() => {
this._cardEditorEl?.toggleMode();
});
}
private _opened() {

View File

@@ -133,6 +133,7 @@ export class HuiDialogSuggestCard extends LitElement {
<ha-yaml-editor
.hass=${this.hass}
.defaultValue=${this._cardConfig}
.inDialog=${true}
></ha-yaml-editor>
</div>
`

View File

@@ -57,6 +57,9 @@ export abstract class HuiElementEditor<
@property({ attribute: false }) public context?: C;
@property({ type: Boolean, attribute: "in-dialog" })
public inDialog = false;
@state() private _config?: T;
@state() private _configElement?: LovelaceGenericElementEditor;
@@ -150,6 +153,9 @@ export abstract class HuiElementEditor<
}
public toggleMode() {
if (!this.GUImode) {
this._yamlEditor?.disableCodeEditorFullscreen();
}
this.GUImode = !this.GUImode;
}
@@ -243,6 +249,7 @@ export abstract class HuiElementEditor<
.defaultValue=${this._config}
autofocus
.hass=${this.hass}
.inDialog=${this.inDialog}
@value-changed=${this._handleYAMLChanged}
@blur=${this._onBlurYaml}
@keydown=${this._ignoreKeydown}

View File

@@ -127,6 +127,7 @@ export class HuiDialogEditSection
<ha-yaml-editor
.hass=${this.hass}
autofocus
.inDialog=${true}
@value-changed=${this._viewYamlChanged}
></ha-yaml-editor>
`;

View File

@@ -162,6 +162,7 @@ export class HuiDialogEditView extends LitElement {
<ha-yaml-editor
.hass=${this.hass}
autofocus
.inDialog=${true}
@value-changed=${this._viewYamlChanged}
></ha-yaml-editor>
`;

View File

@@ -84,6 +84,7 @@ export class HuiDialogEditViewHeader extends LitElement {
<ha-yaml-editor
.hass=${this.hass}
autofocus
.inDialog=${true}
@value-changed=${this._viewYamlChanged}
></ha-yaml-editor>
`;