diff --git a/src/dialogs/config-flow/dialog-data-entry-flow.ts b/src/dialogs/config-flow/dialog-data-entry-flow.ts index d03e2aa4a9..be9bf9d761 100644 --- a/src/dialogs/config-flow/dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/dialog-data-entry-flow.ts @@ -6,8 +6,7 @@ import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import type { HASSDomEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event"; -import "../../components/ha-dialog"; -import "../../components/ha-dialog-header"; +import "../../components/ha-wa-dialog"; import "../../components/ha-icon-button"; import type { DataEntryFlowStep } from "../../data/data_entry_flow"; import { @@ -64,6 +63,8 @@ class DataEntryFlowDialog extends LitElement { private _instance = instance; + @state() private _open = false; + @state() private _step: | DataEntryFlowStep | undefined @@ -77,6 +78,7 @@ class DataEntryFlowDialog extends LitElement { public async showDialog(params: DataEntryFlowDialogParams): Promise { this._params = params; this._instance = instance++; + this._open = true; const curInstance = this._instance; let step: DataEntryFlowStep; @@ -146,6 +148,17 @@ class DataEntryFlowDialog extends LitElement { } public closeDialog() { + if (!this._params) { + return; + } + if (!this._open) { + this._dialogClosed(); + return; + } + this._open = false; + } + + private _dialogClosed(): void { if (!this._params) { return; } @@ -174,6 +187,7 @@ class DataEntryFlowDialog extends LitElement { this._unsubDataEntryFlowProgress(); this._unsubDataEntryFlowProgress = undefined; } + this._open = false; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -289,56 +303,53 @@ class DataEntryFlowDialog extends LitElement { const dialogSubtitle = this._getDialogSubtitle(); return html` - - - + -
- ${dialogTitle} -
+
+ ${dialogTitle} +
- ${dialogSubtitle - ? html`
${dialogSubtitle}
` - : nothing} - ${showDocumentationLink && !this._loading && this._step - ? html` - ${dialogSubtitle}` + : nothing} + ${showDocumentationLink && !this._loading && this._step + ? html` + + - - - ` - : nothing} -
+ + ` + : nothing}
${this._loading || this._step === null ? html` @@ -358,6 +369,7 @@ class DataEntryFlowDialog extends LitElement { ${this._step.type === "form" ? html` - + `; } @@ -547,11 +559,24 @@ class DataEntryFlowDialog extends LitElement { }; } + private _focusFormStep = async (): Promise => { + if (this._step?.type !== "form" || !this._open) { + return; + } + + await this.updateComplete; + ( + this.renderRoot.querySelector( + "step-flow-form[autofocus]" + ) as HTMLElement | null + )?.focus(); + }; + static get styles(): CSSResultGroup { return [ haStyleDialog, css` - ha-dialog { + ha-wa-dialog { --dialog-content-padding: 0; } .dialog-title { diff --git a/src/dialogs/config-flow/step-flow-form.ts b/src/dialogs/config-flow/step-flow-form.ts index 4692764fe5..85f5998acf 100644 --- a/src/dialogs/config-flow/step-flow-form.ts +++ b/src/dialogs/config-flow/step-flow-form.ts @@ -29,6 +29,8 @@ class StepFlowForm extends LitElement { @property({ type: Boolean }) public narrow = false; + @property({ type: Boolean, attribute: "autofocus" }) public autoFocus = false; + @property({ attribute: false }) public step!: DataEntryFlowStepForm; @property({ attribute: false }) public hass!: HomeAssistant; @@ -45,6 +47,11 @@ class StepFlowForm extends LitElement { private _errors?: Record; + static shadowRootOptions: ShadowRootInit = { + ...LitElement.shadowRootOptions, + delegatesFocus: true, + }; + public disconnectedCallback(): void { super.disconnectedCallback(); this.removeEventListener("keydown", this._handleKeyDown); @@ -83,6 +90,7 @@ class StepFlowForm extends LitElement { ? html`${this._errorMsg}` : ""} this.shadowRoot!.querySelector("ha-form")!.focus(), 0); this.addEventListener("keydown", this._handleKeyDown); } + public override focus(_options?: FocusOptions): void { + this.renderRoot.querySelector("ha-form")?.focus(); + } + protected willUpdate(changedProps: PropertyValues): void { super.willUpdate(changedProps); if (changedProps.has("step") && this.step?.preview) { diff --git a/src/panels/config/integrations/dialog-add-integration.ts b/src/panels/config/integrations/dialog-add-integration.ts index 0351c34af8..62981bea38 100644 --- a/src/panels/config/integrations/dialog-add-integration.ts +++ b/src/panels/config/integrations/dialog-add-integration.ts @@ -1,11 +1,9 @@ -import { mdiClose } from "@mdi/js"; import type { IFuseOptions } from "fuse.js"; import Fuse from "fuse.js"; import type { HassConfig } from "home-assistant-js-websocket"; import type { PropertyValues, TemplateResult } from "lit"; import { LitElement, css, html, nothing } from "lit"; import { customElement, state } from "lit/decorators"; -import { ifDefined } from "lit/directives/if-defined"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; @@ -17,10 +15,10 @@ import { import { navigate } from "../../../common/navigate"; import { caseInsensitiveStringCompare } from "../../../common/string/compare"; import type { LocalizeFunc } from "../../../common/translations/localize"; -import { createCloseHeading } from "../../../components/ha-dialog"; import "../../../components/ha-icon-button-prev"; import "../../../components/ha-list"; import "../../../components/ha-spinner"; +import "../../../components/ha-wa-dialog"; import "../../../components/search-input"; import { getConfigEntries } from "../../../data/config_entries"; import { @@ -145,6 +143,10 @@ class AddIntegrationDialog extends LitElement { public closeDialog() { this._open = false; + } + + private _dialogClosed() { + this._open = false; this._integrations = undefined; this._helpers = undefined; this._pickedBrand = undefined; @@ -361,7 +363,7 @@ class AddIntegrationDialog extends LitElement { } protected render() { - if (!this._open) { + if (!this._open && !this._integrations && !this._helpers) { return nothing; } const integrations = this._integrations @@ -373,20 +375,38 @@ class AddIntegrationDialog extends LitElement { findIntegration(this._integrations, this._pickedBrand) : undefined; - return html` - ${(this._pickedBrand && (!this._integrations || pickedIntegration)) || - this._showDiscovered - ? this._renderBrandView(pickedIntegration) + ${showingBrandView + ? html` + ${!this._openedDirectly + ? html` + + ` + : nothing} + ${this._renderBrandView(pickedIntegration, flowsInProgress)} + ` : this._renderAll(integrations)} - `; + `; } private _getFlowsForCurrentView( @@ -413,61 +433,53 @@ class AddIntegrationDialog extends LitElement { return this._getFlowsInProgressForDomains(domains); } - private _renderBrandView( - integration: Brand | Integration | undefined - ): TemplateResult { - const flowsInProgress = this._getFlowsForCurrentView(integration); - - let heading: string; + private _getBrandHeading( + integration: Brand | Integration | undefined, + flowsInProgress: DataEntryFlowProgress[] + ): string { if ( integration?.iot_standards && !("integrations" in integration) && !flowsInProgress.length ) { - heading = this.hass.localize( + return this.hass.localize( "ui.panel.config.integrations.what_device_type" ); - } else if ( + } + + if ( integration && !integration?.iot_standards && !("integrations" in integration) && flowsInProgress.length ) { - heading = this.hass.localize( + return this.hass.localize( "ui.panel.config.integrations.confirm_add_discovered" ); - } else { - heading = this.hass.localize("ui.panel.config.integrations.what_to_add"); } - return html`
- ${this._openedDirectly - ? html`` - : html``} -

${heading}

-
- `; + return this.hass.localize("ui.panel.config.integrations.what_to_add"); + } + + private _renderBrandView( + integration: Brand | Integration | undefined, + flowsInProgress: DataEntryFlowProgress[] + ): TemplateResult { + return html``; } private _handleSelectBrandEvent(ev: CustomEvent) { @@ -524,7 +536,7 @@ class AddIntegrationDialog extends LitElement { private _renderAll(integrations?: IntegrationListItem[]): TemplateResult { return html` ${integrations - ? html` + ? html`

${this.hass.localize( "ui.panel.config.integrations.config_flow.yaml_only" )}

- - ${this.hass.localize("ui.common.cancel")} - - ${docLink - ? html` - ${this.hass.localize( - "ui.panel.config.integrations.config_flow.open_documentation" - )} - ` - : html` - ${this.hass.localize("ui.common.ok")} - `} - + + + ${this.hass.localize("ui.common.cancel")} + + ${docLink + ? html` + + ${this.hass.localize( + "ui.panel.config.integrations.config_flow.open_documentation" + )} + ` + : html` + ${this.hass.localize("ui.common.ok")} + `} + + `; } @@ -79,15 +97,10 @@ export class DialogYamlIntegration extends LitElement { a { text-decoration: none; } - ha-dialog { + ha-wa-dialog { /* Place above other dialogs */ --dialog-z-index: 104; } - @media all and (min-width: 600px) { - ha-dialog { - --mdc-dialog-min-width: 400px; - } - } `; }