#Custom button card styling (border with SVG)

1 messages ยท Page 1 of 1 (latest)

woeful dome
#

lets use this thread ๐Ÿ™‚

#

so. why not use two path? and create 1 SVG for the background and 1 SVG for the colored border

#

so basically add a #background-path {
stroke: grey;
stroke-width: ${bar_thickness};
}

and use the "remaining" path of the earler created one?

#
<svg id="progress-bar" fill="none" stroke-linecap="round" viewBox="0 0 100 100">
          <path id="background-path" d="M50,0.2
                h0 a50,50 0 0 1 50,50 v0 a50,50 0 0 1 -50,50
                h0 a50,50 0 0 1 -50,-50 v0 a50,50 0 0 1 50,-50" />
          <path id="progress-path" d="M50,0.2
                h0 a50,50 0 0 1 50,50 v0 a50,50 0 0 1 -50,50
                h0 a50,50 0 0 1 -50,-50 v0 a50,50 0 0 1 50,-50" />
        </svg>
        <style>
          #background-path {
            stroke: grey;
            stroke-width: ${bar_thickness};
          }
          #progress-path {
            stroke: ${color};
            stroke-width: ${bar_thickness};
            stroke-dasharray: ${totalLength};
            stroke-dashoffset: ${progress};
            transition: stroke-dashoffset 1s linear;
          }
        </style>

open ridge
#

I was initialy thinking about that but the box-shadow seemed like a good fit. Might run into an issue with the z-index depending on how they're both drawing. (I assume if gray is drawn first then it will be on the bottom.)

woeful dome
open ridge
#

Seems like that was the way to go.

woeful dome
#

it worked, just copy pasted the SVG (the same) And didnt give it a path.. just let it act as a background

#

the problem now is this:

#

its not round anymore hehe

open ridge
#

I think it is because totalLength has to change because now there is an additional path that it has to draw.

woeful dome
#

I do get it to 100% nicely, but the border is not have rounded edges,, its to "thick" for its own good it seems like

#

I think my card styling is the issue..

#

it was the stroke-linecap tricking my brain

open ridge
#

I literally just figured that out...

woeful dome
#
<svg id="progress-bar" fill="none"  viewBox="0 0 100 100">
          <path id="background-path" d="M50,0.2
                h0 a50,50 0 0 1 50,50 v0 a50,50 0 0 1 -50,50
                h0 a50,50 0 0 1 -50,-50 v0 a50,50 0 0 1 50,-50" />
          <path id="progress-path"  d="M50,0.2
                h0 a50,50 0 0 1 50,50 v0 a50,50 0 0 1 -50,50
                h0 a50,50 0 0 1 -50,-50 v0 a50,50 0 0 1 50,-50" />
        </svg>
        <style>
          #background-path {
            stroke: grey;
            stroke-width: ${bar_thickness};
          }
          #progress-path {
            stroke: ${color};
            stroke-width: ${bar_thickness};
            stroke-dasharray: ${totalLength};
            stroke-dashoffset: ${progress};
            transition: stroke-dashoffset 1s linear;
          }
        </style>

#

hehe

open ridge
woeful dome
#

i just removed the whole strole-linecap and worked ๐Ÿ™‚

#

but none might be more safe to use

#

your way*

#

and i have to fix my const to var i see now hehe

open ridge
#

var is the safest approach IMO. const is best if you're not going to change the value later.

#

I also ended up making a second custom_field and setting the z-index of each. It works, but if it works with a single custom_field, that's probably the better way to go.

woeful dome
#

so you z-indexed the SVG background in a custom field? that might work for many other things.. like adding shadows and stuff ๐Ÿ™‚

#

i will need to test that ๐Ÿ™‚

open ridge
#

Yeah. It allowed me to put the background under the progress.
But, interestingly, the background stroke-width wouldn't change and I couldn't figure out why. ...I still had the box-shadow in place... ๐Ÿคฆโ€โ™‚๏ธ

#

