Fun with custom:button-card

You could also use the localize feature for sun and moon:


show_label: true
label: |
  [[[
   let x = states['sun.sun']
   return helpers.localize(x);
  ]]]

or if entity == label entity:

label: |
  [[[ return helpers.localize(entity); ]]]

If the moon pics are named the same as the moon states, the entity picture part can be shortened using


show_entity_picture: true
entity_picture: |
  [[[ return `/local/images/moon/${entity.state}.png`; ]]]

Only the 1st character of the state is capitalized…
image

I managed to figure out what I wanted to achieve though by using state_display: plus I decided to switch the state_display: and label: usage…

type: custom:button-card
aspect_ratio: 1/0.6
show_name: true
show_state: true
show_label: true
entity: sensor.moon
styles:
  card:
    - color: |
        [[[
         if (states['sun.sun'].state == 'below_horizon') 
          return "white";
         else return "darkblue";
        ]]]
    - background-color: |
        [[[
         if (states['sun.sun'].state == 'below_horizon') 
          return "black";
         else return "cyan";
        ]]]
name: "Moon Phase"
state_display: |
      [[[
       if (states['sensor.moon_phase'].state == 'new_moon') return "New Moon";
       if (states['sensor.moon_phase'].state == 'waxing_crescent') return "Waxing Crescent";
       if (states['sensor.moon_phase'].state == 'first_quarter') return "First Quarter";
       if (states['sensor.moon_phase'].state == 'waxing_gibbous') return "Waxing Gibbous";
       if (states['sensor.moon_phase'].state == 'waning_gibbous') return "Waning Gibbous";
       if (states['sensor.moon_phase'].state == 'last_quarter') return "Last Quarter";
       if (states['sensor.moon_phase'].state == 'waning_crescent') return "Waning Crescent";
       else return "Full Moon"
      ]]]
label: |
  [[[
    if (states['sensor.moon'].state == 'below_horizon') 
      return "(Below Horizon)";
    else return "(Above Horizon)";
  ]]]
entity_picture: |
  [[[ return `/local/images/moon/${entity.state}.jpg`; ]]]
show_entity_picture: true

image

That is because it thinks below_horizion is one word. Glad you found a solution!

One more tweak…

image

type: custom:button-card
aspect_ratio: 1/0.6
show_name: true
show_state: true
show_label: true
entity: sensor.moon_phase
styles:
  card:
    - text-transform: capitalize
    - color: |
        [[[
         if (states['sun.sun'].state == 'below_horizon') 
          return "white";
         else return "darkblue";
        ]]]
    - background-color: |
        [[[
         if (states['sun.sun'].state == 'below_horizon') 
          return "black";
         else return "lightblue";
        ]]]
name: Moon Phase
label: |
  [[[
   return states['sensor.moon'].state.replace('_',' ');
  ]]]
entity_picture: |
  [[[ return `/local/images/moon/${entity.state}.jpg`; ]]]
show_entity_picture: true
1 Like

I’m quite enamored with this, and would like to replicate exactly. Can you provide links to the images you used for your card? Thank you!

The zip file is in this post.

1 Like

Thank you very much!

1 Like

If I have a template for a room card that for the sub-buttons takes a bunch of variables can I pass a template as a variable? For example

in variables

          entity_2:
            entity_id: switch.esph_shelly_1_fr_fireplace_relay
            icon: mdi:fireplace
            templates:
              - red_on
            tap_action:
              action: toggle

Is it possible to pass a template into variable? E.g.
if (entity = on) mdi:fireplace-on else mdi-fireplace

Or something like that?

This thread is for custom:button-card. You only posted a very brief snippit of your card config so I’m only guessing this question should be posted in Custom card: Room Card?

But regardless of that, the room card wiki shows:

type: custom:room-card
entity: sensor.fordpass_ignitionstatus
icon: mdi:car
show_icon: true
info_entities:
  - entity: sensor.fordpass_fuel
    show_icon: true
    icon:
      template:
        styles: >
          if (entity.state >= 70) return 'color: green';  
          if (entity.state >= 20) return 'color: orange';  
          else return 'color: orangered';
        icon: >
          if (entity.state >= 70) return 'mdi:car';  
          if (entity.state >= 20) return 'mdi:carplus';  
          else return 'mdi:carplus2';

