Add support for option descriptions in config flows (#26825)

* Add support for option descriptions in config flows

* use `twoline`

* remove unused classes
This commit is contained in:
Petar Petrov
2025-09-02 17:03:35 +03:00
committed by GitHub
parent c6c3170c1b
commit c49d2a0be6
6 changed files with 66 additions and 4 deletions

View File

@@ -256,6 +256,13 @@ export const showConfigFlowDialog = (
); );
}, },
renderMenuOptionDescription(hass, step, option) {
return hass.localize(
`component.${step.translation_domain || step.handler}.config.step.${step.step_id}.menu_option_descriptions.${option}`,
step.description_placeholders
);
},
renderLoadingDescription(hass, reason, handler, step) { renderLoadingDescription(hass, reason, handler, step) {
if (reason !== "loading_flow" && reason !== "loading_step") { if (reason !== "loading_flow" && reason !== "loading_step") {
return ""; return "";

View File

@@ -137,6 +137,12 @@ export interface FlowConfig {
option: string option: string
): string; ): string;
renderMenuOptionDescription(
hass: HomeAssistant,
step: DataEntryFlowStepMenu,
option: string
): string;
renderLoadingDescription( renderLoadingDescription(
hass: HomeAssistant, hass: HomeAssistant,
loadingReason: LoadingReason, loadingReason: LoadingReason,

View File

@@ -225,6 +225,13 @@ export const showOptionsFlowDialog = (
); );
}, },
renderMenuOptionDescription(hass, step, option) {
return hass.localize(
`component.${step.translation_domain || configEntry.domain}.options.step.${step.step_id}.menu_option_descriptions.${option}`,
step.description_placeholders
);
},
renderLoadingDescription(hass, reason) { renderLoadingDescription(hass, reason) {
return ( return (
hass.localize(`component.${configEntry.domain}.options.loading`) || hass.localize(`component.${configEntry.domain}.options.loading`) ||

View File

@@ -252,6 +252,13 @@ export const showSubConfigFlowDialog = (
); );
}, },
renderMenuOptionDescription(hass, step, option) {
return hass.localize(
`component.${step.translation_domain || configEntry.domain}.config_subentries.${flowType}.step.${step.step_id}.menu_option_descriptions.${option}`,
step.description_placeholders
);
},
renderLoadingDescription(hass, reason, handler, step) { renderLoadingDescription(hass, reason, handler, step) {
if (reason !== "loading_flow" && reason !== "loading_step") { if (reason !== "loading_flow" && reason !== "loading_step") {
return ""; return "";

View File

@@ -1,5 +1,5 @@
import type { TemplateResult } from "lit"; import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-icon-next"; import "../../components/ha-icon-next";
@@ -20,6 +20,7 @@ class StepFlowMenu extends LitElement {
protected render(): TemplateResult { protected render(): TemplateResult {
let options: string[]; let options: string[];
let translations: Record<string, string>; let translations: Record<string, string>;
let optionDescriptions: Record<string, string> = {};
if (Array.isArray(this.step.menu_options)) { if (Array.isArray(this.step.menu_options)) {
options = this.step.menu_options; options = this.step.menu_options;
@@ -30,10 +31,26 @@ class StepFlowMenu extends LitElement {
this.step, this.step,
option option
); );
optionDescriptions[option] =
this.flowConfig.renderMenuOptionDescription(
this.hass,
this.step,
option
);
} }
} else { } else {
options = Object.keys(this.step.menu_options); options = Object.keys(this.step.menu_options);
translations = this.step.menu_options; translations = this.step.menu_options;
optionDescriptions = Object.fromEntries(
options.map((key) => [
key,
this.flowConfig.renderMenuOptionDescription(
this.hass,
this.step,
key
),
])
);
} }
const description = this.flowConfig.renderMenuDescription( const description = this.flowConfig.renderMenuDescription(
@@ -46,8 +63,18 @@ class StepFlowMenu extends LitElement {
<div class="options"> <div class="options">
${options.map( ${options.map(
(option) => html` (option) => html`
<ha-list-item hasMeta .step=${option} @click=${this._handleStep}> <ha-list-item
hasMeta
.step=${option}
@click=${this._handleStep}
?twoline=${optionDescriptions[option]}
>
<span>${translations[option]}</span> <span>${translations[option]}</span>
${optionDescriptions[option]
? html`<span slot="secondary">
${optionDescriptions[option]}
</span>`
: nothing}
<ha-icon-next slot="meta"></ha-icon-next> <ha-icon-next slot="meta"></ha-icon-next>
</ha-list-item> </ha-list-item>
` `
@@ -73,11 +100,10 @@ class StepFlowMenu extends LitElement {
css` css`
.options { .options {
margin-top: 20px; margin-top: 20px;
margin-bottom: 8px; margin-bottom: 16px;
} }
.content { .content {
padding-bottom: 16px; padding-bottom: 16px;
border-bottom: 1px solid var(--divider-color);
} }
.content + .options { .content + .options {
margin-top: 8px; margin-top: 8px;

View File

@@ -289,6 +289,15 @@ export const showRepairsFlowDialog = (
); );
}, },
renderMenuOptionDescription(hass, step, option) {
return hass.localize(
`component.${issue.domain}.issues.${
issue.translation_key || issue.issue_id
}.fix_flow.step.${step.step_id}.menu_option_descriptions.${option}`,
mergePlaceholders(issue, step)
);
},
renderLoadingDescription(hass, reason) { renderLoadingDescription(hass, reason) {
return ( return (
hass.localize( hass.localize(