diff --git a/src/common/const.ts b/src/common/const.ts
index c7b2ac917f..8ed86c0614 100644
--- a/src/common/const.ts
+++ b/src/common/const.ts
@@ -226,6 +226,7 @@ export const DOMAINS_INPUT_ROW = [
"select",
"switch",
"text",
+ "time",
"vacuum",
];
diff --git a/src/common/entity/compute_state_display.ts b/src/common/entity/compute_state_display.ts
index e07f19fc20..662b58a541 100644
--- a/src/common/entity/compute_state_display.ts
+++ b/src/common/entity/compute_state_display.ts
@@ -117,7 +117,7 @@ export const computeStateDisplayFromEntityAttributes = (
const domain = computeDomain(entityId);
- if (domain === "input_datetime") {
+ if (domain === "input_datetime" || domain === "time") {
if (state !== undefined) {
// If trying to display an explicit state, need to parse the explicit state to `Date` then format.
// Attributes aren't available, we have to use `state`.
diff --git a/src/data/time.ts b/src/data/time.ts
new file mode 100644
index 0000000000..c2e9310633
--- /dev/null
+++ b/src/data/time.ts
@@ -0,0 +1,10 @@
+import { HomeAssistant } from "../types";
+
+export const setTimeValue = (
+ hass: HomeAssistant,
+ entityId: string,
+ time: string | undefined = undefined
+) => {
+ const param = { entity_id: entityId, time: time };
+ hass.callService(entityId.split(".", 1)[0], "set_value", param);
+};
diff --git a/src/panels/lovelace/create-element/create-row-element.ts b/src/panels/lovelace/create-element/create-row-element.ts
index 71f8a2359e..6852092e42 100644
--- a/src/panels/lovelace/create-element/create-row-element.ts
+++ b/src/panels/lovelace/create-element/create-row-element.ts
@@ -42,6 +42,7 @@ const LAZY_LOAD_TYPES = {
"number-entity": () => import("../entity-rows/hui-number-entity-row"),
"select-entity": () => import("../entity-rows/hui-select-entity-row"),
"text-entity": () => import("../entity-rows/hui-text-entity-row"),
+ "time-entity": () => import("../entity-rows/hui-time-entity-row"),
"timer-entity": () => import("../entity-rows/hui-timer-entity-row"),
conditional: () => import("../special-rows/hui-conditional-row"),
"weather-entity": () => import("../entity-rows/hui-weather-entity-row"),
@@ -80,6 +81,7 @@ const DOMAIN_TO_ELEMENT_TYPE = {
siren: "toggle",
switch: "toggle",
text: "text",
+ time: "time",
timer: "timer",
vacuum: "toggle",
// Temporary. Once climate is rewritten,
diff --git a/src/panels/lovelace/entity-rows/hui-time-entity-row.ts b/src/panels/lovelace/entity-rows/hui-time-entity-row.ts
new file mode 100644
index 0000000000..1efee0fee9
--- /dev/null
+++ b/src/panels/lovelace/entity-rows/hui-time-entity-row.ts
@@ -0,0 +1,95 @@
+import {
+ css,
+ CSSResultGroup,
+ html,
+ LitElement,
+ nothing,
+ PropertyValues,
+ TemplateResult,
+} from "lit";
+import { customElement, property, state } from "lit/decorators";
+import "../../../components/ha-date-input";
+import { isUnavailableState } from "../../../data/entity";
+import { setTimeValue } from "../../../data/time";
+import type { HomeAssistant } from "../../../types";
+import { hasConfigOrEntityChanged } from "../common/has-changed";
+import "../components/hui-generic-entity-row";
+import { createEntityNotFoundWarning } from "../components/hui-warning";
+import type { EntityConfig, LovelaceRow } from "./types";
+import "../../../components/ha-time-input";
+
+@customElement("hui-time-entity-row")
+class HuiTimeEntityRow extends LitElement implements LovelaceRow {
+ @property({ attribute: false }) public hass?: HomeAssistant;
+
+ @state() private _config?: EntityConfig;
+
+ public setConfig(config: EntityConfig): void {
+ if (!config) {
+ throw new Error("Invalid configuration");
+ }
+ this._config = config;
+ }
+
+ protected shouldUpdate(changedProps: PropertyValues): boolean {
+ return hasConfigOrEntityChanged(this, changedProps);
+ }
+
+ protected render(): TemplateResult | typeof nothing {
+ if (!this._config || !this.hass) {
+ return nothing;
+ }
+
+ const stateObj = this.hass.states[this._config.entity];
+
+ if (!stateObj) {
+ return html`
+
+ ${createEntityNotFoundWarning(this.hass, this._config.entity)}
+
+ `;
+ }
+
+ return html`
+
+
+
+ `;
+ }
+
+ private _stopEventPropagation(ev: Event): void {
+ ev.stopPropagation();
+ }
+
+ private _timeChanged(ev: CustomEvent<{ value: string }>): void {
+ const stateObj = this.hass!.states[this._config!.entity];
+ setTimeValue(this.hass!, stateObj.entity_id, ev.detail.value);
+ }
+
+ static get styles(): CSSResultGroup {
+ return css`
+ ha-date-input + ha-time-input {
+ margin-left: 4px;
+ margin-inline-start: 4px;
+ margin-inline-end: initial;
+ direction: var(--direction);
+ }
+ `;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "hui-time-entity-row": HuiTimeEntityRow;
+ }
+}