Lovelace: Button card

So it does…! Thanks for the help!

I’m trying to color a button based on the state_attr of another entity… this stems from a conditional script I’m putting together to join/unjoin Sonos speakers to groups, and display different colors based on their group membership. Here’s what I have that doesn’t work for me so far:

type: custom:button-card
color_type: card
aspect_ratio: 2/1
color: auto
entity: media_player.sonos_living_room
name: Living Room
show_name: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.sonos_living_room_join_unjoin_kitchen
show_state: false
state:
  - color: |
      [[[
        if ('media_player.sonos_kitchen' in state_attr('media_player.sonos_living_room', 'sonos_group') return 'rgba(0,200,0,.7)';
        else return 'rgba(200,200,0,.7)';
      ]]]
    icon: mdi:speaker-wireless
    value: playing

Unfortunately, it’s only returning my rgba(0,200,0,0.7). Where have I gone wrong here?

your template is incorrect syntactically.

[[[ return states['media_player.sonos_living_room'].attributes.sonos_group.includes('media_player.sonos_kitchen') ? 'rgba(0,200,0,.7)' : 'rgba(200,200,0,.7)'; ]]]

might work though (didnt check any logic, imply followed js syntax here (you seem to be using some mix jinja /js code :wink: )

You’re right! And I edited my comment it just as you responded. I’m now getting one color, but not both.Nope… I was mistaken. My code is still worthless, let me try what you’ve suggested…

EDIT: No, unfortunately, that just gave me a blank white button in either case… still fooling with it.

OK, this is highly odd:

type: custom:button-card
color_type: card
aspect_ratio: 2/1
color: auto
entity: media_player.sonos_living_room
name: Living Room
show_name: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.sonos_living_room_join_unjoin_kitchen
show_state: false
state:
  - color: >
      [[[ if ("media_player.sonos_kitchen") in
      (state_attr["media_player.sonos_living_room"], 'sonos_group') return
      'blue';
        else return 'rgba(200,200,0,.7)';
      ]]]
    icon: mdi:speaker-wireless
    value: playing

When I play sonos_living_room (state = playing) and it’s in no group, the button remains green and the icon changes from white to black. When I then add it to the group with sonos_kitchen, it does not change. Hm.

Unfortunately, I’ve tried this and it’s not netting me a color change during playing state:

type: custom:button-card
color_type: card
aspect_ratio: 2/1
color: auto
entity: media_player.sonos_living_room
name: Living Room
show_name: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.sonos_living_room_join_unjoin_kitchen
show_state: false
state:
  - color: >
      [[[ return
      states['media_player.sonos_living_room'].attributes.sonos_group.includes('media_player.sonos_kitchen')
      ? 'orange' : 'blue'; ]]]
    icon: mdi:speaker-wireless
    value: playing

I’m not seeing a similar example over on the gist, either. Any other ideas?

EDIT: This doesn’t work:

state:
  - color: >
      [[[ if (states['media_player.sonos_living_room.attributes.sonos_group']
      includes['media_player.sonos_kitchen'])
       return 'orange';
       return 'blue'; ]]]
    icon: mdi:speaker-wireless
    value: playing

…nor does this:

state:
  - color: >
      [[[ if
      (states['media_player.sonos_living_room']attributes.sonos_group.includes["media_player.sonos_kitchen"])
       return 'orange';
       return 'blue'; ]]]
    icon: mdi:speaker-wireless
    value: playing

…so I’m at a bit of a loss.

first of all, I didn’t know you were using the entity in your card, so used a ‘global’ states syntax. you should change that to

[[[ return
      entity.attributes.sonos_group.includes('media_player.sonos_kitchen')
      ? 'orange' : 'blue'; ]]]

and save some resources.

also, you’re getting mixed up in states and styles… I take it you want the icon color to change, so you have to indicate that as in the docs:

state:
    - value: playing
      styles:
        icon:
          - color: >
              [[[ return entity.attributes.sonos_group.includes('media_player.sonos_kitchen')
                  ? 'orange' : 'blue'; ]]]

also, since the icon isnt state dependent (?) id set that in the button_config itself.

nope, none of these 3 will work, because they are not correct :wink: you need to set the color to the icon, which you dont do in either of the 3 examples. (the last 2 also have incorrect templates swill not work. there should be a . before attributes, and states['media_player.sonos_living_room.attributes.sonos_group'] simply isnt the way the state attributes are found.

Thank you–I’m making some progress, but I’m not there yet.

I have color_type set to card, and I’m actually trying to get the card color to change (the icon will stay white, or maybe change color on state only). For that reason–and because it’s where my entity states have been responsible for changing colors until now–I’ve been playing around in this section.

So, I used your code and replaced icon with card, and while I do get a color change, the card is black when playing; and black regardless of the value of sonos_group:

state:
  - value: playing
    styles:
      card:
        - color: >
            [[[ return
            entity.attributes.sonos_group.includes('media_player.sonos_kitchen')
            ? 'orange' : 'blue'; ]]]

Had I seen orange and blue, I could claim success, but I’m not there yet. Thanks for looking at this and providing suggestions; any ideas to push me over the finish line?

can you confirm the template in dev tools:

{{'media_player.sonos_kitchen' in state_attr('media_player.sonos_living_room','sonos_group') }}

works ? If not, please post the result of

{{state_attr('media_player.sonos_living_room','sonos_group')}}

also, take out color: auto

do note that setting

card: 
  - color

sets the color to the items in the card (except icon)… so name, state etc. if you want the card itself to get a color, you need background-color:

        card:
          - color: var(--text-color-off)
          - background-color: var(--background-color-off)

Yes! I checked this in my script, linked above. I watch the value toggle by grouping and ungrouping in the Sonos app.

I did in fact remove color: auto before the last attempt. I’m not sure where I’d put this code… at the highest level?

        card:
          - color: var(--text-color-off)
          - background-color: var(--background-color-off)

I should note that these state and color changes work fine:

state:
  - color: rgba(0, 200, 0, .7)
    icon: mdi:speaker
    value: paused
  - color: rgba(169, 169, 169, .7)
    icon: mdi:speaker
    value: idle
  - color: rgba(200, 0, 0, .7)
    icon: mdi:close-circle-outline
    value: unavailable

great, so the js template should be ok too (always check in inspector to notice any syntax errors though…)

I guess it is the (in) correct configuration of your button config that prevents it from doing what you want …

Well… using this, I get the icon to correctly reflect the sonos_group values (blue and orange):

type: custom:button-card
color_type: card
aspect_ratio: 2/1
entity: media_player.sonos_living_room
name: Living Room
show_name: true
tap_action:
  action: call-service
  service: script.turn_on
  service_data:
    entity_id: script.sonos_living_room_join_unjoin_kitchen
show_state: false
state:
  - value: playing
    styles:
      icon:
        - color: >
            [[[ return
            entity.attributes.sonos_group.includes('media_player.sonos_kitchen')
            ? 'orange' : 'blue'; ]]]
  - value: paused
    color: rgba(0, 200, 0, .7)
    icon: mdi:speaker
  - value: idle
  - color: rgba(169, 169, 169, .7)
    icon: mdi:speaker
  - color: rgba(200, 0, 0, .7)
    icon: mdi:close-circle-outline
    value: unavailable
styles:
  grid:
    - grid-template-areas: '"i" "n"'
    - grid-template-rows: 2fr 20%
  icon:
    - color: white
    - height: 35px
    - padding-top: 5px
  card:
    - height: 80px
  name:
    - font-size: 14px
    - color: white

Now I just need to fool around with it until I can get the card to change colors.

Yep, and start doing that by always keeping the - for value, you make several edits that lead to errors.
(See idle)

Ah, right. Thanks. I first created this card a long time ago from copying & pasting examples, and I’ve learned a bit since then. This card and every similar one started this morning with - color , and now I’m remedying that.

I’ve been at this little problem for a few hours and I’m stuck. I frankly don’t get why icon: works and card: doesn’t. I can change the setting of color_type: but that royally screws up the card.

just so you dont misunderstand me:
the order isnt perse important, but it keeps you from making mistakes like:

  - value: paused
    color: rgba(0, 200, 0, .7)
    icon: mdi:speaker
  - value: idle
  - color: rgba(169, 169, 169, .7)
    icon: mdi:speaker
  - color: rgba(200, 0, 0, .7)
    icon: mdi:close-circle-outline
    value: unavailable

where you probably meant:

  - value: paused
    icon: mdi:speaker
    styles:
      icon:
        - color: rgba(0, 200, 0, .7)
  - value: idle
    icon: mdi:speaker-off
    styles:
      icon:
        - color: rgba(169, 169, 169, .7)
  - value: unavailable
    icon: mdi:close-circle-outline
    styles:
      icon:
        - color: rgba(200, 0, 0, .7)

Well, those colors were relevant to the card (state) and it worked as I’d hoped, at least until my requirements changed earlier today. At this point I’m not sure how to accomplish the card-color-change based on sonos_group.

No, the order isn’t important, but putting the value of state first is more logical for me than color. In the original code, I wanted to change the card color and not the icon.

EDIT: The corrected code in your last post does something different from mine; mine may (?) be bad form, but the icon changes in form as intended, and the card changes in color as intended. Your corrected code changes the icon color instead of the card, and the card turns black instead of whatever color it was before. That’s not what I was looking to do when I put these buttons together sometime last year.

Ah well. I’m still playing with it and not finding any way to do it, so maybe it’s not possible with the button card.

EDIT: In the end… I accomplished what I wanted to do with a few template sensors and conditional cards. The button backgrounds change according to whether the speakers are grouped or not, playing or not, etc. As a bonus, I can call the join & unjoin services directly instead of using scripts. My only remaining gripe is that using conditional cards in this way–showing one button or the other, arranged in a horizontal stack–results in a slight horizontal offset; i.e., things don’t line up as nicely. Oh well.

Is it possible to use a variable to define another variable?

This code returns an error “Cannot read properties of undefined (reading ‘LEVEL_CRITICAL’)”:

variables:
  LEVEL_CRITICAL: "300"
  LEVEL_WARNING: "1000"
  STATE_COLOR: >-
    [[[
      var STATE = entity.state;
      if (parseFloat(STATE) < parseFloat(variables.LEVEL_CRITICAL))
        return 'red';
      else if (parseFloat(STATE) < parseFloat(variables.LEVEL_WARNING))
        return 'orange';
      else
       return 'green';
    ]]]

This code works:

...
      if (parseFloat(STATE) < parseFloat(100))
        return 'red';
      else if (parseFloat(STATE) < parseFloat(300))
...

Do not bother about hard-coded values for LEVEL_CRITICAL & LEVEL_WARNING variables - I was going to override these values by templates in “posterity” buttons.

I do my first experiments with nested buttons, to have a general switch for AdGuard but also a button in the top right to just pause it for 30 mins.
The functionality meanwhile works great, but I am not able to hide the borders of the nested card in the top right. I have searched through the whole thread and found some questions and feature requests on hiding the borders, but no answers.
Even if I explicitly use a white border, I still see this box shadow as you see here, how can I get this away?
grafik

Here is my current config:

type: custom:button-card
entity: switch.adguard_protection
name: AdGuard Protection
show_state: false
styles:
  card:
    - height: 290px
  name:
    - font-size: 14px
  custom_fields:
    pause:
      - position: absolute
      - right: 2%
      - top: 2%
      - font-size: 10px
state:
  - value: 'on'
    styles:
      icon:
        - color: green
  - value: 'off'
    styles:
      icon:
        - color: grey
custom_fields:
  pause:
    card:
      type: custom:button-card
      entity: timer.timer_30_min
      show_state: true
      show_name: false
      size: 60px
      tap_action:
        action: call-service
        service: input_boolean.toggle
        service_data:
          entity_id: input_boolean.adguard_pause
      state:
        - value: idle
          styles:
            icon:
              - color: var(--paper-item-icon-color)
            state:
              - color: white
        - value: active
          styles:
            icon:
              - color: red
            state:
              - color: red
1 Like

for a nested button-card you can set a style in the nested card with:

      styles:
        card:
          - box-shadow: none
type: custom:button-card
entity: switch.adguard_protection
name: AdGuard Protection
show_state: false
styles:
  card:
    - height: 290px
  name:
    - font-size: 14px
  custom_fields:
    pause:
      - position: absolute
      - right: 2%
      - top: 2%
      - font-size: 10px
state:
  - value: 'on'
    styles:
      icon:
        - color: green
  - value: 'off'
    styles:
      icon:
        - color: grey
custom_fields:
  pause:
    card:
      type: custom:button-card
      styles:
        card:
          - box-shadow: none
      entity: timer.timer_30_min
      show_state: true
      show_name: false
      size: 60px
      tap_action:
        action: call-service
        service: input_boolean.toggle
        service_data:
          entity_id: input_boolean.adguard_pause
      state:
        - value: idle
          styles:
            icon:
              - color: var(--paper-item-icon-color)
            state:
              - color: white
        - value: active
          styles:
            icon:
              - color: red
            state:
              - color: red


1 Like

Thx, works perfectly, I had played with card style but was missing the box shadow as I was rather trying with border commands.
A really nice card now :slight_smile: