Fun with custom:button-card

Another random one I’m struggling with… trying to make a single button, that shows two icons… e.g. two different states at the same time… and has a single tap_action. Possible?

Check this other post I did that might be similar to what you want to do:

1 Like

Actually came up with a kinda hack… Actually made my own icons…

Now I need to figure out how to change the color of different parts of the icon…

Almost fully there now…

Basically the main icon is an SVG I am drawing with JS Templating to color different paths. The button opens a popup where i have controls for the individual doors and “dual” door functions. The issue is that when I click the main icon the “multiple” actions are being triggered… e.g. the buttons in the popup are somehow being triggered even though I clicked on the main icon…

Thoughts?

          - type: custom:button-card
            tap_action:
              action: fire-dom-event
              browser_mod:
                service: browser_mod.popup
                data:
                  title: Single Garage Door
                  content:
                    type: vertical-stack
                    cards:
                      - type: custom:frigate-card
                        cameras:
                          - camera_entity: camera.garage
                      - type: horizontal-stack
                        cards:
                          - entity: cover.single_garage_door
                            name: Open
                            icon: "emf:garage-single-open"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: call-service
                              service: cover.open_cover
                              service_data:
                                entity_id: "cover.single_garage_door"
                          - entity: cover.single_garage_door
                            name: Crack
                            icon: "emf:garage-single-cracked"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: call-service
                              service: button.press
                              service_data:
                                entity_id: "button.single_crack"
                          - entity: cover.single_garage_door
                            name: Close
                            icon: "emf:garage-single-closed"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: call-service
                              service: cover.close_cover
                              service_data:
                                entity_id: "cover.single_garage_door"
                      - type: horizontal-stack
                        cards:
                          - entity: cover.double_garage_door
                            name: Open
                            icon: "emf:garage-double-open"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: call-service
                              service: cover.open_cover
                              service_data:
                                entity_id: "cover.double_garage_door"
                          - entity: cover.double_garage_door
                            name: Crack
                            icon: "emf:garage-double-cracked"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: call-service
                              service: button.press
                              service_data:
                                entity_id: "button.double_crack"
                          - entity: cover.double_garage_door
                            name: Close
                            icon: "emf:garage-double-closed"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: call-service
                              service: cover.close_cover
                              service_data:
                                entity_id: "cover.double_garage_door"
                      - type: horizontal-stack
                        cards:
                          - entity: cover.double_garage_door
                            name: Open
                            icon: "emf:garage-dual-open-open"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: nothing
                              multi_calls: |
                                [[[
                                  hass.callService(
                                    "cover",
                                    "open_cover",
                                    { entity_id: "cover.double_garage_door"}
                                  );
                                  hass.callService(
                                    "cover",
                                    "open_cover",
                                    { entity_id: "cover.single_garage_door"}
                                  );
                                ]]]
                          - entity: cover.double_garage_door
                            name: Crack & Closed
                            icon: "emf:garage-dual-closed-cracked"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: nothing
                              multi_calls: |
                                [[[
                                  hass.callService(
                                    "cover",
                                    "close_cover",
                                    { entity_id: "cover.double_garage_door"}
                                  );
                                  hass.callService(
                                    "button",
                                    "press",
                                    { entity_id: "button.single_crack"}
                                  );
                                ]]]
                          - entity: cover.double_garage_door
                            name: Close
                            icon: "emf:garage-dual-closed-closed"
                            type: "custom:button-card"
                            aspect_ratio: 2/1
                            tap_action:
                              action: nothing
                              multi_calls: |
                                [[[
                                  hass.callService(
                                    "cover",
                                    "close_cover",
                                    { entity_id: "cover.double_garage_door"}
                                  );
                                  hass.callService(
                                    "cover",
                                    "close_cover",
                                    { entity_id: "cover.single_garage_door"}
                                  );
                                ]]]
            entity:
            name: Garage
            show_name: true
            show_icon: false
            size: 80%
            styles:
              card:
                - padding: 0.2em
                - "--mdc-ripple-color": yellow
                - "--mdc-ripple-press-opacity": 0.5
                - height: 100%
              icon:
                - opacity: 0.5
                # - max-height: 4.5rem #tweaking the auto-size to prevent vertical inflation of the UI on my wall tablets
              name:
                - font-size: 0.65em
                - white-space: normal
              state:
                - font-size: 0.65em
                - white-space: normal
              label:
                - font-size: 0.4em
                - white-space: normal
              grid:
                - grid-template-areas: '"info" "n"'
                - grid-template-columns: 1fr
                - grid-template-rows: 1fr min-content
              custom_fields:
                info:
                  - opacity: 0.5
            custom_fields:
              info: >
                [[[
                  var colorSingle = '#0000FF';
                  var colorDouble = '#0000FF';

                  if ((states['cover.single_garage_door'].state == 'open') && !(states['sensor.single_garage_door_position'].state == 'Cracked')) {
                    colorSingle = '#00FF00';
                  } else if ((states['cover.single_garage_door'].state == 'open') && (states['sensor.single_garage_door_position'].state == 'Cracked')) {
                    colorSingle = '#FF0000';
                  }


                  if ((states['cover.double_garage_door'].state == 'open') && !(states['sensor.double_garage_door_position'].state == 'Cracked')) {
                    colorDouble = '#00FF00';
                  } else if ((states['cover.double_garage_door'].state == 'open') && (states['sensor.double_garage_door_position'].state == 'Cracked')) {
                    colorDouble = '#FF0000';
                  }
                  
                  var toReturn = '<svg viewBox="0 0 24 24" version="1.1" id="svg67">';
                  toReturn += `<path
                    style="stroke-width:0.715542;fill:var(--primary-text-color)"
                    d="M 7.1992188,6.5 0.80078125,9.6992188 V 18.5 H 2.0800781 V 11.300781 H 12.320312 V 18.5 h 0.0039 v 0.02539 h 1.599609 v -7.199219 h 8 v 7.199219 h 1.59961 V 9.7265625 l -5.59961,-3.2011719 -4.978516,2.8457032 z"
                    id="path65"
                    inkscape:label="garage" />
                      <path
                      style="stroke-width:0.715542;fill:${colorSingle}"
                      d="m 14.724609,12.125 v 1.601562 H 21.125 V 12.125 Z"
                      id="path238"
                      inkscape:label="single-open" />
                    <path
                      style="stroke-width:0.715542;fill:${colorDouble}"
                      d="m 2.7207031,12.099609 v 1.59961 h 8.9589849 v -1.59961 z"
                      id="path236"
                      inkscape:label="double-open" />`

                  if (states['cover.single_garage_door'].state == 'closed') {
                    toReturn += `<path
                          style="stroke-width:0.715542;fill:${colorSingle}"
                          d="m 14.724609,16.925781 v 1.59961 H 21.125 v -1.59961 z"
                          id="path246"
                          inkscape:label="single-closed" />
                          <path
                          style="stroke-width:0.715542;fill:${colorSingle}"
                          d="M 14.724609,14.525391 V 16.125 H 21.125 v -1.599609 z"
                          id="path242"
                          inkscape:label="single-cracked" />`;
                  } else if ((states['cover.single_garage_door'].state == 'open') && (states['sensor.single_garage_door_position'].state == 'Cracked')) {
                    toReturn += `<path
                          style="stroke-width:0.715542;fill:${colorSingle}"
                          d="M 14.724609,14.525391 V 16.125 H 21.125 v -1.599609 z"
                          id="path242"
                          inkscape:label="single-cracked" />`;
                  };


                  if (states['cover.double_garage_door'].state == 'closed') {
                    toReturn += `<path
                          style="stroke-width:0.715542;fill:${colorDouble}"
                          d="M 2.7207031,16.900391 V 18.5 h 8.9589849 v -1.599609 z"
                          id="path244"
                          inkscape:label="double-closed" />
                        <path
                          style="stroke-width:0.715542;fill:${colorDouble}"
                          d="m 2.7207031,14.5 v 1.599609 H 11.679688 V 14.5 Z"
                          id="path240"
                          inkscape:label="double-cracked" />`;
                  } else if ((states['cover.double_garage_door'].state == 'open') && (states['sensor.double_garage_door_position'].state == 'Cracked')) {
                    toReturn += `<path
                          style="stroke-width:0.715542;fill:${colorDouble}"
                          d="m 2.7207031,14.5 v 1.599609 H 11.679688 V 14.5 Z"
                          id="path240"
                          inkscape:label="double-cracked" />`;
                  };


                  return toReturn + '</svg>';
                ]]]