Putting the background in the code before the progress would have probably worked too but I wanted the background at the very end (so it would be easy to delete if it didn't work.)

#

Had to change totalLength from 311.1 to 314 now that the linecap is gone. (There was a gap at 100%.)

woeful dome
#

i think i will try your way with the background when im back home, i se it made some complication having it in the same custom field

open ridge
#

I just put the two paths back together. Seems to work for me.

olive oracle
#

You guys are awesome, I drop and image and with in a couple hours you 2 smashed it out. I really appreciate the support guys. ๐Ÿ‘.
I am just on my road to learning all this, you are were I want to be. Kudos.

open ridge
#

If you would have posted your question a week or two ago, I doubt there would have been a response. It just so happened that BerrisNO was working on something similar and the concept was able to be adapted.

#

I just added some variables that can be easily defined and color options for the bar. The bar can now be a defined color, simple 5-color scale, or dynamic red-to-green.```yaml
variables:
demo_percentage: 65
bar_thickness: 13
bar_background: gray
bar_color: dynamic

#

I incorporated the dynamic colors from one of the examples on my GH.

open ridge
#

So, I just learned something new based on something that I've been trying to incorporate more: conditional (ternary) operators. But, I used it to set a variable. I went from javascript if (typeof variables.demo_percentage !== 'undefined') { var percentage = variables.demo_percentage } else { var percentage = entity.state } to```javascript
var percentage = (typeof variables.demo_percentage !== 'undefined') ? variables.demo_percentage : entity.state

woeful dome
#

Oh.

open ridge
#

Just had a genius idea: merging the square and circle configurations into one super card. ๐Ÿฆธ

woeful dome
#

you and me think alike bro!

#

I was thinking of a if variable.type = circle ( sett different values)

#

We do like super card hehe

#

using your code might help with that...

var type = (typeof variables.type !== 'circle') ? variables.type : square

#

how the frick did you add the colors to pasting code in discord? ๐Ÿ˜›

open ridge
#

I was thinking along those lines, however, I have an interesting spin on it. Two custom fields: progress-square and progress-circle. In the styles: for each custom_field, display: none could be set to hide the one not in use.
For the rest of the card, there should be a relatively easy way to handle the layout without having to use IF statements on each line. Perhaps mediaquery or something.

open ridge
woeful dome
#
var type = typeof d_sellers1.awesome!==`OFC` 

#

oh nice

open ridge
#

I've already incorporated more variables. It will soon be ready to turn into a template and theat's when it will become really useful. ```yaml
variables:
demo_percentage: 34
card_height_width: 120
card_background: black
icon_state_color: white
bar_thickness: 13
bar_background: gray
bar_color: blue

woeful dome
#

Same as with github basically

open ridge
#

exactly.

woeful dome
#

why use height and width?

open ridge
#

Just because apect_ratio never really works for me. I tend to set specific sizes for the majority of my cards (provided they're not sitting in a grid card or something like that.)

woeful dome
#

ah noted

open ridge
#

That's what works for me but I'm sure there's a way to incorporate both.

woeful dome
#

i add everything inside grids automatically hehe

#

woops i did something with the text hehehe

open ridge
#

I noticed earlier if I set the demo_percentage to 0, the state disappeared.
Correction: it actually returns the entity.state now that I have it set to use either. Kind of a weird thing. Not really a bug but I guess it has something to do with 0 kind of being undefined.

#

@karmic raptor Come join in the fun here. I'm curious how you got that to work.

karmic raptor
#

I'm on my way home. I can discuss 2 hours later

woeful dome
#

@open ridge what styles have you applied to the card?

#

my name and state is to fare bewlow hehe.
probably because i dont use height and width

open ridge
woeful dome
#

i was missing the icon height of 50% lol

karmic raptor
#

Is that what you want?

woeful dome
#

what happens if you set the border radius to 25% instead?

karmic raptor
open ridge
woeful dome
#

thats the code withouth the SVG thing that we are working on

karmic raptor
woeful dome
#

never mind.. spell check

karmic raptor
woeful dome
karmic raptor
#

If you want to follow the shape, you need to add code for it

#

I can try 2 hours later

woeful dome
#

no no, we are trying a different way, without using the background thing ๐Ÿ™‚

#

@open ridge i got it working now:

open ridge
woeful dome
#

yes sir

#

Im working on all the variables now, prepairing it for the config change ๐Ÿ™‚ but i need your help on making this the super duper card! ๐Ÿ™‚

open ridge
#

One thing that I've considered about my version is that it is really only useful for 0-100% values. Although, I was considering how to make it a bit more flexible to handling other values.

woeful dome
#

you can add the threshold thing

#

i can share mine in 2 sec

#

might take a bit more then 2 sec.. i screwed up my threshold hehehe

#

I forgot how to add a sensor in variables lol hehe

woeful dome
open ridge
#

Do you mean like this: yaml variables: sensor_entity: sensor.ams_7494_pthen at Line 61javascript var percentage = (state / states[variables.sensor_entity].state) * 100

woeful dome
#

oh my god.. was it my ' ' that made it go in error mode?

open ridge
#

Or you can just pull the value into the variable:yaml variables: sensor_entity_state: "[[[ return states['sensor.ams_7494_p'].state ]]]"then at Line 61javascript var percentage = (state / variables.sensor_entity_state) * 100

woeful dome
#

i always do this.. add ' ' where is not supposed to be, and then not when i need them hehehe

open ridge
#

Yeah. They can make a big difference sometimes. ๐Ÿ˜›

woeful dome
#

dude... 20 minuits of problem shooting.....

#

var threshold = states[variables.sensor_threshold].state
var percentage = (state / states[variables.sensor_threshold].state) * 100
#

nice it works!

#

i have so many things i should do... but this thing is fun ๐Ÿ˜›

open ridge
#

I should be asleep right now... 5.5 hours should be good enough though.

#

Oh. I noticed what you did with the background opacity. I didn't even consider going that route, but it makes sense that it would work.yaml opacity: ${bar_bg_opacity};

woeful dome
#

yes, inspired by you tricking me into using variables ๐Ÿ™‚

open ridge
#

You don't have to set the variables in your code block to use variables set at the card level. Just call the variables.whatever or entity.state directly since they're already defined. javascript var bar_thickness = variables.bar_thickness; var state = entity.state; var bar_bg_opacity = variables.bar_bg_opacity; var bar_bg_color = variables.bar_bg_color;

woeful dome
#

ah ok

open ridge
#

The only problem with setting the bar_bg_opacity, is if it is undefined, it will break the card. When/if you turn it into a template, you must set the variable within the template (like a default setting). Any variables defined at the card level will override the template. Really, all variables need to be defined at the template level to ensure default values are present. (Except for demo_percentage that I used which is special.)

woeful dome
#

i usually always set tie variables in the template

#
      var state = entity.state;
      var threshold = states[variables.sensor_threshold].state
      var percentage = (state / states[variables.sensor_threshold].state) * 100
      if (percentage >= 90) var color = 'red';
      else if (percentage >= 70) var color = 'orange';
      else if (percentage >= 50) var color = 'yellow';
      else if (percentage >= 30) var color = 'lightgreen';
      else var color = 'lightgreen';
      var totalLength = 315;
      var progress = (1 - state / threshold) * totalLength;

      var svg = `
        <svg id="progress-bar" fill="none"  viewBox="0 0 100 100" width: 100%; height: 100%;>
          <path id="background-path" d="M50,0.2
                h0 a50,50 0 0 1 50,50 v0 a50,50 0 0 1 -50,50
                h0 a50,50 0 0 1 -50,-50 v0 a50,50 0 0 1 50,-50" />
          <path id="progress-path" d="M50,0.2
                h0 a50,50 0 0 1 50,50 v0 a50,50 0 0 1 -50,50
                h0 a50,50 0 0 1 -50,-50 v0 a50,50 0 0 1 50,-50" />
        </svg>
        <style>
          #background-path {
            opacity: ${variables.bar_bg_opacity};
            stroke: ${variables.bar_bg_color};
            stroke-width: ${variables.bar_thickness};
          }
          #progress-path {
            stroke: ${color};
            stroke-width: ${variables.bar_thickness};
            stroke-dasharray: ${totalLength};
            stroke-dashoffset: ${progress};
            transition: stroke-dashoffset 1s linear;
          }
        </style>
      `;
      return svg;
#

thanks, that made it allot cleaner ๐Ÿ™‚

open ridge
#

Well, that solves that problem: opacity: ${variables.bar_background_opacity ?? 0.2};

woeful dome
#

genius!

#

so it goes back to 0.2 if nothing is set right?

open ridge
#

I was actually looking for something else dealing with null but this turned out to be better.

#

Correct. If the variable is not defined at all or is simply null, it returns 0.2. If the variable has a value, it uses that value.

woeful dome
#

that is sawesome

#

so we can set all defaults, to help the user get a "standard" then they can edit variables if needed

open ridge
#

Yup. Without having to explicitly define the variables in the template ahead of time.

woeful dome
#

nice find dude! that is perfect

#

so i just added it and it works real nice: bar_thickness: #set a value between 1-100, default set to 5

#

real handy!

open ridge
#
#background-path {
  opacity: ${variables.bar_background_opacity ?? 0.2};
  stroke: ${variables.bar_background ?? "gray"};
  stroke-width: ${variables.bar_thickness ?? 13};
}```
woeful dome
#

same with what i did hehe perfectto

#

Is it allowed to work on this in the hospital, if wife desides to poop out child nr2 while we are working on this? hehhe

open ridge
#
styles:
  card:
    - height: '[[[ return `${variables.card_height_width ?? 120}px` ]]]'
    - width: '[[[ return `${variables.card_height_width ?? 120}px` ]]]'
    - background: '[[[ return variables.card_background ?? "black" ]]]'
woeful dome
#

but i dont get the "stroke: gray" thing... it gives me an error

#
stroke: ${variables.bar_bg_color ?? gray};

This gives no error if you have something in the variables, but when you remove it, i get a syntax

open ridge
#

Looks like gray has to be in quotes. stroke: ${variables.bar_background_color ?? "gray"}; which makes sense because otherwise it could be a a variable.

woeful dome
#

true

#
styles:
  img_cell:
    - height: '[[[ return `${variables.icon_height ?? 120}` ]]]'
    - height: '[[[ return `${variables.icon_width ?? 120}` ]]]'
#

so that actually made things allot easier for "beginners"

#

might be a stupid question.. but when i use 100 instead of 100px, what does it actually use?

open ridge
#

px might be a default. I didn't consider it would have a default so I just added the px to keep it from breaking.
EDIT: I just tried to remove px from the card's height and width and it broke the card.

