diff --git a/src/dialogs/more-info/controls/more-info-group.js b/src/dialogs/more-info/controls/more-info-group.js
deleted file mode 100644
index fabab470cc..0000000000
--- a/src/dialogs/more-info/controls/more-info-group.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import { dom } from "@polymer/polymer/lib/legacy/polymer.dom";
-import { html } from "@polymer/polymer/lib/utils/html-tag";
-/* eslint-plugin-disable lit */
-import { PolymerElement } from "@polymer/polymer/polymer-element";
-import dynamicContentUpdater from "../../../common/dom/dynamic_content_updater";
-import { computeStateDomain } from "../../../common/entity/compute_state_domain";
-import "../../../state-summary/state-card-content";
-
-class MoreInfoGroup extends PolymerElement {
- static get template() {
- return html`
-
-
-
-
-
-
-
-
- `;
- }
-
- static get properties() {
- return {
- hass: {
- type: Object,
- },
-
- stateObj: {
- type: Object,
- },
-
- states: {
- type: Array,
- computed: "computeStates(stateObj, hass)",
- },
- };
- }
-
- static get observers() {
- return ["statesChanged(stateObj, states)"];
- }
-
- computeStates(stateObj, hass) {
- const states = [];
- const entIds = stateObj.attributes.entity_id || [];
-
- for (let i = 0; i < entIds.length; i++) {
- const state = hass.states[entIds[i]];
-
- if (state) {
- states.push(state);
- }
- }
-
- return states;
- }
-
- statesChanged(stateObj, states) {
- let groupDomainStateObj = false;
- let groupDomain = false;
-
- if (states && states.length > 0) {
- const baseStateObj = states.find((s) => s.state === "on") || states[0];
- groupDomain = computeStateDomain(baseStateObj);
-
- // Groups need to be filtered out or we'll show content of
- // first child above the children of the current group
- if (groupDomain !== "group") {
- groupDomainStateObj = {
- ...baseStateObj,
- entity_id: stateObj.entity_id,
- attributes: { ...baseStateObj.attributes },
- };
-
- for (let i = 0; i < states.length; i++) {
- if (groupDomain !== computeStateDomain(states[i])) {
- groupDomainStateObj = false;
- break;
- }
- }
- }
- }
-
- if (!groupDomainStateObj) {
- const el = dom(this.$.groupedControlDetails);
- if (el.lastChild) {
- el.removeChild(el.lastChild);
- }
- } else {
- dynamicContentUpdater(
- this.$.groupedControlDetails,
- "MORE-INFO-" + groupDomain.toUpperCase(),
- { stateObj: groupDomainStateObj, hass: this.hass }
- );
- }
- }
-}
-
-customElements.define("more-info-group", MoreInfoGroup);
diff --git a/src/dialogs/more-info/controls/more-info-group.ts b/src/dialogs/more-info/controls/more-info-group.ts
new file mode 100644
index 0000000000..788d1a2f6b
--- /dev/null
+++ b/src/dialogs/more-info/controls/more-info-group.ts
@@ -0,0 +1,111 @@
+import { HassEntity } from "home-assistant-js-websocket";
+import {
+ LitElement,
+ property,
+ CSSResult,
+ css,
+ internalProperty,
+ PropertyValues,
+} from "lit-element";
+import { html, TemplateResult } from "lit-html";
+import { dynamicElement } from "../../../common/dom/dynamic-element-directive";
+import { computeStateDomain } from "../../../common/entity/compute_state_domain";
+import "../../../state-summary/state-card-content";
+import { GroupEntity, HomeAssistant } from "../../../types";
+import {
+ importMoreInfoControl,
+ domainMoreInfoType,
+} from "../state_more_info_control";
+
+class MoreInfoGroup extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @property() public stateObj?: GroupEntity;
+
+ @internalProperty() private _groupDomainStateObj?: HassEntity;
+
+ @internalProperty() private _moreInfoType?: string;
+
+ protected updated(changedProperties: PropertyValues) {
+ if (
+ !this.hass ||
+ !this.stateObj ||
+ (!changedProperties.has("hass") && !changedProperties.has("stateObj"))
+ ) {
+ return;
+ }
+
+ const states = this.stateObj.attributes.entity_id
+ .map((entity_id) => this.hass.states[entity_id])
+ .filter((state) => state);
+
+ if (!states.length) {
+ this._groupDomainStateObj = undefined;
+ this._moreInfoType = undefined;
+ return;
+ }
+
+ const baseStateObj = states.find((s) => s.state === "on") || states[0];
+ const groupDomain = computeStateDomain(baseStateObj);
+
+ // Groups need to be filtered out or we'll show content of
+ // first child above the children of the current group
+ if (
+ groupDomain !== "group" &&
+ states.every((state) => groupDomain === computeStateDomain(state))
+ ) {
+ this._groupDomainStateObj = {
+ ...baseStateObj,
+ entity_id: this.stateObj.entity_id,
+ attributes: { ...baseStateObj.attributes },
+ };
+ const type = domainMoreInfoType(groupDomain);
+ importMoreInfoControl(type);
+ this._moreInfoType = type === "hidden" ? undefined : `more-info-${type}`;
+ } else {
+ this._groupDomainStateObj = undefined;
+ this._moreInfoType = undefined;
+ }
+ }
+
+ protected render(): TemplateResult {
+ if (!this.hass || !this.stateObj) {
+ return html``;
+ }
+ return html`${this._moreInfoType
+ ? dynamicElement(this._moreInfoType, {
+ hass: this.hass,
+ stateObj: this._groupDomainStateObj,
+ })
+ : ""}
+ ${this.stateObj.attributes.entity_id.map((entity_id) => {
+ const state = this.hass!.states[entity_id];
+ if (!state) {
+ return "";
+ }
+ return html`
+
+ `;
+ })}`;
+ }
+
+ static get styles(): CSSResult {
+ return css`
+ state-card-content {
+ display: block;
+ margin-top: 8px;
+ }
+ `;
+ }
+}
+
+customElements.define("more-info-group", MoreInfoGroup);
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "more-info-group": MoreInfoGroup;
+ }
+}
diff --git a/src/dialogs/more-info/state_more_info_control.ts b/src/dialogs/more-info/state_more_info_control.ts
index c2b97d9c59..6f8cf904ab 100644
--- a/src/dialogs/more-info/state_more_info_control.ts
+++ b/src/dialogs/more-info/state_more_info_control.ts
@@ -32,6 +32,10 @@ const LAZY_LOADED_MORE_INFO_CONTROL = {
export const stateMoreInfoType = (stateObj: HassEntity): string => {
const domain = computeStateDomain(stateObj);
+ return domainMoreInfoType(domain);
+};
+
+export const domainMoreInfoType = (domain: string): string => {
if (DOMAINS_WITH_MORE_INFO.includes(domain)) {
return domain;
}