Are you looking for already working custom cards?
If yes, please vote for this feature request.

For anyone interested… built a two car garage into a single button. Made custom SVGs, with states for open/closed/cracked … as well as animated states for opening/closing … The action is a popup that has buttons to control all the states as well as a frigate card from my garage camera. It’s still a work in progress. But pretty fun and cool I think.

type: custom:button-card
tap_action:
  action: fire-dom-event
  browser_mod:
    service: browser_mod.popup
    data:
      title: Single Garage Door
      content:
        type: vertical-stack
        cards:
          - type: custom:frigate-card
            cameras:
              - camera_entity: camera.garage
          - type: horizontal-stack
            cards:
              - entity: cover.single_garage_door
                name: Open
                icon: "emf:garage-single-open"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: cover.open_cover
                  service_data:
                    entity_id: "cover.single_garage_door"
              - entity: cover.single_garage_door
                name: Crack
                icon: "emf:garage-single-cracked"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: button.press
                  service_data:
                    entity_id: "button.single_crack"
              - entity: cover.single_garage_door
                name: Close
                icon: "emf:garage-single-closed"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: cover.close_cover
                  service_data:
                    entity_id: "cover.single_garage_door"
          - type: horizontal-stack
            cards:
              - entity: cover.double_garage_door
                name: Open
                icon: "emf:garage-double-open"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: cover.open_cover
                  service_data:
                    entity_id: "cover.double_garage_door"
              - entity: cover.double_garage_door
                name: Crack
                icon: "emf:garage-double-cracked"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: button.press
                  service_data:
                    entity_id: "button.double_crack"
              - entity: cover.double_garage_door
                name: Close
                icon: "emf:garage-double-closed"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: cover.close_cover
                  service_data:
                    entity_id: "cover.double_garage_door"
          - type: horizontal-stack
            cards:
              - entity: cover.double_garage_door
                name: Open
                icon: "emf:garage-dual-open-open"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: button.press
                  service_data:
                    entity_id: "button.open_both"
              - entity: cover.double_garage_door
                name: Crack & Closed
                icon: "emf:garage-dual-closed-cracked"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: button.press
                  service_data:
                    entity_id: "button.single_crack_and_close_double"
              - entity: cover.double_garage_door
                name: Close
                icon: "emf:garage-dual-closed-closed"
                type: "custom:button-card"
                aspect_ratio: 2/1
                tap_action:
                  action: call-service
                  service: button.press
                  service_data:
                    entity_id: "button.close_both"
