diff --git a/src/components/ha-form/ha-form-expandable.ts b/src/components/ha-form/ha-form-expandable.ts
index f8e88c43aa..1ffa6339b5 100644
--- a/src/components/ha-form/ha-form-expandable.ts
+++ b/src/components/ha-form/ha-form-expandable.ts
@@ -21,13 +21,45 @@ export class HaFormExpendable extends LitElement implements HaFormElement {
@property({ attribute: false }) public computeLabel?: (
schema: HaFormSchema,
- data?: HaFormDataContainer
+ data?: HaFormDataContainer,
+ options?: { path?: string[] }
) => string;
@property({ attribute: false }) public computeHelper?: (
- schema: HaFormSchema
+ schema: HaFormSchema,
+ options?: { path?: string[] }
) => string;
+ private _renderDescription() {
+ const description = this.computeHelper?.(this.schema);
+ return description ? html`
${description}
` : nothing;
+ }
+
+ private _computeLabel = (
+ schema: HaFormSchema,
+ data?: HaFormDataContainer,
+ options?: { path?: string[] }
+ ) => {
+ if (!this.computeLabel) return this.computeLabel;
+
+ return this.computeLabel(schema, data, {
+ ...options,
+ path: [...(options?.path || []), this.schema.name],
+ });
+ };
+
+ private _computeHelper = (
+ schema: HaFormSchema,
+ options?: { path?: string[] }
+ ) => {
+ if (!this.computeHelper) return this.computeHelper;
+
+ return this.computeHelper(schema, {
+ ...options,
+ path: [...(options?.path || []), this.schema.name],
+ });
+ };
+
protected render() {
return html`
@@ -43,16 +75,17 @@ export class HaFormExpendable extends LitElement implements HaFormElement {
`
: nothing}
- ${this.schema.title}
+ ${this.schema.title || this.computeLabel?.(this.schema)}
+ ${this._renderDescription()}
@@ -71,6 +104,9 @@ export class HaFormExpendable extends LitElement implements HaFormElement {
.content {
padding: 12px;
}
+ .content p {
+ margin: 0 0 24px;
+ }
ha-expansion-panel {
display: block;
--expansion-panel-content-padding: 0;
diff --git a/src/components/ha-form/ha-form.ts b/src/components/ha-form/ha-form.ts
index 0d460098b0..0894ac38c4 100644
--- a/src/components/ha-form/ha-form.ts
+++ b/src/components/ha-form/ha-form.ts
@@ -31,7 +31,7 @@ const LOAD_ELEMENTS = {
};
const getValue = (obj, item) =>
- obj ? (!item.name ? obj : obj[item.name]) : null;
+ obj ? (!item.name || item.flatten ? obj : obj[item.name]) : null;
const getError = (obj, item) => (obj && item.name ? obj[item.name] : null);
@@ -73,10 +73,6 @@ export class HaForm extends LitElement implements HaFormElement {
schema: any
) => string | undefined;
- @property({ attribute: false }) public localizeValue?: (
- key: string
- ) => string;
-
protected getFormProperties(): Record {
return {};
}
@@ -149,7 +145,6 @@ export class HaForm extends LitElement implements HaFormElement {
.disabled=${item.disabled || this.disabled || false}
.placeholder=${item.required ? "" : item.default}
.helper=${this._computeHelper(item)}
- .localizeValue=${this.localizeValue}
.required=${item.required || false}
.context=${this._generateContext(item)}
>`
@@ -204,9 +199,10 @@ export class HaForm extends LitElement implements HaFormElement {
if (ev.target === this) return;
- const newValue = !schema.name
- ? ev.detail.value
- : { [schema.name]: ev.detail.value };
+ const newValue =
+ !schema.name || ("flatten" in schema && schema.flatten)
+ ? ev.detail.value
+ : { [schema.name]: ev.detail.value };
this.data = {
...this.data,
diff --git a/src/components/ha-form/types.ts b/src/components/ha-form/types.ts
index e2e032312d..53a51313a1 100644
--- a/src/components/ha-form/types.ts
+++ b/src/components/ha-form/types.ts
@@ -31,15 +31,15 @@ export interface HaFormBaseSchema {
export interface HaFormGridSchema extends HaFormBaseSchema {
type: "grid";
- name: string;
+ flatten?: boolean;
column_min_width?: string;
schema: readonly HaFormSchema[];
}
export interface HaFormExpandableSchema extends HaFormBaseSchema {
type: "expandable";
- name: "";
- title: string;
+ flatten?: boolean;
+ title?: string;
icon?: string;
iconPath?: string;
expanded?: boolean;
@@ -100,7 +100,7 @@ export type SchemaUnion<
SchemaArray extends readonly HaFormSchema[],
Schema = SchemaArray[number],
> = Schema extends HaFormGridSchema | HaFormExpandableSchema
- ? SchemaUnion
+ ? SchemaUnion | Schema
: Schema;
export interface HaFormDataContainer {
diff --git a/src/components/ha-selector/ha-selector-location.ts b/src/components/ha-selector/ha-selector-location.ts
index 01fc052cb2..2ac0b8b82b 100644
--- a/src/components/ha-selector/ha-selector-location.ts
+++ b/src/components/ha-selector/ha-selector-location.ts
@@ -162,8 +162,14 @@ export class HaLocationSelector extends LitElement {
private _computeLabel = (
entry: SchemaUnion>
- ): string =>
- this.hass.localize(`ui.components.selectors.location.${entry.name}`);
+ ): string => {
+ if (entry.name) {
+ return this.hass.localize(
+ `ui.components.selectors.location.${entry.name}`
+ );
+ }
+ return "";
+ };
static styles = css`
ha-locations-editor {
diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts
index 1f930ea970..6682ce9a17 100644
--- a/src/dialogs/config-flow/show-dialog-config-flow.ts
+++ b/src/dialogs/config-flow/show-dialog-config-flow.ts
@@ -76,19 +76,36 @@ export const showConfigFlowDialog = (
: "";
},
- renderShowFormStepFieldLabel(hass, step, field) {
+ renderShowFormStepFieldLabel(hass, step, field, options) {
+ if (field.type === "expandable") {
+ return hass.localize(
+ `component.${step.handler}.config.step.${step.step_id}.sections.${field.name}.name`
+ );
+ }
+
+ const prefix = options?.path?.[0] ? `sections.${options.path[0]}` : "";
+
return (
hass.localize(
- `component.${step.handler}.config.step.${step.step_id}.data.${field.name}`
+ `component.${step.handler}.config.step.${step.step_id}.${prefix}data.${field.name}`
) || field.name
);
},
- renderShowFormStepFieldHelper(hass, step, field) {
+ renderShowFormStepFieldHelper(hass, step, field, options) {
+ if (field.type === "expandable") {
+ return hass.localize(
+ `component.${step.translation_domain || step.handler}.config.step.${step.step_id}.sections.${field.name}.description`
+ );
+ }
+
+ const prefix = options?.path?.[0] ? `sections.${options.path[0]}.` : "";
+
const description = hass.localize(
- `component.${step.translation_domain || step.handler}.config.step.${step.step_id}.data_description.${field.name}`,
+ `component.${step.translation_domain || step.handler}.config.step.${step.step_id}.${prefix}data_description.${field.name}`,
step.description_placeholders
);
+
return description
? html``
: "";
diff --git a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts
index 54caaecbc7..4ae9965e85 100644
--- a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts
+++ b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts
@@ -49,13 +49,15 @@ export interface FlowConfig {
renderShowFormStepFieldLabel(
hass: HomeAssistant,
step: DataEntryFlowStepForm,
- field: HaFormSchema
+ field: HaFormSchema,
+ options: { path?: string[]; [key: string]: any }
): string;
renderShowFormStepFieldHelper(
hass: HomeAssistant,
step: DataEntryFlowStepForm,
- field: HaFormSchema
+ field: HaFormSchema,
+ options: { path?: string[]; [key: string]: any }
): TemplateResult | string;
renderShowFormStepFieldError(
diff --git a/src/dialogs/config-flow/show-dialog-options-flow.ts b/src/dialogs/config-flow/show-dialog-options-flow.ts
index 829f7b4718..089f0eee33 100644
--- a/src/dialogs/config-flow/show-dialog-options-flow.ts
+++ b/src/dialogs/config-flow/show-dialog-options-flow.ts
@@ -93,17 +93,33 @@ export const showOptionsFlowDialog = (
: "";
},
- renderShowFormStepFieldLabel(hass, step, field) {
+ renderShowFormStepFieldLabel(hass, step, field, options) {
+ if (field.type === "expandable") {
+ return hass.localize(
+ `component.${configEntry.domain}.options.step.${step.step_id}.sections.${field.name}.name`
+ );
+ }
+
+ const prefix = options?.path?.[0] ? `sections.${options.path[0]}.` : "";
+
return (
hass.localize(
- `component.${configEntry.domain}.options.step.${step.step_id}.data.${field.name}`
+ `component.${configEntry.domain}.options.step.${step.step_id}.${prefix}data.${field.name}`
) || field.name
);
},
- renderShowFormStepFieldHelper(hass, step, field) {
+ renderShowFormStepFieldHelper(hass, step, field, options) {
+ if (field.type === "expandable") {
+ return hass.localize(
+ `component.${step.translation_domain || configEntry.domain}.options.step.${step.step_id}.sections.${field.name}.description`
+ );
+ }
+
+ const prefix = options?.path?.[0] ? `sections.${options.path[0]}.` : "";
+
const description = hass.localize(
- `component.${step.translation_domain || configEntry.domain}.options.step.${step.step_id}.data_description.${field.name}`,
+ `component.${step.translation_domain || configEntry.domain}.options.step.${step.step_id}.${prefix}data_description.${field.name}`,
step.description_placeholders
);
return description
diff --git a/src/dialogs/config-flow/step-flow-form.ts b/src/dialogs/config-flow/step-flow-form.ts
index 20c665df90..537c5731dd 100644
--- a/src/dialogs/config-flow/step-flow-form.ts
+++ b/src/dialogs/config-flow/step-flow-form.ts
@@ -225,11 +225,24 @@ class StepFlowForm extends LitElement {
this._stepData = ev.detail.value;
}
- private _labelCallback = (field: HaFormSchema): string =>
- this.flowConfig.renderShowFormStepFieldLabel(this.hass, this.step, field);
+ private _labelCallback = (field: HaFormSchema, _data, options): string =>
+ this.flowConfig.renderShowFormStepFieldLabel(
+ this.hass,
+ this.step,
+ field,
+ options
+ );
- private _helperCallback = (field: HaFormSchema): string | TemplateResult =>
- this.flowConfig.renderShowFormStepFieldHelper(this.hass, this.step, field);
+ private _helperCallback = (
+ field: HaFormSchema,
+ options
+ ): string | TemplateResult =>
+ this.flowConfig.renderShowFormStepFieldHelper(
+ this.hass,
+ this.step,
+ field,
+ options
+ );
private _errorCallback = (error: string) =>
this.flowConfig.renderShowFormStepFieldError(this.hass, this.step, error);
diff --git a/src/panels/config/repairs/show-dialog-repair-flow.ts b/src/panels/config/repairs/show-dialog-repair-flow.ts
index 015b60b2d3..8114d3ab75 100644
--- a/src/panels/config/repairs/show-dialog-repair-flow.ts
+++ b/src/panels/config/repairs/show-dialog-repair-flow.ts
@@ -96,20 +96,20 @@ export const showRepairsFlowDialog = (
: "";
},
- renderShowFormStepFieldLabel(hass, step, field) {
+ renderShowFormStepFieldLabel(hass, step, field, options) {
return hass.localize(
`component.${issue.domain}.issues.${
issue.translation_key || issue.issue_id
- }.fix_flow.step.${step.step_id}.data.${field.name}`,
+ }.fix_flow.step.${step.step_id}.${options?.prefix ? `section.${options.prefix[0]}.` : ""}data.${field.name}`,
step.description_placeholders
);
},
- renderShowFormStepFieldHelper(hass, step, field) {
+ renderShowFormStepFieldHelper(hass, step, field, options) {
const description = hass.localize(
`component.${issue.domain}.issues.${
issue.translation_key || issue.issue_id
- }.fix_flow.step.${step.step_id}.data_description.${field.name}`,
+ }.fix_flow.step.${step.step_id}.${options?.prefix ? `section.${options.prefix[0]}.` : ""}data_description.${field.name}`,
step.description_placeholders
);
return description
diff --git a/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts
index d2a9d155d2..2458596fa4 100644
--- a/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts
@@ -74,10 +74,10 @@ export class HuiEntityBadgeEditor
[
{ name: "entity", selector: { entity: {} } },
{
- name: "",
+ name: "appearance",
type: "expandable",
+ flatten: true,
iconPath: mdiPalette,
- title: localize(`ui.panel.lovelace.editor.badge.entity.appearance`),
schema: [
{
name: "",
@@ -153,9 +153,9 @@ export class HuiEntityBadgeEditor
],
},
{
- name: "",
+ name: "interactions",
type: "expandable",
- title: localize(`ui.panel.lovelace.editor.badge.entity.interactions`),
+ flatten: true,
iconPath: mdiGestureTap,
schema: [
{
@@ -238,6 +238,8 @@ export class HuiEntityBadgeEditor
case "state_content":
case "show_entity_picture":
case "displayed_elements":
+ case "appearance":
+ case "interactions":
return this.hass!.localize(
`ui.panel.lovelace.editor.badge.entity.${schema.name}`
);
diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
index 587bb85fe4..cc8500eeb6 100644
--- a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
+++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
@@ -14,7 +14,6 @@ import {
union,
} from "superstruct";
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
-import { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/ha-form/ha-form";
import type {
HaFormSchema,
@@ -69,18 +68,14 @@ export class HuiTileCardEditor
}
private _schema = memoizeOne(
- (
- localize: LocalizeFunc,
- entityId: string | undefined,
- hideState: boolean
- ) =>
+ (entityId: string | undefined, hideState: boolean) =>
[
{ name: "entity", selector: { entity: {} } },
{
- name: "",
+ name: "appearance",
+ flatten: true,
type: "expandable",
iconPath: mdiPalette,
- title: localize(`ui.panel.lovelace.editor.card.tile.appearance`),
schema: [
{
name: "",
@@ -136,9 +131,9 @@ export class HuiTileCardEditor
],
},
{
- name: "",
+ name: "interactions",
type: "expandable",
- title: localize(`ui.panel.lovelace.editor.card.tile.interactions`),
+ flatten: true,
iconPath: mdiGestureTap,
schema: [
{
@@ -178,7 +173,6 @@ export class HuiTileCardEditor
: undefined;
const schema = this._schema(
- this.hass!.localize,
this._config.entity,
this._config.hide_state ?? false
);
@@ -306,6 +300,8 @@ export class HuiTileCardEditor
case "vertical":
case "hide_state":
case "state_content":
+ case "appearance":
+ case "interactions":
return this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.${schema.name}`
);