Does something like this work?

entity_2:
  entity_id: switch.esph_shelly_1_fr_fireplace_relay
  icon:
    template:
      icon: >
        if (entity.state == 'on') return 'mdi:fireplace-on';  
        else return 'mdi:fireplace';
  templates:
    - red_on
  tap_action:
    action: toggle

I’m trying to use the internal variables of the card to set the variables the card will eventually pass towards a service. I.e. filling out the service_data fields using the button card as a ui, without needing to make helpers whose state would be used to pass the options. Which would also mean the settings are specific for a browser instance, which in the case of some custom scripts I use make more sense, as using helpers for this means the helpers need to be reset after a certain amount of time too.

Anyhow, preamble aside, where I got stuck on was performing javascript code inside custom fields, using the variables of the card itself. custom fields that are html elements are able to perform scripts, however they do not have access to the variables variable, which the card does pass to javascript snippets within configurations. My current test setup is this:

type: custom:button-card
variables:
  test_var: false
custom_fields:
  html-field: |
    [[[ return `<ha-icon
          icon="mdi:mouse-left-click"
          style="height: 40%; margin-bottom: -2.5%;" onclick="console.log('tapped the icon');">
          </ha-icon><p><span style="font-size: 500%;">front html</span>` ]]] 
  frt:
    card:
      type: custom:button-card
      variables:
        c: 42
      name: front card
      icon: mdi:test-tube
      tap_action:
        action: |
          [[[ console.log("tapped the front button?");
              variables.test_var = !(variables.test_var);
              return 'nope';
          ]]]
styles:
  grid:
    - grid-template-areas: '"frt right back left"'
    - grid-template-columns: 1fr 1fr 1fr 1fr
  custom_fields:
    html-field:
      - background-color: steelblue
      - border-radius: 0%
      - position: absolute
      - top: 10%
      - height: 190%
      - width: 100%
      - font-size: 8px
      - line-height: 20px
      - icon: mdi:mouse-left-click
    frt:
      - height: 190%
      - width: 500%
icon: mdi:nuke
name: test
tap_action:
  action: |
    [[[
      console.log(`test_var = ${variables.test_var}`);
      console.log("Tapped the main button!");

      variables.test_var = !(variables.test_var);
    ]]]