entity:
name: Garage
show_name: true
show_icon: false
size: 80%
styles:
  card:
    - padding: 0.2em
    - "--mdc-ripple-color": yellow
    - "--mdc-ripple-press-opacity": 0.5
    - height: 100%
  icon:
    - opacity: 0.5
    # - max-height: 4.5rem #tweaking the auto-size to prevent vertical inflation of the UI on my wall tablets
  name:
    - font-size: 0.65em
    - white-space: normal
  state:
    - font-size: 0.65em
    - white-space: normal
  label:
    - font-size: 0.4em
    - white-space: normal
  grid:
    - grid-template-areas: '"info" "n"'
    - grid-template-columns: 1fr
    - grid-template-rows: 1fr min-content
  custom_fields:
    info:
      - opacity: 0.5
custom_fields:
  info: >
    [[[
      var cssStyleSheet = '';

      var stateColors = {
        'closed': '#0000FF',
        'open': '#00FF00',
        'cracked': '#FF0000',
        'closing': '#FFFF00',
        'opening': '#FF00FF'
      };

      var stateSingle = "unknown";
      if ((states['cover.single_garage_door'].state == 'open') && !(states['sensor.single_garage_door_position'].state == 'Cracked')) {
        stateSingle = "open";
      } else if ((states['cover.single_garage_door'].state == 'open') && (states['sensor.single_garage_door_position'].state == 'Cracked')) {
        stateSingle = "cracked";
      } else if (states['cover.single_garage_door'].state == 'opening') {
        stateSingle = "opening";
      } else if (states['cover.single_garage_door'].state == 'closing') {
        stateSingle = "closing";
      } else if (states['cover.single_garage_door'].state == 'closed') {
        stateSingle = "closed";
      }

      var stateDouble = "unknown";
      if ((states['cover.double_garage_door'].state == 'open') && !(states['sensor.double_garage_door_position'].state == 'Cracked')) {
        stateDouble = "open";
      } else if ((states['cover.double_garage_door'].state == 'open') && (states['sensor.double_garage_door_position'].state == 'Cracked')) {
        stateDouble = "cracked";
      } else if (states['cover.double_garage_door'].state == 'opening') {
        stateDouble = "opening";
      } else if (states['cover.double_garage_door'].state == 'closing') {
        stateDouble = "closing";
      } else if (states['cover.double_garage_door'].state == 'closed') {
        stateDouble = "closed";
      }

      var svgOutline = `<path
        style="stroke-width:0.715542;fill:var(--primary-text-color)"
        d="M 7.1992188,6.5 0.80078125,9.6992188 V 18.5 H 2.0800781 V 11.300781 H 12.320312 V 18.5 h 0.0039 v 0.02539 h 1.599609 v -7.199219 h 8 v 7.199219 h 1.59961 V 9.7265625 l -5.59961,-3.2011719 -4.978516,2.8457032 z"
        id="path65"
        inkscape:label="garage" />`;

      var svgSingleTop = `<path
          style="stroke-width:0.715542;fill:${stateColors[stateSingle]}"
          d="m 14.724609,12.125 v 1.601562 H 21.125 V 12.125 Z"
          id="svgSingleTop"
          inkscape:label="single-open" />`;

      var svgSingleMiddle = `<path
              style="stroke-width:0.715542;fill:${stateColors[stateSingle]}"
              d="M 14.724609,14.525391 V 16.125 H 21.125 v -1.599609 z"
              id="svgSingleMiddle"
              inkscape:label="single-cracked" />`;
      
      var svgSingleBottom = `<path
              style="stroke-width:0.715542;fill:${stateColors[stateSingle]}"
              d="m 14.724609,16.925781 v 1.59961 H 21.125 v -1.59961 z"
              id="svgSingleBottom"
              inkscape:label="single-closed" />`;

      var svgDoubleTop = `<path
          style="stroke-width:0.715542;fill:${stateColors[stateDouble]}"
          d="m 2.7207031,12.099609 v 1.59961 h 8.9589849 v -1.59961 z"
          id="svgDoubleTop"
          inkscape:label="double-open" />`;

      var svgDoubleMiddle = `<path
              style="stroke-width:0.715542;fill:${stateColors[stateDouble]}"
              d="m 2.7207031,14.5 v 1.599609 H 11.679688 V 14.5 Z"
              id="svgDoubleMiddle"
              inkscape:label="double-cracked" />`;

      var svgDoubleBottom = `<path
              style="stroke-width:0.715542;fill:${stateColors[stateDouble]}"
              d="M 2.7207031,16.900391 V 18.5 h 8.9589849 v -1.599609 z"
              id="svgDoubleBottom"
              inkscape:label="double-closed" />`;

      var toReturn = '<svg viewBox="0 0 24 24" version="1.1" id="svg67">';
      toReturn += svgOutline;

      if (stateSingle === 'open') {
        toReturn += svgSingleTop;
      } else if (stateSingle === 'cracked') {
        toReturn += svgSingleTop + svgSingleMiddle;
      } else if (stateSingle === 'closed') {
          toReturn += svgSingleTop + svgSingleMiddle + svgSingleBottom;
      } else if (stateSingle === 'closing') {
        toReturn += svgSingleTop + svgSingleMiddle + svgSingleBottom;

        cssStyleSheet += `<style>
                  @keyframes hideshow {
                    0% { opacity: 1; }
                    25% { opacity: 1; }
                    50% { opacity: 0; }
                    75% { opacity: 0; }
                    100% { opacity: 0; }
                  } 
                  #svgSingleTop {
                    animation: hideshow 4s ease infinite;
                  }
                  #svgSingleMiddle {
                    opacity: 0;
                    animation: hideshow 4s 0.5s ease infinite;
                  }
                  #svgSingleBottom {
                    opacity: 0;
                    animation: hideshow 4s 1.0s ease infinite;
                  }
              </style>`;

      } else if (stateSingle === 'opening') {
        toReturn += svgSingleTop + svgSingleMiddle + svgSingleBottom;

        cssStyleSheet += `<style>
                  @keyframes hideshow {
                    0% { opacity: 1; }
                    25% { opacity: 1; }
                    50% { opacity: 0; }
                    75% { opacity: 0; }
                    100% { opacity: 0; }
                  } 
                  #svgSingleBottom {
                    animation: hideshow 4s ease infinite;
                  }
                  #svgSingleMiddle {
                    opacity: 0;
                    animation: hideshow 4s 0.5s ease infinite;
                  }
                  #svgSingleTop {
                    opacity: 0;
                    animation: hideshow 4s 1.0s ease infinite;
                  }
              </style>`;
      } else {

      }


      if (stateDouble === 'open') {
        toReturn += svgDoubleTop;
      } else if (stateDouble === 'cracked') {
        toReturn += svgDoubleTop + svgDoubleMiddle;
      } else if (stateDouble === 'closed') {
        toReturn += svgDoubleTop + svgDoubleMiddle + svgDoubleBottom;
      } else if (stateDouble === 'closing') {
        toReturn += svgDoubleTop + svgDoubleMiddle + svgDoubleBottom;
      
        cssStyleSheet += `<style>
                  @keyframes hideshow {
                    0% { opacity: 1; }
                    25% { opacity: 1; }
                    50% { opacity: 0; }
                    75% { opacity: 0; }
                    100% { opacity: 0; }
                  } 
                  #svgDoubleTop {
                    animation: hideshow 4s ease infinite;
                  }
                  #svgDoubleMiddle {
                    opacity: 0;
                    animation: hideshow 4s 0.5s ease infinite;
                  }
                  #svgDoubleBottom {
                    opacity: 0;
                    animation: hideshow 4s 1.0s ease infinite;
                  }
              </style>`;
      } else if (stateDouble === 'opening') {
        toReturn += svgDoubleTop + svgDoubleMiddle + svgDoubleBottom;
      
        cssStyleSheet += `<style>
                  @keyframes hideshow {
                    0% { opacity: 1; }
                    25% { opacity: 1; }
                    50% { opacity: 0; }
                    75% { opacity: 0; }
                    100% { opacity: 0; }
                  } 
                  #svgDoubleBottom {
                    animation: hideshow 4s ease infinite;
                  }
                  #svgDoubleMiddle {
                    opacity: 0;
                    animation: hideshow 4s 0.5s ease infinite;
                  }
                  #svgDoubleTop {
                    opacity: 0;
                    animation: hideshow 4s 1.0s ease infinite;
                  }
              </style>`;
      } else {

      }

      return toReturn + cssStyleSheet + '</svg>';
    ]]]

