Fun with custom:button-card

Perfect. Thanks for the help.

Here’s what I did with it: I created a set of additional templates, based on the standard one: (under button_card_templates)

  standard-button:
    template: standard
    state:
      - value: 'on'
        styles:
          card:
            - background-color: gold
          name:
            - color: blue
          icon:
            - color: blue
            - opacity: 1
      - value: 'off'
        styles:
          card:
            - background-color: slategrey
          name:
            - color: white
          icon:
            - color: white
            - opacity: 0.5
  standard-alert:
    template: standard
    state:
      - value: 'on'
        styles:
          card:
            - background-color: darkgrey
          name:
            - color: yellow
          icon:
            - color: yellow
            - opacity: 1
      - value: 'off'
        styles:
          card:
            - background-color: darkgrey
          name:
            - color: white
          icon:
            - color: white
            - opacity: 0.5
  standard-cover:
    template: standard
    state:
      - value: 'open'
        styles:
          card:
            - background-color: gold
          name:
            - color: blue
          icon:
            - color: blue
            - opacity: 1
      - value: 'closed'
        styles:
          card:
            - background-color: slategrey
          name:
            - color: white
          icon:
            - color: white
            - opacity: 0.5

Then, within my custom button cards, something like this:

                - entity: binary_sensor.katie_smith_s_galaxy_s7_edge_presence_2
                  name: Katie
                  template: standard-button
                  type: 'custom:button-card'

or this:

                - entity: binary_sensor.daytime_sensor
                  name: Day?
                  template: standard-alert
                  type: 'custom:button-card'

or this:

                    - entity: cover.garage
                      name: Over head
                      template: standard-cover
                      type: 'custom:button-card'
                      aspect_ratio: 1/1.3

That looks like it will work :+1:

The more you play with it the more you’ll see places where you can consolidate some of the settings. For example, the off’ state is pretty consistent across all 3 of your templates, so if you wanted to you could make a base template with that config that the other 3 use as a template. There is also an id feature for states that makes it possible for the templates to merge state configs correctly (even if the values aren’t the same!)

Just for fun, and because I like sharing ideas, here is a different way to define your templates given your example:

  standard-button:
    template: standard
    state:
      - id: value_on
        value: 'on'
        styles:
          card:
            - background-color: gold
          name:
            - color: blue
          icon:
            - color: blue
            - opacity: 1
      - id: value_off
        value: 'off'
        styles:
          card:
            - background-color: slategrey
          name:
            - color: white
          icon:
            - color: white
            - opacity: 0.5
  
  standard-alert:
    template: standard-button
    state:
      - id: value_on
        styles:
          card:
            - background-color: darkgrey
          name:
            - color: yellow
          icon:
            - color: yellow
      - id: value_off
        styles:
          card:
            - background-color: darkgey

  standard-cover:
    template: standard-button
    state:
      - id: value_on
        value: 'open'
      - id: value_off
        value: 'closed'

What I did was use your standard-button as a common template for the other two templates. I added id settings for the 2 states so that the other 2 templates can add or replace configs as needed.

In your standard-alert template I changed the state settings to refer to the id instead of the value and removed any settings already defined in the standard-button template, such as the icon opacity and a few other things.

In the standard-cover template I only had to change the value settings to open and closed, since the colors in the standard-button template are already what is needed.

The custom button card is so flexible that there is often more than a couple ways to get the desired effect. You could even use a single template to do this with some variables and javascript to adjust the colors. I’m having fun writing this up, so I’ll give an example:

  standard-button:
    template: standard
    variables:
      value_on: 'on'
      value_off: 'off'
      background_color_on: gold
      background_color_off: slategrey
      text_color_on: blue
      text_color_off: white
    state:
      - id: value_on
        value: '[[[ return variables.value_on ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_on ]]]'
          name:
            - color: '[[[ return variables.text_color_on ]]]'
          icon:
            - color: '[[[ return variables.text_color_on ]]]'
            - opacity: 1
      - id: value_off
        value: '[[[ return variables.value_off ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_off ]]]'
          name:
            - color: '[[[ return variables.text_color_off ]]]'
          icon:
            - color: '[[[ return variables.text_color_off ]]]'
            - opacity: 0.5