Checking the console log in my browser shows that upon loading, all javascript codes are performed. However, afterwards, only clicking on the html field triggers the on click action in the html element, as well as the tap_action of the main button. This shows that test_var does indeed toggle on each click. However, clicking on the frt custom field does not trigger the javascript code. It does read out the returned value, however (i.e. setting it to return "more-info"; throws an error saying no entity-id has been specified. However the other parts of the script are not performed. Nothing is logged in the console, nor is the variable changed. Is it possible for the action to still perform these parts of the code as well?

I’m not sure if what I’m trying is even possible, as it may be a bit too hacky (which would explain why it won’t work), but maybe someone here actually has an idea of what to do.

Sorry. Not talking about room card, but talking about a template for button card. I thought I included more of the template. Here is a fuller example. Notice how the icon for the i1 custom field is passed through as a variable? I am trying to figure out if I can pass through a template instead of just a single icon. If the entity is on, then one icon and if it is off another. But it doesn’t really seem to work. So my question was if it is possible to pass a template like that as a variable to a custom field. Does that make more sense?

My end goal is to make a room card style template and then use that template. But for something like the fireplace I want to have an icon with the flame if its on and without if it is off. But I am struggling to pass the if/else through as a variable to a template.

Template:

example_template:
  icon: "mdi:sofa-single"
  ....
  custom_fields:
    i1:
      card:
        type: "custom:button-card"
        template: >
          [[[
            let templates = [ 'widget_icon_room_8' ];
            if (variables?.entity_1?.templates?.length) {
              templates.push(...variables.entity_1.templates);
            }
            return templates;
          ]]]
        variables: "[[[ return variables?.entity_1; ]]]"
        state:
          - operator: "template"
            value: "[[[ return !variables.entity_1; ]]]"
            styles:
              card:
                - display: "none"
        entity: "[[[ return variables?.entity_1?.entity_id; ]]]"
        icon: "[[[ return variables?.entity_1?.icon; ]]]"
        styles:
          mwc-ripple:
            - display: "none"

Usage:

      - type: "custom:button-card"
        template:
         - example-template
        ....
        variables:
          label_use_temperature: true
          label_use_brightness: false
          label_use_temperature_entity: "sensor.family_room_temperature"
          entity_1:
            entity_id: switch.zb_family_room_lamps
            icon: mdi:lamps
            tap_action:
              action: toggle
          entity_2:
            entity_id: switch.esph_shelly_1_fr_fireplace_relay
            icon: mdi:fireplace
            tap_action:
              action: toggle

Have you considered using custom-ui to customize the icons?

show_name: true
show_icon: true
type: custom:button-card
tap_action:
  action: toggle
entity: switch.2ch_relay_right

imageimage

configuration.yaml:

homeassistant:
  customize: !include customize.yaml

customize.yaml:

switch.2ch_relay_right:
  templates:
    icon: "return state === 'off' ? 'mdi:fireplace-off' : 'mdi:fireplace';"
    icon_color: "return state === 'off' ? 'grey' : 'gold';"

Note: custom:button-card uses my custom-ui templated icon but does not use my templated icon_color which is likely related to this note in the docs:

By default, if the entity state is off , the color will be var(--paper-item-icon-color) , for on it will be var(--paper-item-icon-active-color) and for any other state it will be var(--primary-text-color).

The standard button card applies both custom-ui templates:
imageimage

Honestly no, I hadn’t because I had never heard of it. Lol. That looks like a very interesting way to go though. Thanks I’ll do some reading tonight. Although it seems development has stopped…

@efaden No, not @Mariusthvdb’s version!

You can find the repository here.

There are numerous references to it here in the community but not sure if there’s a primary topic for it.

Thanks! I’ll check it out. I’m also thinking of just notifying the template to include an on and off icon.

Interesting update, was able to solve my own issue.

This doesn’t work.

        variables:
          entity_1:
            entity_id: switch.zb_family_room_lamps
            icon: mdi:lamps
            tap_action:
              action: toggle
          entity_2:
            entity_id: switch.esph_shelly_1_fr_fireplace_relay
            icon: >
              [[[
                let state = states['variables.entity_2_entity_id'].state; // BAD
                if (state == "on")
                  return "mdi:fireplace";
                else
                  return "mdi:fireplace-off";
              ]]]

but this does…


         variables:
          entity_1:
            entity_id: switch.zb_family_room_lamps
            icon: mdi:lamps
            tap_action:
              action: toggle
          entity_2:
            entity_id: switch.esph_shelly_1_fr_fireplace_relay
            icon: >
              [[[
                let state = states['switch.esph_shelly_1_fr_fireplace_relay'].state;
                if (state == "on")
                  return "mdi:fireplace";
                else
                  return "mdi:fireplace-off";
              ]]]
            tap_action:
              action: toggle
let state = states['variables.entity_1_entity_id'].state;

Also works within entity_2 (not useful, but interesting). So it looks like entity_2 is evaluated all at one go, and nothing within it is available within the sub items.

Turns out even though entity_id is alphabetically before icon in the above example it is still undefined in the icon field. This was my issue.

Interesting. I understand now.

I wonder if variables can reference other variables though?
Like this…

variables:
          switch_1: switch.zb_family_room_lamps
          switch_2: switch.esph_shelly_1_fr_fireplace_relay

          entity_1:
            entity_id: variables.switch_1
            icon: mdi:lamps
            tap_action:
              action: toggle

          entity_2:
            entity_id: variables.switch_2
            icon: 
              [[[
                let state = states['variables.switch_2'].state;
                if (state == "on")
                  return "mdi:fireplace";
                else
                  return "mdi:fireplace-off";
              ]]]

I think you would have to use a_switch1, etc. Reason is that they are processed alphabetically. …

Maybe this then?

variables:
          a1: switch.zb_family_room_lamps
          a2: switch.esph_shelly_1_fr_fireplace_relay

          entity_1:
            entity_id: variables.a1
            icon: mdi:lamps
            tap_action:
              action: toggle

          entity_2:
            entity_id: variables.a2
            icon: 
              [[[
                let state = states['variables.a2'].state;
                if (state == "on")
                  return "mdi:fireplace";
                else
                  return "mdi:fireplace-off";
              ]]]

Yeah. That should work. I’ll test it later…