From 6f6ba71e61a2b97f603684fe38e272e9e74228d7 Mon Sep 17 00:00:00 2001
From: Simon Lamon <32477463+silamon@users.noreply.github.com>
Date: Wed, 11 Mar 2026 10:22:44 +0100
Subject: [PATCH] Redesign gauge card (#29981)
* Redesign gauge card
* Fix calculation
* New design, code needs optimization (ai)
---
gallery/src/pages/lovelace/gauge-card.ts | 13 ++
src/components/ha-gauge.ts | 230 ++++++++++++--------
src/panels/lovelace/cards/hui-gauge-card.ts | 2 -
3 files changed, 147 insertions(+), 98 deletions(-)
diff --git a/gallery/src/pages/lovelace/gauge-card.ts b/gallery/src/pages/lovelace/gauge-card.ts
index c9989692cc..c79a3def95 100644
--- a/gallery/src/pages/lovelace/gauge-card.ts
+++ b/gallery/src/pages/lovelace/gauge-card.ts
@@ -54,6 +54,19 @@ const CONFIGS = [
needle: true
`,
},
+ {
+ heading: "Rendering needle and severity levels",
+ config: `
+- type: gauge
+ entity: sensor.brightness_high
+ name: Brightness High
+ needle: true
+ severity:
+ red: 75
+ green: 0
+ yellow: 50
+ `,
+ },
{
heading: "Setting severity levels",
config: `
diff --git a/src/components/ha-gauge.ts b/src/components/ha-gauge.ts
index 55a00def00..a12552db8c 100644
--- a/src/components/ha-gauge.ts
+++ b/src/components/ha-gauge.ts
@@ -44,16 +44,16 @@ export class HaGauge extends LitElement {
@state() private _updated = false;
- @state() private _segment_label? = "";
+ @state() private _segment_label?: string = "";
protected firstUpdated(changedProperties: PropertyValues) {
super.firstUpdated(changedProperties);
- // Wait for the first render for the initial animation to work
afterNextRender(() => {
this._updated = true;
- this._angle = getAngle(this.value, this.min, this.max);
+ if (this.needle) {
+ this._angle = getAngle(this.value, this.min, this.max);
+ }
this._segment_label = this._getSegmentLabel();
- this._rescaleSvg();
});
}
@@ -70,70 +70,121 @@ export class HaGauge extends LitElement {
}
this._angle = getAngle(this.value, this.min, this.max);
this._segment_label = this._getSegmentLabel();
- this._rescaleSvg();
}
protected render() {
+ const arcRadius = 40;
+ const arcLength = Math.PI * arcRadius;
+ const valueAngle = getAngle(this.value, this.min, this.max);
+ const strokeOffset = arcLength * (1 - valueAngle / 180);
+
return svg`
-
- `;
- }
-
- private _rescaleSvg() {
- // Set the viewbox of the SVG containing the value to perfectly
- // fit the text
- // That way it will auto-scale correctly
- const svgRoot = this.shadowRoot!.querySelector(".text")!;
- const box = svgRoot.querySelector("text")!.getBBox()!;
- svgRoot.setAttribute(
- "viewBox",
- `${box.x} ${box!.y} ${box.width} ${box.height}`
- );
+
+ `;
}
private _getSegmentLabel() {
if (this.levels) {
- this.levels.sort((a, b) => a.level - b.level);
+ [...this.levels].sort((a, b) => a.level - b.level);
for (let i = this.levels.length - 1; i >= 0; i--) {
if (this.value >= this.levels[i].level) {
return this.levels[i].label;
@@ -178,40 +218,38 @@ export class HaGauge extends LitElement {
:host {
position: relative;
}
- .dial {
+
+ .levels-base {
fill: none;
stroke: var(--primary-background-color);
- stroke-width: 15;
- }
- .value {
- fill: none;
- stroke-width: 15;
- stroke: var(--gauge-color);
- transition: all 1s ease 0s;
- }
- .needle {
- fill: var(--primary-text-color);
- transition: all 1s ease 0s;
+ stroke-width: 10;
+ stroke-linecap: round;
}
+
.level {
fill: none;
- stroke-width: 15;
+ stroke-width: 10;
+ stroke-linecap: butt;
}
- .gauge {
- display: block;
+
+ .value {
+ fill: none;
+ stroke-width: 10;
+ stroke: var(--gauge-color);
+ stroke-linecap: round;
+ transition: all 1s ease 0s;
}
- .text {
- position: absolute;
- max-height: 40%;
- max-width: 55%;
- left: 50%;
- bottom: -6%;
- transform: translate(-50%, 0%);
+
+ .needle {
+ stroke: var(--primary-text-color);
+ stroke-width: 2;
+ stroke-linecap: round;
+ transform-origin: 0 0;
+ transition: all 1s ease 0s;
}
+
.value-text {
- font-size: 50px;
fill: var(--primary-text-color);
- text-anchor: middle;
direction: ltr;
}
`;
diff --git a/src/panels/lovelace/cards/hui-gauge-card.ts b/src/panels/lovelace/cards/hui-gauge-card.ts
index 28b8ee9368..e871af677f 100644
--- a/src/panels/lovelace/cards/hui-gauge-card.ts
+++ b/src/panels/lovelace/cards/hui-gauge-card.ts
@@ -303,7 +303,6 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
ha-gauge {
width: 100%;
- max-width: 250px;
}
.name {
@@ -312,7 +311,6 @@ class HuiGaugeCard extends LitElement implements LovelaceCard {
color: var(--primary-text-color);
width: 100%;
font-size: var(--ha-font-size-m);
- margin-top: 8px;
}
`;
}