#

If the demo_icon is defined, it will use that. Otherwise, it defaults to the entity's icon. icon: "[[[ return `${variables.demo_icon ?? ''}` ]]]"

woeful dome
#

might be safe to use px then.

#

i can se that without it braks at my side as well hehe

#

was kind of cool with a bigger backgrund svg hehe

#

there is many customazation things we can do with this card.. by just changing the width and stuf.. love it!

open ridge
#

might consider using % instead of px.

woeful dome
#

yeah i usually do

amber sandal
#

Can someone send the whole card code?
I tried to piece together stuff and failed

woeful dome
#

I will update my GitHub when I'm back home tomorrow. Currently a bit busy ๐Ÿ™‚

olive oracle
#

I know where to come when my get my next idea haha. I spent all weekend searching for something like this, and a few evenings Trying to force ApexCharts to do what I want. Would be really cool to test it out when you guys are ready... I am really good at breaking things ๐Ÿคฃ

karmic raptor
#
    background_in_card:
      - width: |-
          [[[ if ( variables.main_card_height < variables.main_card_width )
              return Math.floor(variables.main_card_width-(variables.main_card_height-(variables.main_card_height/1.1)))+'px';
            return Math.floor(variables.main_card_width/1.1)+'px';
          ]]]```
amber sandal
open ridge
#

I've seen images "not get linked properly" when pasting directly into the editor. That's probably all that is. Just means the image needs to be re-added.

#

Nevermind. I just looked at the link. He probably wrote it in a private repository and then copied the markdown into the public.

woeful dome
#

I will try to fix it tonight

olive oracle
#

Just want to say thanks to everyone who helped and a big thanks to @woeful dome for the coaching. I have got the key parts of what I ws hoping to achieve, just need a little tweaking of shadows etc.

#

I take no credit for this. Here is the Code I ended up with for each "chip card"

#

as I make more tweaks I will share them here if anyone is interested

woeful dome
#

Beautiful ๐Ÿ˜ quick note. When pasting code in here you might want to use dpaste.org or something ๐Ÿ™‚๐Ÿ™‚

woeful dome
open ridge
woeful dome
olive oracle
#

Now I just want to find other things with Batteries so I can make more hahah

open ridge
#

Do the iPad & Polestar images not show the rest of the bar properly (from 48-100% and 91-100%, respectively)?

#

Or do you just have it set to none which I just figured out works, too.

#

I'm dumb. Just noticed you posted code link. I see it now. You have the bar thickness at 8 and the bar background thickness at 2. That makes sense now.

#

In my version, I just used one variable that applied to both paths.

amber sandal
# olive oracle

I'm using this yaml
Any way to fix the overlap in horizontal stacks ?

open ridge
#

You want them to display on top of each other?

amber sandal
#

next to each other

amber sandal
open ridge
#

Here I used a grid card but you can apply the same concept to the horizontal-stack.```yaml
type: grid
cards:

  • type: custom:button-card
    entity: sensor.s22_ultra_battery_level
    [...all the yaml here...]
  • type: custom:button-card
    entity: sensor.s22_ultra_battery_level
    [...all the yaml here...]```
amber sandal
#

grid seems wo work well, but it adds a lot of extra blank space

open ridge
#

You can "control" the spacing by setting the number of columns (accounting for future cards.)

columns: 8```
amber sandal
#

Perfect!
I can have a row on my dashboard dedicated to batteries

open ridge
#