And then to use that template:

                # the variables don't need to be set because the template's default values are good
                - entity: binary_sensor.katie_smith_s_galaxy_s7_edge_presence_2
                  name: Katie
                  template: standard-button
                  type: 'custom:button-card'

                # same template, but setting a few variables to change colors
                - entity: binary_sensor.daytime_sensor
                  name: Day?
                  template: standard-button
                  type: 'custom:button-card'
                  variables:
                    background_color_on: darkgrey
                    background_color_off: darkgrey
                    text_color_on: yellow

                # again, same template but set some variables to change the on/off values
                - entity: cover.garage
                  name: Over head
                  template: standard-button
                  type: 'custom:button-card'
                  aspect_ratio: 1/1.3
                  variables:
                    value_on: open
                    value_off: closed

Hopefully that wasn’t too deep and it gives you a taste of what’s possible. :slight_smile:

1 Like

Not too deep at all and I can definitely see some other possibilities.
Thanks again.
I’d noticed the use of variables in another part of your example and had wanted to try using them. Your example is right along those lines.
As a side note, I’m always walking a balance point when I’m coding. I like to get things as elegant as possible without getting too cute (to the point where I won’t be able to remember what I did and why when I look back at it in a year :slight_smile: ) I made the mistake of some Byzantine CSS some time back. It looks like your examples are just the right level of actual simplification as opposed to obfuscation.

1 Like

I noticed that my garage cover has two additional states: “closing” and “opening”. (Go figure.) However, I like the fact that these don’t share the color theme with “open” or “closed”. It highlights that it’s in progress. A little serendipity along the way and something I can tweak if I decide to tweak it later.

Nice. I don’t have those states on mine.
We can easily add styling for those states like this:

  standard-cover:
    template: standard-button
    state:
      - id: value_on
        value: 'open'
      - id: value_off
        value: 'closed'
      - value: 'opening'
        styles:
          card:
            - background-color: magenta
      - value: 'closing'
        styles:
          card:
            - background-color: cyan

Or, if you were using the variables version:

                - entity: cover.garage
                  name: Over head
                  template: standard-button
                  type: 'custom:button-card'
                  aspect_ratio: 1/1.3
                  variables:
                    value_on: open
                    value_off: closed
                  state:
                    - value: 'opening'
                      styles:
                        card:
                          - background-color: magenta
                    - value: 'closing'
                      styles:
                        card:
                          - background-color: cyan
2 Likes

Yes. I’d figured something like that. I’m leaving it the way it is for now, but if I get an urge for completeness, I’ll that in.

One last question (I think):
Is there a way to change the name based on state? For instance, could the button tied to my binary_sensor.daytime_sensor (states ‘on’ or ‘off’) be “Day” when “on” and “Night” when “off”? I’m not entirely sure how to code the name text in the middle of a conditional state.

Specify the name you want in each of the states. You can set a few other things in states too, like icon and spin.

...
  state:
    - value: 'on'
      id: value_on
      name: Day
    - value: 'off'
      id: value_off
      name: Night
...
1 Like

Ah. I was lacking the id:
Thanks one more time.

The id is important when merging state settings because they are an array. If you don’t use the id then they are added to the array as new items. For example, if your template defines value: 'on' and your button also defines value: 'on' you will have 2 entries in your array for ‘on’ instead of one combined entry, and only one of them will be used (probably the one defined in the template because it is first in the final array). Merging states depends on the id because merging by value has significant challenges: the value could be javascript, or even if value is a literal the operator can be different and change the context what what the value represents. A nice benefit of using the id to merge state configs is that you don’t have to re-define the value or operator. This is especially useful when that value is javascript in the template.