Does anyone know if there is anyway to make an icon flash two different colours?

I can use the below code to make it flash on a certain state, however this is only flashing the icon on and off. But if I wanted to flash between two colours (for example flash between red and green), is there anyway to do that?

Hope that makes sense!

Thanks

    state:
      - value: 1
        styles:
          icon:
            - animation: blink 5s ease infinite

Look above, there was a reference to a dual toggle a few posts up. You can do it using keyframes

Thanks @efaden, I’m not familiar with keyframes, so I’ll check them out.

Look at the post I made above. I use them to animate an SVG.

Can some one give me a hand with the active/background’s variable?
I want to differentiate the active option from the others:

fancard

In this case the activated options are 30º, as the angle, and Normal, as the Mode; but I can’t seem to find the right way to differentiate those from the others…

type: vertical-stack
cards:
  - type: entity
    entity: fan.fan
    state_color: true
    attribute: percentage
    unit: '%'
  - type: horizontal-stack
    cards:
      - show_name: true
        show_icon: true
        type: custom:button-card
        name: 30º
        tap_action:
          action: call-service
          service: script.fan_30
        show_state: false
        color_type: card
        color: rgb(66, 134, 244)
        icon: ''
      - show_name: true
        show_icon: false
        color_type: card
        color: rgb(66, 134, 244)
        type: custom:button-card
        name: 60º
        tap_action:
          action: call-service
          service: script.fan_60
        show_state: false
        icon: ''
      - show_name: true
        show_icon: false
        type: custom:button-card
        name: 90º
        tap_action:
          action: call-service
          service: script.fan_90
        show_state: false
        color_type: card
        color: rgb(66, 134, 244)
        icon: ''
      - show_name: true
        show_icon: false
        type: custom:button-card
        name: 120º
        tap_action:
          action: call-service
          service: script.fan_120
        show_state: false
        color_type: card
        color: rgb(66, 134, 244)
        icon: ''
  - type: horizontal-stack
    cards:
      - show_name: true
        show_icon: true
        type: custom:button-card
        name: Normal
        tap_action:
          action: call-service
          service: script.fan_normal
        show_state: false
        icon: ''
      - show_name: true
        show_icon: true
        type: custom:button-card
        name: Breeze
        tap_action:
          action: call-service
          service: script.fan_breeze
        show_state: false
        icon: ''
  • type: custom:button-card
    show_name: true
    show_icon: true
    show_state: false
    entity: number.lr_hvac_tadiran_set_setpoint
    name: |
    [[[return ‘ok’;]]]
    size: 100%
    color: |
    [[[ return ‘red’;]]]

