yeah that’s the solution. Many Thanks
I ate hours there, I don’t understand enough javascript, I would never have thought of that
return variables.state === 'on' ? '45% -20% 0 0' : ' 8% -20% 0 0'
Thank you Thank you
yeah that’s the solution. Many Thanks
I ate hours there, I don’t understand enough javascript, I would never have thought of that
return variables.state === 'on' ? '45% -20% 0 0' : ' 8% -20% 0 0'
Thank you Thank you
of course, but its not animated only with color when the state is ON, its my Made in Shade
this is my “disgraced icon” it’s a bit ugly and deserves some love again when i have time
icon_pool:
styles:
custom_fields:
icon:
- width: 72%
custom_fields:
icon: >
[[[
let color;
if (variables.state === 'on' && variables.timeout < 2000) {
color = 'var(--primary-color)';
}
if (variables.state === 'off' && variables.timeout < 2000) {
color = '#a0a0a0';
}
if (variables.state === 'on' && variables.timeout > 2000) {
color = 'var(--primary-color)';
}
if (variables.state === 'off' && variables.timeout > 2000) {
color = '#a0a0a0';
}
let state = variables.state ? 'on' : null;
return `
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 480 480" style="enable-background:new 0 0 480 480;" xml:space="preserve">
<path class="${state}" fill="${color}" d="M447.216,504.163h-64.784c-11.542,0-20.898-9.356-20.898-20.898V326.588h106.58v156.677
C468.114,494.807,458.758,504.163,447.216,504.163z"/>
<polygon fill="${color}" points="409.078,415.115 336.98,415.115 336.98,381.678 388.18,381.678 "/>
<rect x="190.694" y="33.959" fill="${color}" width="73.143" height="125.388"/>
<polygon fill="${color}" points="91.429,504.163 60.082,504.163 60.082,478.041 101.878,478.041 "/>
<polygon fill="${color}" points="300.408,504.163 269.061,504.163 258.612,478.041 300.408,478.041 "/>
<path class="${state}" fill="${color}" d="M339.592,232.49H20.898c-7.214,0-13.061,5.847-13.061,13.061l0,0
c0,7.214,5.847,13.061,13.061,13.061h318.694c7.214,0,13.061-5.847,13.061-13.061l0,0
C352.653,238.337,346.806,232.49,339.592,232.49z"/>
<path class="${state}" fill="${color}" d="M316.082,478.041H44.408c-11.542,0-20.898-9.356-20.898-20.898V258.612H336.98v198.531
C336.98,468.685,327.624,478.041,316.082,478.041z"/>
<path class="${state}" fill="${color}" d="M336.98,455.053v2.09c0,11.546-9.352,20.898-20.898,20.898H44.408
c-11.546,0-20.898-9.352-20.898-20.898v-2.09H336.98z"/>
<path class="${state}" fill="${color}" d="M125.461,258.612v219.429H44.408c-11.546,0-20.898-9.352-20.898-20.898V258.612H125.461z"/>
<path class="${state}" fill="${color}" d="M316.082,159.347H44.408c-11.542,0-20.898,9.356-20.898,20.898v52.245H336.98v-52.245
C336.98,168.703,327.624,159.347,316.082,159.347z"/>
<circle style="fill:#FFFFFF;" cx="227.265" cy="326.531" r="20.898"/>
<circle style="fill:#FFFFFF;" cx="227.265" cy="410.122" r="20.898"/>
<rect x="175.02" y="7.837" fill="${color}" width="104.49" height="26.122"/>
<path class="${state}" d="M423.217,422.952l-30.694-49.11h-47.707v-108.08c8.999-2.329,15.673-10.494,15.673-20.21c0-5.583-2.173-10.831-6.119-14.778
c-2.682-2.682-5.973-4.522-9.555-5.441v-45.087c0-15.845-12.891-28.735-28.735-28.735h-44.408v-45.704H256v45.704h-20.898v-43.637
l82.934-49.96l-8.088-13.426l-38.275,23.057V41.796h15.673V0H167.184v41.796h15.673V151.51H44.408
c-15.844,0-28.735,12.89-28.735,28.735v45.096C6.675,227.67,0,235.835,0,245.551c0,5.583,2.173,10.831,6.119,14.778
c2.682,2.682,5.973,4.522,9.555,5.441v191.373c0,15.845,12.891,28.735,28.735,28.735h7.837V512h44.49l10.449-26.122h146.123
L263.755,512h44.49v-26.122h7.837c15.844,0,28.735-12.89,28.735-28.735v-34.191H423.217z M383.836,389.515l11.102,17.763h-50.122
v-17.763H383.836z M316.082,167.184c7.203,0,13.061,5.859,13.061,13.061v44.408h-80.98v15.673h91.429
c1.397,0,2.709,0.543,3.695,1.529c0.986,0.986,1.53,2.299,1.53,3.696c0,2.881-2.344,5.224-5.224,5.224h-91.429v15.673h80.98v180.767
H133.298V266.449h86.131v32.442c-12.046,3.42-20.898,14.512-20.898,27.64c0,15.845,12.891,28.735,28.735,28.735
S256,342.375,256,326.531c0-13.128-8.852-24.219-20.898-27.64V167.184H316.082z M31.347,266.449h86.277v180.767H31.347V266.449z
M227.265,313.469c7.202,0,13.061,5.859,13.061,13.061s-5.859,13.061-13.061,13.061c-7.202,0-13.061-5.859-13.061-13.061
S220.063,313.469,227.265,313.469z M182.857,15.673h88.816v10.449h-88.816V15.673z M198.531,41.796H256v35.19l-36.571,22.031v52.494
h-20.898V41.796z M44.408,167.184h175.02v57.469H31.347v-44.408C31.347,173.042,37.206,167.184,44.408,167.184z M20.898,240.327
h198.531v10.449H20.898c-1.397,0-2.709-0.543-3.695-1.529c-0.987-0.986-1.53-2.299-1.53-3.696
C15.673,242.67,18.017,240.327,20.898,240.327z M86.123,496.327H67.918v-10.449h22.384L86.123,496.327z M292.571,496.327h-18.204
l-4.18-10.449h22.384V496.327z M316.082,470.204H44.408c-5.138,0-9.58-2.989-11.711-7.314h295.096
C325.661,467.215,321.219,470.204,316.082,470.204z"/>
<path class="${state}" d="M227.265,381.388c-15.844,0-28.735,12.89-28.735,28.735c0,15.845,12.891,28.735,28.735,28.735S256,425.967,256,410.122
C256,394.278,243.109,381.388,227.265,381.388z M227.265,423.184c-7.202,0-13.061-5.859-13.061-13.061s5.859-13.061,13.061-13.061
c7.202,0,13.061,5.859,13.061,13.061S234.468,423.184,227.265,423.184z"/>
<path class="${state}" d="M512,365.772h-36.049v-47.015H353.698v42.026h15.673V334.43h90.906v31.342v97.118v20.376
c0,7.202-5.859,13.061-13.061,13.061h-64.784c-7.202,0-13.061-5.859-13.061-13.061v-47.25h-15.673v47.25
c0,15.845,12.891,28.735,28.735,28.735h64.784c15.844,0,28.735-12.89,28.735-28.735V462.89H512V365.772z M496.327,447.216h-20.376
v-65.771h20.376V447.216z"/>
<style>
@keyframes on {
0% {
transform: scale(0.85);
}
20% {
transform: scale(1.1);
}
40% {
transform: scale(0.95);
}
60% {
transform: scale(1.03);
}
80% {
transform: scale(0.97);
}
100% {
transform: scale(1);
}
}
.on {
animation: on 0.8s;
transform-origin: center;
}
</style>
</svg>
`;
]]]
what is in your kids_climate then ?
I no longer use this approach for my ac so I can not provide the code, but it was the same AC popup that was provided by @Mattias_Persson with an added input select input to set the fan speed.
happy to help,
there might have been a way to get this working with the “low code” approach that you had taken, but as a developer I went straight to the code way and didn’t look into the low code approach.
this is what’s known as a ternary statement. its just a fancy inline if statement, you can read more in the javascript documentation.
with the same code, why is the result on my home assistant like this, please help
HI, maybe anyone can help, because obviously I´m to dumb to change the aspect ratio to fit it to a normal Full-HD screen.
I´ve already changed the size of the background.png and took a fresh browser to ensure the cache is clean.
The HTML-Tag seems to have the right size:
But the root element not
@tommysusilo, welcome.
@Giblet has given a fantastic response below mine
This is a more recent graph card, the post you replied to is over a year old, lots of updates between now and then. A different take on designing a Lovelace UI - #4263 by karma
if you have any issues feel free to reach out.
@kamilk, I can’t tell what you are asking.
if you would like the layout to work on a larger screen then this is my solution
views:
- type: custom:grid-layout
path: 0
layout:
#default
grid-gap: var(--custom-layout-card-padding)
grid-template-columns: 0.7fr repeat(3, 1fr) 0.7fr
grid-template-rows: 0 repeat(2, fit-content(100%)) 0fr
grid-template-areas: |
"sidebar . . . ."
"sidebar Living_Room Rooms Climate footer"
"sidebar media Home People footer"
"sidebar . . . ."
mediaquery:
#phone
'(max-width: 800px)':
grid-gap: calc(var(--custom-layout-card-padding) * 1.7)
grid-template-columns: 0 repeat(2, 1fr) 0
grid-template-rows: 0 repeat(5, fit-content(100%)) 0fr
grid-template-areas: |
". . . ."
". sidebar sidebar ."
". Living_Room Climate ."
". Rooms Home ."
". media People ."
". footer footer ."
". . . ."
#portrait
'(max-width: 1200px)':
grid-gap: var(--custom-layout-card-padding)
grid-template-columns: repeat(3, 1fr) 0
grid-template-rows: 0 repeat(3, fit-content(100%)) 0fr
grid-template-areas: |
"sidebar . . ."
"sidebar Living_Room Climate ."
"sidebar Rooms Home ."
"sidebar media People ."
"sidebar footer footer ."
"sidebar . . ."
'(max-width: 1440px)':
grid-gap: var(--custom-layout-card-padding)
grid-template-columns: repeat(4, 1fr) 0
grid-template-rows: 0 repeat(2, fit-content(100%)) 0fr
grid-template-areas: |
"sidebar . . . ."
"sidebar Living_Room Rooms Climate ."
"sidebar media Home People ."
"sidebar footer footer footer ."
theme: tablet
and I have added this to the team to stack the footer icons on larger screens
#################################################
# #
# FOOTER #
# #
#################################################
grid-layout$hui-horizontal-stack-card:
$: |
#root {
flex-wrap: wrap;
justify-content: center;
overflow: visible;
margin-top: -1.95vw !important;
padding-bottom: 2.5em;
}
@media screen and (min-width: 1200px) {
#root {
flex-wrap: nowrap;
justify-content: space-between;
margin-top: -1.6vh;
padding-bottom: 0;
}
}
@media screen and (min-width: 1441px) {
#root {
flex-direction: column;
}
}
/* phone */
@media screen and (max-width: 800px) {
#root {
padding-top: 4vw !important;
}
}
posting YAML helps, the browser debug screenshots are fantastic but you should provide more context next time
I have created a more generalized “environment” card.
So first the environment.yaml (which should be in the button_card_templates directory)
environment:
template:
- base
- circle
state_display: >
[[[ return ' '; ]]]
tap_action: !include /config/popup/environment.yaml
double_tap_action: !include /config/popup/environment.yaml
hold_action:
action: none
show_state: true
variables:
circle_input: >
[[[
if (entity) {
return 100;
}
]]]
text_input: >
[[[
if (entity) {
return entity.attributes.temperature === undefined ? null : Math.round(entity.attributes.temperature);
}
]]]
circle_input_unit: '°C'
custom_fields:
graph:
card:
type: sensor
entity: >
[[[ return entity.entity_id; ]]]
graph: line
card_mod:
style: |
.header, .value, .measurement {
display: none !important;
}
:host {
--ha-card-border-width: 0;
}
push_graph: >
[[[
setTimeout(() => {
let elt = this.shadowRoot,
card = elt.getElementById('card'),
container = elt.getElementById('container'),
graph = elt.getElementById('graph');
if (elt && card && container && graph) {
card.insertBefore(graph, container);
}
}, 0);
return null;
]]]
styles:
custom_fields:
graph:
- position: absolute
- width: 100%
- height: 100%
- clip-path: inset(0 round var(--button-card-border-radius))
- left: 0
- bottom: 0
icon:
- width: 69%
- fill: "#9da0a2"
Then in the lovelace.yaml you already use, you should “forward” the correct variables to this environment card
In my case this looks something like:
- type: custom:button-card
entity: sensor.es_bathroom_temperature
name: Badkamer
custom_fields:
graph:
card:
entities:
- sensor.es_bathroom_temperature
template:
- environment
- icon_temp
variables:
popup_name: Badkamer
Then you might also want the popup environment.yaml card.
Keep in mind this is pretty specific to my setup, because it uses entity_id.replace to get the correct humidity sensor from the forwarded temperature sensor…
Meaning… In the lovelace.yaml I only have to forward the temperature sensor, and in the popup yaml it will “translate” it to the accompanying humidity sensor, which might only work with my specific environment sensor.
Anyhow:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
title: >
[[[ return variables.popup_name ]]]
card_mod:
style:
#popup header
.:
content:
type: vertical-stack
cards:
- type: entities
card_mod:
class: content
style: |
#states {
padding-top: 0.5em;
padding-bottom: 0em;
}
entities:
- name: Temperatuur
entity: >
[[[
return entity.entity_id;
]]]
- name: Luchtvochtigheid
entity: >
[[[
return entity.entity_id.replace("temperature", "humidity")
]]]
- name: Luchtdruk
entity: >
[[[
return entity.entity_id.replace("temperature", "pressure")
]]]
footer:
type: custom:apexcharts-card
layout: minimal
graph_span: 3h
locale: en
apex_config:
chart:
fontFamily: var(--primary-font-family)
height: 180px
tooltip:
style:
fontSize: 14px
x:
show: true
format: HH:mm
xaxis:
crosshairs:
show: false
legend:
fontSize: 14px
fontWeight: 400
height: 60
offsetY: 20
itemMargin:
horizontal: 25
vertical: 5
formatter: |
EVAL: (seriesName, opts) => {
var arr = opts.w.globals.series[opts.seriesIndex],
value = arr[arr.length - 1];
return value == null
? seriesName : "" ;
}
markers:
width: 26
height: 23
customHTML:
- 'EVAL:() => {return `<ha-icon icon="mdi:water-percent" style="--mdc-icon-size: 23px;"></ha-icon>`}'
- 'EVAL:() => {return `<ha-icon icon="mdi:thermometer" style="--mdc-icon-size: 23px;"></ha-icon>`}'
fillColors:
- none
- none
fill:
type: gradient
gradient:
type: vertical
opacityFrom: 0.8
opacityTo: 0
stops:
- 0
- 99
- 100
stroke:
width: 3
all_series_config:
type: area
fill_raw: last
series:
- name: Humidity
color: '#385581'
entity: >
[[[
return entity.entity_id.replace("temperature", "humidity");
]]]
- name: Temperature
color: green
entity: >
[[[
return entity.entity_id;
]]]
I suppose that should be all…
HI Giblet,
thanks for the code So far everything works, but it doesn’t show the circles.
any idea why?
Ahh I probably forgot to mention there is also some change in the circle.yaml button_card_template file:
Again: it’s straying quite far from the original by Mathias
This might even start you on a rabbit hole, where you are going to need to change other button_card_templates / lovelace.yaml to make sure the circles show for them…
circle:
styles:
card:
- --c-stroke-color-on: '#b0b0b0'
- --c-stroke-color-off: '#313638'
- --c-fill-color-on: none
- --c-fill-color-off: rgba(255,255,255,0.04)
- --c-stroke-width-on: 2.3
- --c-stroke-width-off: 1.5
- --c-stroke-width-dragging: 4
- --c-font-color-off: '#97989c'
- --c-font-color-on: '#25292a'
- --c-font-size: 14px
- --c-unit-font-size: 10.5px
- --c-font-weight: 700
- --c-letter-spacing: -0.02rem
custom_fields:
circle:
- display: initial
- width: 88%
- margin: -3% 2% 0 0
- justify-self: end
- opacity: 1
custom_fields:
circle: >
[[[
if (entity) {
let r = 22.1,
c = r * 2 * Math.PI,
tspan = '<tspan dx=".2" dy="-.4">',
domain = entity.entity_id.split('.')[0],
state = variables.state_on,
input = variables.circle_input || ' ',
text = variables.text_input || ' ',
unit = variables.circle_input_unit || ' ';
if(text === ' ') {
text = variables.circle_input
}
/* * * * * * * * * * * * * * * * * *
* *
* CIRCLE *
* *
* * * * * * * * * * * * * * * * * */
let circle = (state, input, unit, text) => {
return `
<svg viewBox="0 0 50 50">
<style>
circle {
transform: rotate(-90deg);
transform-origin: 50% 50%;
stroke-dasharray: ${c};
stroke-dashoffset: ${typeof input === 'number' && c - input / 100 * c};
stroke-width: ${state ? 'var(--c-stroke-width-on)' : 'var(--c-stroke-width-off)'};
stroke: ${text !== '0d' && state ? 'var(--c-stroke-color-on)' : 'var(--c-stroke-color-off)'};
fill: ${state ? 'var(--c-fill-color-on)' : 'var(--c-fill-color-off)'};
}
text {
font-size: var(--c-font-size);
font-weight: var(--c-font-weight);
letter-spacing: var(--c-letter-spacing);
fill: ${text === '0d' ? 'var(--c-font-color-on)' : 'var(--c-font-color-off)'};
}
tspan {
font-size: var(--c-unit-font-size);
}
#circle_value, tspan {
text-anchor: middle;
dominant-baseline: central;
}
</style>
<circle id="circle_stroke" cx="25" cy="25" r="${r}" />
<text id="circle_value" x="51%" y="50%">${text}${tspan}${unit}</tspan></text>
</svg>
${domain === 'light' && `
<input id="circle_slider" type="range" min="0" max="100" value="${input}">
`}
`;
}
/* * * * * * * * * * * * * * * * * *
* *
* LIGHT *
* *
* * * * * * * * * * * * * * * * * */
if (domain === 'light' && state) {
// wait 0ms for shadow dom
setTimeout(() => {
// then get elements
let elt = this.shadowRoot,
circle_slider = elt.getElementById('circle_slider'),
circle_value = elt.getElementById('circle_value'),
circle_stroke = elt.getElementById('circle_stroke');
// approximate position of thumb relative to circle
circle_slider.style.top = `${(circle_slider.value - 50) / 1.66 - 1}%`;
// debug position
let debug = false;
if (debug) circle_slider.style.opacity = 0.3;
// pass each event to handler
['click', 'input', 'mousedown', 'mouseup', 'touchstart', 'touchend'].forEach((event) => {
circle_slider.addEventListener(event, handler, { passive: true })
});
function handler(event) {
// "this" refers to slider
if (event.target === this) {
// bypass button-card tap_action
event.stopPropagation();
// update circle_value
circle_value.innerHTML = `${this.value}${tspan}${unit}</tspan>`;
// update stroke
circle_stroke.style.strokeDashoffset = c - this.value / 100 * c;
circle_stroke.style.strokeWidth = 'var(--c-stroke-width-dragging)';
// set cursor while dragging
if (event.type === 'mousedown' || event.type === 'input') {
this.style.cursor = 'grabbing';
} else {
this.style.cursor = 'grab';
}
// reset stroke width if value doesn't change
if (input == this.value && (event.type === 'click' || event.type === 'touchend'))
circle_stroke.style.strokeWidth = 'var(--c-stroke-width)';
// on release
if (event.type === 'mouseup' || event.type === 'touchend') {
// display loader if brightness is 0
if (circle_slider.value == 0 && elt.getElementById('loader')) {
elt.getElementById('loader').style.display = 'initial';
elt.getElementById('circle').style.display = 'none';
}
// set brightness
hass.callService('light', 'turn_on', {
entity_id: entity.entity_id,
brightness_pct: this.value
});
}
}
}
}, 0);
return circle(state, input, unit, text);
}
/* * * * * * * * * * * * * * * * * *
* *
* PERSON *
* *
* * * * * * * * * * * * * * * * * */
else if (domain === 'person') {
let time = c => {
let s = (c/1e3),
m = (c/6e4),
h = (c/36e5),
d = (c/864e5);
return s < 60
? parseInt(s) + 's'
: m < 60 ? parseInt(m) + 'm'
: h < 24 ? parseInt(h) + 'h'
: parseInt(d) + 'd';
};
let input = states[variables.retain] === undefined || states[variables.retain].state === 'unavailable'
? time(Date.now() - Date.parse(entity.last_changed))
: time(Date.now() - Date.parse(states[variables.retain].state)),
unit = ' ',
text = input;
return circle(state, input, unit, text);
}
/* * * * * * * * * * * * * * * * * *
* *
* LAUNDRY *
* *
* * * * * * * * * * * * * * * * * */
else if (domain === 'sensor' && variables.time_input ) {
let time = c => {
let s = (c/1e3),
m = (c/6e4),
h = (c/36e5),
d = (c/864e5);
return s < 60
? parseInt(s) + 's'
: m < 60 ? parseInt(m) + 'm'
: h < 24 ? parseInt(h) + 'h'
: parseInt(d) + 'd';
};
let time_left = time(Date.parse(variables.time_input) - Date.now()),
unit = ' ',
text = time_left;
state = 'on'
if (variables.time_input != 'False') {
if ( Date.parse(variables.time_input) > Date.now()){
return circle(state, input, unit, text);
}
}
}
/* * * * * * * * * * * * * * * * * *
* *
* CLIMATE *
* *
* * * * * * * * * * * * * * * * * */
else if (domain === 'climate') {
return circle(state, input, unit, text);
}
/* * * * * * * * * * * * * * * * * *
* *
* Temperature *
* *
* * * * * * * * * * * * * * * * * */
else if (domain === 'sensor') {
return circle(state, input, unit, text);
}
/* * * * * * * * * * * * * * * * * *
* *
* OTHER *
* *
* * * * * * * * * * * * * * * * * */
else if (variables.state_on) {
return circle(state, input, unit, text);
}
}
]]]
I like your font style, size, and weight. Could you tell me what you are using and where to change it?
hi, keep in mind this comment that you replied to use old so my settings have changed between now and then. this is what that card looks like now.
This is all the locations that I think are needed to update the font and font size.
main font size is set in the themes file I have the following settings
sidebar-font-size: 1.42vw
button-card-font-size: 1.35vw
footer-card-font-size: 1.22vw
and the font family itself is set in themes file mine is
primary-font-family: SF Pro Text, Roboto, system-ui
lastly the scaling for screen sizes is in button_card_templates/extra_styles.yaml
/* magnification */
:host {
--card-portrait: 1.4;
--card-phone: 2.271;
}
and
#name, #state {
font-size: calc(var(--button-card-font-size)*0.85);
font-weight: var(--button-card-font-weight);
letter-spacing: var(--button-card-letter-spacing);
}
/* tablet */
@media screen and (max-width: 1400px) {
#name, #state {
font-size: var(--button-card-font-size);
}
}
/* portrait */
@media screen and (max-width: 1200px) {
#name, #state {
font-size: calc(var(--button-card-font-size) * var(--card-portrait));
}
}
/* phone */
@media screen and (max-width: 800px) {
#name, #state {
font-size: calc(var(--button-card-font-size) * var(--card-phone));
}
}
Thank you!
First of all thanks for all the work and inspiration!
I’m running in a problem that whenever i change something in the layout, sidebar or custom buttons there seems to be a border around the custom button and now the sidebar.
Any idea how to fix this? cant seem to find out where this border comes from.
Here is my code, used elements and idea’s from this post but always i get the border-line…
- type: custom:vertical-stack-in-card
view_layout:
grid-area: sidebar
mode: vertical
cards:
- type: markdown
content: |
{% set attributes = states.sensor.template_sidebar.attributes | default %}
{% for template in attributes %}
{{ state_attr('sensor.template_sidebar', template) }}
{% endfor %}
- type: "custom:hui-element"
card_type: weather-forecast
entity: weather.thuis
show_forecast: false
- type: "custom:hui-element"
card_type: "custom:auto-entities"
card:
type: entities
filter:
include:
- entity_id: sensor.sauna_temperature
state: <30
- entity_id: sensor.anniversary_xyzs_birthday
state: <30
- entity_id: sensor.anniversary_first_day_of_summer
state: <30
- entity_id: sensor.anniversary_first_day_of_fall
state: <30
- entity_id: sensor.anniversary_first_day_of_spring
state: <30
- entity_id: sensor.anniversary_first_day_of_winter
state: <30
- entity_id: sensor.anniversary_our_anniversary
state: <30
- entity_id: sensor.anniversary_xyzss_birthday
state: <30
- entity_id: sensor.anniversary_halloween
state: <30
- entity_id: sensor.anniversary_christmas
state: <30
- entity_id: sensor.anniversary_xyzs_birthday
state: <30
- entity_id: sensor.anniversary_good_friday
state: <30
show_empty: false
sort:
method: state
numeric: true
- type: grid
view_layout:
grid-area: sidebar
columns: 4
cards:
- type: "custom:button-card"
color_type: blank-card
- type: button
icon: mdi:robot-vacuum
# tap_action:
# !include popup/sidebar_vacuum.yaml
- type: button
icon: mdi:cctv
# tap-action:
# !include popup/sidebar_cameras.yaml
- type: button
icon: mdi:tune-vertical
# tap-action:
# !include popup/sidebar_settings.yaml
- type: custom:button-card
entity: sensor.sauna_temperature
name: Sauna
# tap_action: toggle switch.sauna
state_display: >
[[[ return ' '; ]]]
template:
- base
- circle
- icon_climate
custom_fields:
icon: >
<ha-icon icon="mdi:radiator" style="color: #9da0a2;"></ha-icon>
circle: >
[[[
if (entity) {
return `
<svg viewBox="0 0 50 50">
<circle cx="25" cy="25" r="20.5" stroke="none" stroke-width="1.5" fill="rgba(255,255,255,0.04)" />
<text x="50%" y="54%" fill="#8d8e90" font-size="14" text-anchor="middle" alignment-baseline="middle" dominant-baseline="middle">${parseInt(entity.state)}<tspan font-size="10">°C</tspan></text>
</svg>
`;
}
]]]
graph:
card:
type: sensor
entity: >
[[[ return entity.entity_id; ]]]
graph: line
card_mod:
style: |
.header, .value, .measurement {
display: none !important;
}
push_graph: >
[[[
setTimeout(() => {
let elt = this.shadowRoot,
card = elt.getElementById('card'),
container = elt.getElementById('container'),
graph = elt.getElementById('graph');
if (elt && card && container && graph) {
card.insertBefore(graph, container);
}
}, 0);
return null;
]]]
styles:
custom_fields:
graph:
- position: absolute
- width: 100%
- height: 100%
- clip-path: inset(0 round var(--custom-button-card-border-radius))
- left: 0
- bottom: 0
EDIT:
Found a workaround / solution:
Added this line to themes.yaml
ha-card-border-width: 0
hey @Mattias_Persson,
I got my self an Apple TV, and went to implement the YouTube thumbnail, (when I looked it needed the video ID, or more info than I could get out of my TV at the time), however there looks to be an issue with GitHub - matt8707/youtube-watching: 📦 Containerized flask app using yt-dlp, I only get the thumbnail for the most resent short that I have watched not the most recent video. I think YouTube recently made a change to the history page to show shorts in a new section.
is this something I have done to myself?
would this be an easy fix?
is this a known issues?
Hi Henkseegers
Did you manage to get this to work properly. I’ve tried a couple of times but with no success. Reverting to the default HA lovelace view, I cast perfectly well, but this customized, no luck. Any pointers?
Can you give advice on how you got the buttons aligned to the bottom?
I have my sidebar like this, but would like the person badged/picture entity aligned to the bottom. Any advice?
#################################################
# #
# SIDEBAR #
# #
#################################################
- type: custom:layout-card
view_layout:
grid-area: sidebar
layout_type: grid
layout:
grid-template-columns: 5% 90% 5%
grid-template-rows: auto
grid-template-areas: |
"left center right"
cards:
- type: vertical-stack
view_layout:
grid-area: center
cards:
- type: custom:button-card
entity: sensor.template_sidebar
template: sidebar
- type: custom:simple-weather-card
entity: weather.thuis
name: ' '
custom:
- temp: sensor.wupws_temp
- precipitation: sensor.wupws_preciptotal
secondary_info:
- precipitation
card_mod:
style: |
ha-card {
color: red;
width: 250px !important;
--primary-text-color: #6a7377;
}
- type: custom:layout-card
layout_type: grid
layout:
grid-template-columns: 10% 40% 40% 10%
grid-template-rows: auto
grid-template-areas: |
"links tim mieke rechts"
cards:
- type: picture-entity
view_layout:
grid-area: tim
entity: person.tim
image: /local/timkleur2.png
tap_action:
!include popup/tim.yaml
show_name: false
show_state: false
state_filter:
"home": grayscale(30%)
"not_home": grayscale(90%)
style: |
ha-card {
transform: scale(0.6,0.6)
}
- type: picture-entity
view_layout:
grid-area: mieke
align-self: end
entity: person.mieke
image: /local/miekekleur2.png
show_name: false
show_state: false
tap_action:
!include popup/mieke.yaml
state_filter:
"home": grayscale(30%)
"not_home": grayscale(90%)
style: |
ha-card {
transform: scale(0.6,0.6)
}