Happy to share the code. I did make a slight formatting adjustment as the title for the Garage, at a higher temperature, slide off the card, so the label and temperature are now stacked. ChatGPT suggested that it could work on dynamic positioning, but I’m going to work with this thru the summare and make adjustments if needed,
The labels are actionable and will open a thermostat pop-up card.
ChatGPT is wrong…a lot. And you’re right. When it is wrong, you need to know enough to suggest an alternative approach to solve the problems.
entity: sensor.upstairs_current_temperature
tap_action:
action: none
show_name: false
show_icon: false
show_state: false
custom_fields:
title: Current Inside Temperatures
gradient: ""
bar: ""
temperature_ticks: |
[[[
const ticks = [];
for (let t = 65; t <= 80; t += 5) {
const left = ((t - 60) / (85 - 60)) * 100;
ticks.push(`<div style="
position: absolute;
top: 47%;
left: ${left}%;
height: 10%;
width: 0.5px;
background-color: white;
z-index: 2;
transform: translateX(-50%);
"></div>`);
}
return ticks.join('');
]]]
upstairs_marker: |
[[[
const temp = Math.round(states['sensor.upstairs_current_temperature'].state);
const mode = states['climate.upstairs'].state;
const color = mode === 'cool' ? '#00bfff' : mode === 'heat' ? '#ff4d4d' : 'white';
const left = ((temp - 60) / (85 - 60)) * 100;
return `
<span style="
position: absolute;
top: 28%;
pointer-events: auto;
touch-action: manipulation;
cursor: pointer;
left: ${left}%;
transform: translateX(-50%);
font-size: 24px;
color: ${color};
z-index: 3;"
onclick="event.stopPropagation(); location.hash='#upstairs'"
ontouchstart="event.stopPropagation(); location.hash='#upstairs'">
▼
</span>
`;
]]]
downstairs_marker: |
[[[
const temp = Math.round(states['sensor.downstairs_current_temperature'].state);
const mode = states['climate.downstairs'].state;
const color = mode === 'cool' ? '#00bfff' : mode === 'heat' ? '#ff4d4d' : 'white';
const left = ((temp - 60) / (85 - 60)) * 100;
return `
<span style="
position: absolute;
top: 55%;
pointer-events: auto;
touch-action: manipulation;
cursor: pointer;
left: ${left}%;
transform: translateX(-50%);
font-size: 24px;
color: ${color};
z-index: 3;"
onclick="event.stopPropagation(); location.hash='#downstairs'"
ontouchstart="event.stopPropagation(); location.hash='#downstairs'">
▲
</span>
`;
]]]
garage_marker: |
[[[
const temp = Math.round(states['sensor.a3_garage_temperature'].state);
const mode = states['climate.lounge'].state;
const color = mode === 'cool' ? '#00bfff' : mode === 'heat' ? '#ff4d4d' : 'white';
const left = ((temp - 60) / (85 - 60)) * 100;
return `
<span style="
position: absolute;
top: 55%;
pointer-events: auto;
touch-action: manipulation;
cursor: pointer;
left: ${left}%;
transform: translateX(-50%);
font-size: 24px;
color: ${color};
z-index: 3;"
onclick="event.stopPropagation(); location.hash='#lounge'"
ontouchstart="event.stopPropagation(); location.hash='#lounge'">
▲
</span>
`;
]]]
fixed_77_marker: "|← 77"
fixed_65_marker: 65 →|
upstairs_label: |
[[[
const temp = Math.round(states['sensor.upstairs_current_temperature'].state);
return `
<div style="
pointer-events: auto;
cursor: pointer;
padding: 4px 8px;
border-radius: 6px;"
onclick="event.stopPropagation(); location.hash='#upstairs'"
ontouchstart="event.stopPropagation(); location.hash='#upstairs'">
Upstairs: ${temp}°F
</div>
`;
]]]
downstairs_label: |
[[[
const temp = Math.round(states['sensor.downstairs_current_temperature'].state);
return `
<div style="text-align: center; pointer-events: auto; cursor: pointer;"
onclick="event.stopPropagation(); location.hash='#downstairs'"
ontouchstart="event.stopPropagation(); location.hash='#downstairs'">
<div style="padding: 2px 6px; border-radius: 6px;">Downstairs</div>
<div style="font-size: 12px; margin-top: 2px;">${temp}°F</div>
</div>
`;
]]]
garage_label: |
[[[
const temp = Math.round(states['sensor.a3_garage_temperature'].state);
return `
<div style="text-align: center; pointer-events: auto; cursor: pointer;"
onclick="event.stopPropagation(); location.hash='#lounge'"
ontouchstart="event.stopPropagation(); location.hash='#lounge'">
<div style="padding: 2px 6px; border-radius: 6px;">Garage</div>
<div style="font-size: 12px; margin-top: 2px;">${temp}°F</div>
</div>
`;
]]]
top_right: |
[[[
let cur = Math.round(parseFloat(states['sensor.home_realfeel_temperature'].state));
return 'Current: ' + cur + '°F';
]]]
styles:
card:
- background-color: transparent
- border-radius: 30px
- padding: 0
- height: 140px
- position: relative
- font-size: 14px
- color: white
- overflow: visible
- pointer-events: none
custom_fields:
title:
- position: absolute
- top: 0%
- left: 1px
- font-weight: bold
- font-size: 14px
- z-index: 2
top_right:
- position: absolute
- top: 0%
- right: 4px
- font-size: 14px
gradient:
- position: absolute
- top: 45%
- left: 0
- width: 100%
- height: 15%
- border-radius: 30px
- background: |
linear-gradient(to right,
#001f3f 11.5%,
#001f3f 23.1%,
#0074D9 35.9%,
#2ECC40 48.7%,
#FFDC00 61.5%,
#FF851B 74.4%,
#FF4136 87.2%,
#85144b 100%
)
- z-index: 0
bar:
- position: absolute
- top: 40%
- left: 0
- width: 100%
- height: 20%
- background-color: rgba(255, 255, 255, 0.0)
- border-radius: 30px
- z-index: 1
temperature_ticks:
- position: absolute
- top: 0
- left: 0
- width: 100%
- height: 100%
- z-index: 2
upstairs_label:
- position: absolute
- top: 28%
- font-size: 14px
- left: |
[[[
let temp = Math.round(parseFloat(states['sensor.upstairs_current_temperature'].state)) + 0.5;
return ((temp - 60) / (85 - 60) * 100) + '%';
]]]
- transform: translateX(0%)
- pointer-events: auto
downstairs_label:
- position: absolute
- top: 62%
- font-size: 14px
- left: |
[[[
let temp = Math.round(parseFloat(states['sensor.downstairs_current_temperature'].state)) - 0.7;
return ((temp - 60) / (85 - 60) * 100) + '%';
]]]
- transform: translateX(-100%)
- pointer-events: auto
garage_label:
- position: absolute
- top: 62%
- font-size: 14px
- left: |
[[[
let temp = Math.round(parseFloat(states['sensor.a3_garage_temperature'].state)) + 0.7;
return ((temp - 60) / (85 - 60) * 100) + '%';
]]]
- transform: translateX(0%)
- pointer-events: auto
fixed_77_marker:
- position: absolute
- top: 46.5%
- font-size: 12px
- color: black
- left: |
[[[ return ((77 - 60) / (85 - 60) * 100) + '%'; ]]]
- transform: translateX(-50%)
- z-index: 3
fixed_65_marker:
- position: absolute
- top: 46.5%
- font-size: 12px
- color: white
- left: |
[[[ return ((65 - 60) / (85 - 60) * 100 - 3) + '%'; ]]]
- transform: translateX(-50%)
- z-index: 3
I think it would be fairly easy to adapt the code - and no doubt, improve upon it.