not showing the red color. what is wrong?
thanks

Is there a way to display the name of the linked room on the place name? In Jinja we can use area_name but I don’t know what the js template of this is.

I have a question concerning the JavaScript templates in this card.
Configuration excerpt:

tmpl_btn_roll:
  variables:
    preset: open # closed, shade, blinds
    set_width: 7 #6.8 #"rem" will be added later
    enty: null #placeholder
  entity: '[[[ return variables.enty ]]]'
  size: 24px
...and so on

Further down the road I want to access an attribute of the entity.
This attribute’s name is provided via the variable preset.
If I try

  styles:
    grid: # div#container.vertical.no-state
      - grid-template: '"i l" auto'
    card: # ha-card#card.button-card-main.type-custom-button-card
      - border-style: >
          [[[ var v_pos = states[variables.enty].attributes.current_position;
              if (v_pos == states[variables.enty].attributes.${variables.preset}) return 'dashed';
              return 'solid'; ]]]

it produces an error: ButtonCardJSTemplateError: SyntaxError: Unexpected token '{' in 'var v_pos = states[variables.enty].attributes.current_position; if (v_pos == states[variables....'

How do I access an attribute which name is changing?

Dug two hours in SO since I didn’t find the right question (I’m absolutely not into JS).
Once I asked the right question, the following answer came up:
if (v_pos == eval("states[variables.enty].attributes." + variables.preset)) return 'dashed';
works, but it uses evil eval()

@Ghafla, try this to avoid eval:

if (v_pos == states[variables.enty].attributes[variables.preset]) return 'dashed';

What’s cool about javascript is you can access properties of an object as if the properties are an array of names. That allows us to access a property from the array by name using a variable.

1 Like

@Ostracizado, take a look at this part of the documentation for the state settings. You can have different visual settings based on state values. Each of your buttons can watch for a specific state and show itself differently.

@mirkin1993, take a look at this part of the documentation for javascript templating

@janiv, please edit your post to put your yaml inside triple-backticks ``` at the start and end so we can see the indentation properly. Also, I think that color setting is the on color and not used when the state is off. There are other places to set color that may work better.