If you want to get really fancy, you can incorporate an auto-entities card and have it "generate" the bar-cards. Here, BerrisNO has it set to find power usage and sort it by consumption. (It can "find" the entities to display or you could define a list. Minimal repetitive code.)

woeful dome
#

The auto entity is using labels to find what I want to show. So I add labels to everything I want shown there, and it filters it automatically ๐Ÿ™‚

amber sandal
#

possibly a galaxy ring in the future :)

open ridge
#

It can also accept wildcards. So, something like sensor.*_battery_level could be used.

#

Holy crap! 750-day streak on DuoLingo. That's crazy!

amber sandal
#

if i don't practice in a day all the screens in my house go crazy

open ridge
#

How so?

amber sandal
#

this lol

open ridge
#

๐Ÿ‘€

olive oracle
olive oracle
#

then I can drag and re-arrange the cards easily

amber sandal
olive oracle
#

I usually do to, just trying out the new feature.

#

Strange one. Does any one know why the coloured progress bar isn't showing up on my iPad dashboard? everything else is fine, just the progress bar is missing....

woeful dome
olive oracle
#

oh no ๐Ÿ˜ฆ

#

god I hate apple

woeful dome
#

can you install other borwsers in ipad? like firefox or something?

olive oracle
#

I am using the HA app on the iPad in focused mode, I am guessing switching to Chrome wouldn't be a big issue.

woeful dome
#

Well not sure if it will help... But it's worth a try

olive oracle
#

No luck, same issue with chrome on the iPad.

woeful dome
#

Hmm well shit

olive oracle
#

playing with other uses of this card of yours, and trying to figure out how to change the Shadow colour based on the entity state. Why? - I have sensors on doors and windows, when they are all closed I just want a plain grey card, but if any are open I want it to be red. the idea is that I can quickly glance at my dashboard and know if everything is closed before leaving or going to bed.

#

I even tried setting up two box_shadows as variables but again styles doesn't seem to like if/else statements ( or at least how I have written them). If I google it, I never seem to get the same answer in 2 places.

woeful dome
#

I have already started on that with shadows, it will come out on next update I think

#

But. I would probably use another method.. and that's conditions. So it only shows if anything is open, and hides closed stuff

#

It will be on a separate card though

olive oracle
#

oh cool. Well just if it helps at all this is some of the ones I am playing with:

#

My next step was going to make the Electric car box-shadows glow blue, when they are charging. so I will take a look at conditions.

#

or maybe pulsating, but let me start with getting the right colour first hahaha

#

just to help me narrow down my searching and learning, this is considered CSS right? or is it something else?

woeful dome
#

Pulse ?

#

Just look at my GitHub, the vehicle card has a effect you can tweak

olive oracle
#

yes similar to that, but for the shadow only. need to learn how to use conditions in styles first

woeful dome
#

State styling

#

It's in my vehicle card

olive oracle
#

I tried to follow what you have done on your Vehicle card, and tried it 20 different ways, but I am getting some odd behaviour. Sometimes it changes colour, but then it won't change back. I thought it might have something to do with the state value being text rather than an integer, but I tried both and still nothing. No rush, you got a lot more important things going on, just when you get a few mins spare, can you tell me where I am going wrong? cheers

open ridge
#

thought it might have something to do with the state value being text rather than an integer
@olive oracle All states are strings. But, when you do comparisons of a string that is a number, it has to be coveted to an integer. With Javascript, use parseInt(value) or parseFloat(value); with Jinja, pipe to int/float value | int or value | float.

olive oracle
#

turns out it was throwing up the strnage bevahiour as it was unhappy that I had semi-colons at the end of the box shadow inputs. wish the inbuilt de-bugging was a little smarter to counter act my lack of it haha

#

I also needed to create another template that gave me an 'on' / 'off' value based on the number of doors open.

#

everything closed

#

a door open:

#

and if you tap the card a pop-up tells me what door is open:

open ridge
karmic raptor
olive oracle
olive oracle
#

might add another colour state ( pulsating blue) based on a different entity ( charging state), next.

olive oracle
#

Went with the pop-up card and auto entities.

karmic raptor
woeful dome
#

animation is fun ๐Ÿ˜„

olive oracle
#

@woeful dome I have the SVG working on the Ipad now too, if you are interested

woeful dome
#

how?

olive oracle
#

@woeful dome

Here's my full code. Still working in the car one that gives an additional state of plugged in and not charging. Will share that when it's done. But for now here is my one for a device state of charge with a pulsing shadow if charging.
https://dpaste.org/jaW7D

woeful dome
#

And the svg works on iPad? What part of the code made the svg on iPad work?

woeful dome
olive oracle
olive oracle