Thanks for the explanation. I was trying to leverage that a little further. My presence device (person.russell_smith) has several states (home, not_home, Work, Church (as defined by my zones)). I cast this to binary_sensor.russ_sensor to toggle home/away status. I thought it would be interesting to use the multi-status “person” device in my indicator. At first I thought I could do something like

                - entity: person.russell_smith
                  name: Russ
                  template: standard-button
                  type: 'custom:button-card'
                  aspect_ratio: 1/1.07
                  styles:
                    name:
                      - font-size: 0.47em
                  state:
                    - value: home
                      id: value_on
                      name: Russ home
                      icon: 'mdi:home'
                    - value: not_home
                      id: value_off
                      name: Russ away
                      icon: 'mdi:home-outline'
                      variables:
                        text_color_off: yellow
                    - value: Work
                      id: value_off
                      name: Russ work
                      icon: 'mdi:office-building'
                      variables:
                        text_color_off: powderblue
                    - value: Church
                      id: value_off
                      name: Russ church
                      icon: 'mdi:church'
                      variables:
                        text_color_off: plum

but that didn’t work. So I added two more states to the standard_button:

    state:
      - id: value_on
        value: '[[[ return variables.value_on ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_on ]]]'
          name:
            - color: '[[[ return variables.text_color_on ]]]'
          icon:
            - color: '[[[ return variables.text_color_on ]]]'
            - opacity: 1
      - id: value_off
        value: '[[[ return variables.value_off ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_off ]]]'
          name:
            - color: '[[[ return variables.text_color_off ]]]'
          icon:
            - color: '[[[ return variables.text_color_off ]]]'
            - opacity: 0.5
      - id: value_2
        value: '[[[ return variables.value_2 ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_2 ]]]'
          name:
            - color: '[[[ return variables.text_color_2 ]]]'
          icon:
            - color: '[[[ return variables.text_color_2 ]]]'
            - opacity: 0.5
      - id: value_3
        value: '[[[ return variables.value_3 ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_3 ]]]'
          name:
            - color: '[[[ return variables.text_color_3 ]]]'
          icon:
            - color: '[[[ return variables.text_color_3 ]]]'
            - opacity: 0.5

and then coded my indicator like this:

                - entity: person.russell_smith
                  name: Russ
                  template: standard-button
                  type: 'custom:button-card'
                  aspect_ratio: 1/1.07
                  styles:
                    name:
                      - font-size: 0.47em
                  state:
                    - value: home
                      id: value_on
                      name: Russ home
                      icon: 'mdi:home'
                    - value: not_home
                      id: value_off
                      name: Russ away
                      icon: 'mdi:home-outline'
                      variables:
                        text_color_off: yellow
                    - value: Work
                      id: value_2
                      name: Russ work
                      icon: 'mdi:office-building'
                    - value: Church
                      id: value_3
                      name: Russ church
                      icon: 'mdi:church' 

It works, but I’m not sure why I could just load into the value_off id array with the Work and Church values.

I think in your first yaml you just needed to remove the id for Work and Church. You have id: value_off for not_home, Work and Church…effectively merging them together and clobbering the first 2 with the last one. You just need Work and Church to be added to the array as separate states. You only need the id’s if needing to configure the same states in multiple templates and/or the top level button. If you want to keep the id’s on them, make them unique.

1 Like

I see… and now I understand just a tad more of the way this works.
Thank you.

I decided to do a similar thing with the garage “cover” as follows:

                    - entity: cover.garage_door_opener
                      template: standard-button
                      type: 'custom:button-card'
                      aspect_ratio: 1/1.3
                      styles:
                        name:
                          - font-size: 0.47em
                      state:
                        - value: open
                          id: value_on
                          name: Overhead open
                        - value: closed
                          id: value_off
                          name: Overhead closed
                        - value: opening
                          name: Overhead opening
                          icon: 'mdi:arrow-up-bold-box-outline'
                        - value: closing
                          name: Overhead closing
                          icon: 'mdi:arrow-down-bold-box-outline'

