button-card icon indicating copy to clipboard operation
button-card copied to clipboard

Allow Templating for State->Color

Open Rai-Rai opened this issue 2 years ago • 1 comments

Is your feature request related to a problem? Please describe. I'd like to crate a button showing 3 states from two entities for a door: open, closed and locked. Currently that's not easy to do since state (default) --> color doesn't allow templating Wanted states/colors: Door open: red and blinking Door closed & unlocked: yellow Door closed & locked: green

Describe the solution you'd like Allowing templating for state->color would allow the following configuration which is much shorter than what my current solution (see below) is:

type: custom:button-card
color_type: card
entity: binary_sensor.ug_garagentuere_mk
icon: mdi:door
state:
    - operator: default
      color: |
        [[[
          if(states["binary_sensor.ug_garagentuere_rk"].state == 'on') return 'red';
          else if(states["binary_sensor.ug_garagentuere_mk"].state == 'on') return 'orange';
          else if(states["binary_sensor.ug_garagentuere_mk"].state == 'off') return 'green';
          else return 'grey';
        ]]]
      styles:
        card:
          - animation: |
            [[[
              if(states["binary_sensor.ug_garagentuere_rk"].state == 'on') return 'blink 2s ease infinite';
              else return 'none';
            ]]]

Describe alternatives you've considered I've found a solution, but it takes too much duplicated code in my oppinion. When I change the color by using state->color, then the text/icon is automatically changed to be be still readable. With my solution I have to do this manually:

color_type: card
entity: binary_sensor.eg_garten_tursensor_eg_garten_tursensor_ch1
icon: mdi:door
styles:
  card:
    - animation: |
        [[[
          if(states["binary_sensor.eg_garten_tursensor_riegelkontakt"].state == 'on') return 'blink 2s ease infinite';
          else return 'none';
        ]]]
    - background-color: |
        [[[
          if(states["binary_sensor.eg_garten_tursensor_riegelkontakt"].state == 'on') return 'red';
          else if(states["binary_sensor.eg_garten_tursensor_eg_garten_tursensor_ch1"].state == 'on') return 'orange';
          else if(states["binary_sensor.eg_garten_tursensor_eg_garten_tursensor_ch1"].state == 'off') return 'green';
          else return 'grey';
        ]]]
    - color: |
        [[[
          if(states["binary_sensor.eg_garten_tursensor_riegelkontakt"].state == 'on') return 'black';
          else if(states["binary_sensor.eg_garten_tursensor_eg_garten_tursensor_ch1"].state == 'on') return 'black';
          else if(states["binary_sensor.eg_garten_tursensor_eg_garten_tursensor_ch1"].state == 'off') return 'white';
          else return 'black';
        ]]]

Additional context Add any other context or screenshots about the feature request here.

Rai-Rai avatar Nov 25 '23 20:11 Rai-Rai

Awesome - thanks for the workaround @Rai-Rai. My use was simpler than yours, so it worked out in the end :)

LordMike avatar Sep 24 '24 20:09 LordMike

I'd like to crate a button showing 3 states from two entities for a door: open, closed and locked.

Best to use a template helper in core to represent the state, then there is no complexity in button-card and your frontend becomes much easier to write. All state styles are not templatable and it will remain that way to reduce complexity of the color code.

dcapslock avatar Aug 24 '25 09:08 dcapslock

sorry to interrupt, but this can also be much better in the card itself:

color_type: card
entity: binary_sensor.eg_garten_tursensor_eg_garten_tursensor_ch1
variables:
  riegel_on: >
    [[[ return states['binary_sensor.eg_garten_tursensor_riegelkontakt'].state == 'on'; ]]]
  ch1_on: >
    [[[ return states[config.entity].state == 'on'; ]]]
  ch1_off: >
    [[[ return states[config.entity].state == 'off'; ]]]
icon: mdi:door
styles:
  card:
    - animation: |
        [[[ return variables.riegel_on ? 'blink 2s ease infinite' :'none'; ]]]
    - background-color: |
        [[[  if (variables.riegel_on) return 'red';
             else if (variables.ch1_on) return 'orange';
             else if (variables.ch1_off) return 'green';
             return 'grey';  ]]]
    - color: |
        [[[ if (variables.riegel_on) return 'black';
            else if (variables.ch1_on) return 'black';
            else if (variables.ch1_off) return 'white';
            return 'black';  ]]]

and then, I feel optimizations can be made even further, I didnt pursue because not into deep diving here. (check the final template always returning black if not variables.ch1_off) could probably be

    - color: |
        [[[ return variables.ch1_off ? 'white': 'black';  ]]]

Mariusthvdb avatar Aug 24 '25 11:08 Mariusthvdb