That all works wonderfully, but I also tried changing the background color for opening and closing by adding the lines

                      variables:
                        text_color_off: DarkCoral

right under the icon setting. That didn’t work. Any ideas?

I also added the code

                      tap_action:
                        action: call-service
                        service: cover.toggle
                        service_data:
                          entity_id: cover.garage_door_opener

So now, instead of calling up the “more information” window (which will actually let me open or close the door, but it needs one more tap to open and one more to close the window), a tap will toggle the door open or closed depending on its current state.

I don’t believe variables can be set in the state config. If you want to change the background color in a state config you need to use styles:

                        - value: opening
                          name: Overhead opening
                          icon: 'mdi:arrow-up-bold-box-outline'
                          styles:
                            card:
                              - background-color: DarkCoral
1 Like

Oops. Right. Thanks again.

Is there some simple way to combine two binary items into a tri-state item?
To be specific, I already have a group.family that groups the people into one entity. It’s set in the default way so when anyone is home it’s state is home.
Here’s my indicator code:

        - entity: group.family
          name: Family
          template: standard-button
          type: 'custom:button-card'
          aspect_ratio: 1/1.1
          styles:
            name:
              - font-size: 0.47em
          variables:
            background_color_on: darkgrey
            background_color_off: darkgrey
            text_color_on: yellow
          state:
            - value: home
              id: value_on
              name: Some Home
              icon: 'mdi:home-circle'
            - value: not_home
              id: value_off
              name: All Away
              icon: 'mdi:home-circle-outline'

All that works flawlessly and it’s all I need for automations because they only care whether no one is at home or anyone is home. For display purposes, though, it would be nice to have it change to “all home” when everyone is present. I can set up another group with the same entities, but using the “all” option so that it’s only home when everyone’s here, but is there a way to combine both entities into one button which would display as above in all situations except when everyone’s here and then it would display “all home” and possibly use a brighter color than yellow to call attention to the fact?
The other possibility is to throw out the current scheme and create a virtual sensor device with three states: 0-home, 1-some away, 2-all away, and then throw some code to count presences. (Either count everyone at home each time any presence changes – absolutely reliable, but processing intense, or count up and down based on when any of the presences changes from home to not or vice-versa – less processing intense, but could there be an error in the count when two presence changes occur nearly simultaneously (say in the likely situation when we all leave in the same vehicle?))

I actually figure this one out myself :slight_smile:
What I did was set up an input_select with values of “none”,“some”, and “all”. In node-RED I created a flow which get triggered any time anyone comes home or leaves home. It then uses an entities node to get all my people (any entity_id that starts with person) as an array. Then I use a function that passes both the total number of people and a count of the filtered people whose state is “home”. I then set up text which is “none” (count=0), “all” (count=total), or “some” (whatever’s left) and set the option on my input_select using that. The input_select that is thus automated goes into a custom:button card as follows:

        - entity: input_select.family_presence
          name: Family
          template: standard-button
          type: 'custom:button-card'
          aspect_ratio: 1/1.1
          styles:
            name:
              - font-size: 0.47em
          variables:
            background_color_on: darkgrey
            background_color_off: darkgrey
            text_color_on: yellow
          state:
            - value: none
              id: value_off
              name: none Home
              icon: 'mdi:home-circle-outline'
            - value: some
              id: value_on
              name: some Home
              icon: 'mdi:home-circle'
            - value: all
              name: all Home
              icon: 'mdi:home-circle'
              styles:
                card:
                  - background-color: darkgrey
                name:
                  - color: greenyellow
                icon:
                  - color: greenyellow

Viola! I have an indicator that glows soft white when no one is home, yellow when someone is home, and green when everyone is home with icons and text to match the state.
I’m really enjoying being able to have such control over the interface.