Lovelace: Button card

Welcome to the community. Hope this helps you out.

First you’ll need this plugin installed from the amazing @thomasloven
https://github.com/thomasloven/lovelace-hui-element

Then; click on the 3 dots and Edit Dashboard.
Click on the 3 dots again and select Raw configuration editor.

Then paste this code from the equally amazing @tom_l

button_card_templates:
  red_border:
    aspect_ratio: 4/3
    color_type: icon
    hold_action:
      action: more-info
      haptic: selection
    label: >
      [[[ var bri = entity.attributes.brightness &&
      Math.round(entity.attributes.brightness / 2.55);  if
        (entity.state === 'on') return (bri ? (bri+"%") : 'On'); else return "Off"; ]]]
    layout: icon_label
    show_label: true
    show_name: true
    state:
      - styles:
          card:
            - border: solid 1px red
            - box-shadow: 0px 0px 10px 3px red
          label:
            - color: var(--paper-item-icon-active-color)
        value: 'on'
      - styles:
          card:
            - border: solid 1px var(--primary-color)
            - box-shadow: none
        value: 'off'
      - icon: mdi:alert
        label: Lost
        styles:
          card:
            - border: 'solid 1px #7f7f7f'
            - box-shadow: none
          icon:
            - color: '#ff0000'
            - opacity: 0.4
          label:
            - color: '#7f7f7f'
          name:
            - color: '#7f7f7f'
        value: unavailable
    styles:
      card:
        - border-radius: 10px
        - padding: 6px 6px 6px 6px
        - margin: 0% 0% 0% 0%
        - '--ha-card-background': rgba(0, 0, 0, 0)
      grid:
        - grid-template-areas: '"i l l" "n n n"'
        - grid-template-rows: 33% auto
        - grid-template-columns: 33% auto
      icon:
        - width: 28px
        - padding: 0px 0px 0px 0px
        - color: var(--button-card-light-color-no-temperature)
      label:
        - font-size: 12px
        - justify-self: right
        - padding: 0px 0px 0px 0px
        - color: var(--secondary-text-color)
      name:
        - justify-self: middle
        - align-self: end
        - font-size: 14px
        - padding: 0px 0px 0px 0px
        - color: var(--primary-text-color)
        - white-space: normal
    tap_action:
      action: toggle
      
  light_button:
    aspect_ratio: 4/3
    color_type: icon
    hold_action:
      action: more-info
      haptic: selection
    label: >
      [[[ var bri = entity.attributes.brightness &&
      Math.round(entity.attributes.brightness / 2.55);  if
        (entity.state === 'on') return (bri ? (bri+"%") : 'On'); else return "Off"; ]]]
    layout: icon_label
    show_label: true
    show_name: true
    state:
      - styles:
          card:
            - border: solid 1px var(--button-card-light-color-no-temperature)
            - box-shadow: 0px 0px 10px 3px var(--button-card-light-color-no-temperature)
          label:
            - color: var(--paper-item-icon-active-color)
        value: 'on'
      - styles:
          card:
            - border: solid 1px var(--primary-color)
            - box-shadow: none
        value: 'off'
      - icon: mdi:alert
        label: Lost
        styles:
          card:
            - border: 'solid 1px #7f7f7f'
            - box-shadow: none
          icon:
            - color: '#ff0000'
            - opacity: 0.4
          label:
            - color: '#7f7f7f'
          name:
            - color: '#7f7f7f'
        value: unavailable
    styles:
      card:
        - border-radius: 10px
        - padding: 6px 6px 6px 6px
        - margin: 0% 0% 0% 0%
        - '--ha-card-background': rgba(0, 0, 0, 0)
      grid:
        - grid-template-areas: '"i l l" "n n n"'
        - grid-template-rows: 33% auto
        - grid-template-columns: 33% auto
      icon:
        - width: 28px
        - padding: 0px 0px 0px 0px
        - color: var(--button-card-light-color-no-temperature)
      label:
        - font-size: 12px
        - justify-self: right
        - padding: 0px 0px 0px 0px
        - color: var(--secondary-text-color)
      name:
        - justify-self: middle
        - align-self: end
        - font-size: 14px
        - padding: 0px 0px 0px 0px
        - color: var(--primary-text-color)
        - white-space: normal
    tap_action:
      action: toggle

Make sure it is at the TOP and Save.

ADD the “MANUAL CARD” and paste this code. Change the entities to suit your setup.

entities:
  - type: custom:hui-element
    card_type: horizontal-stack
    cards:
      - entity: switch.meals
        template: light_button
        type: custom:button-card
      - entity: switch.entry
        template: light_button
        type: custom:button-card
      - entity: binary_sensor.garage_motion
        tap_action:
          action: more_info
        template: red_border
        type: custom:button-card
        name: Garage
type: entities


:crossed_fingers: Hopefully no errors and it works :+1:

1 Like

After some (LOTS) of trial and error. Success. A flashing border.

1

Now; to see if I can turn this into a template would be awesome.

The code if anyone is interested. Improvements appreciated too.

type: custom:button-card
name: Garage
state:
  - value: 'on'
    styles:
      card:
        - animation: bgcolorswap 1s linear infinite
extra_styles: |
  @keyframes bgcolorswap {
    0% {
      border: 15px solid rgb(0, 0, 0, 50%);
    }
    25% {
      border: 5px solid rgb(255, 27, 27, 50%);
    }
    50% {
      border: 15px solid rgb(0, 0, 0, 50%);
    }
    75% {
      border: 5px solid rgb(255, 27, 27, 50%);
    }
    100% 
styles:
  card:
    - border: solid 1px var(--primary-color)
tap-action:
  action: more-info
entity: binary_sensor.garage_motion

3 Likes

Way off topic (but as I was quoted… :wink: )
What do you use to create the animated gif of a (partial) screen shot?

https://getsharex.com/

1 Like

3

The template

  red_border:
    aspect_ratio: 4/3
    color_type: icon
    hold_action:
      action: more-info
      haptic: selection
    label: >
      [[[ var bri = entity.attributes.brightness &&
      Math.round(entity.attributes.brightness / 2.55);  if
        (entity.state === 'on') return (bri ? (bri+"%") : 'On'); else return "Off"; ]]]
    layout: icon_label
    show_label: true
    show_name: true
    state:
      - styles:
          card:
            - border: solid 1px red
            - box-shadow: 0px 0px 10px 3px red
          label:
            - color: var(--paper-item-icon-active-color)
      - value: 'on'
        styles:
          card:
            - animation: bgcolorswap 1s linear infinite
    extra_styles: |
      @keyframes bgcolorswap {
        0% {
          border: 3px solid rgb(0, 0, 0, 50%);
        }
        25% {
          border: 3px solid rgb(255, 27, 27, 50%);
        }
        50% {
          border: 3px solid rgb(0, 0, 0, 50%);
        }
        75% {
          border: 3px solid rgb(255, 27, 27, 50%);
        }
        100% {
          border: 3px solid rgb(0, 0, 0, 50%);
        }

      - styles:
          card:
            - border: solid 1px var(--primary-color)
            - box-shadow: none
        value: 'off'
      - icon: mdi:alert
        label: Lost
        styles:
          card:
            - border: 'solid 1px #7f7f7f'
            - box-shadow: none
          icon:
            - color: '#ff0000'
            - opacity: 0.4
          label:
            - color: '#7f7f7f'
          name:
            - color: '#7f7f7f'
        value: unavailable
    styles:
      card:
        - border-radius: 10px
        - padding: 6px 6px 6px 6px
        - margin: 0% 0% 0% 0%
        - '--ha-card-background': rgba(0, 0, 0, 0)
      grid:
        - grid-template-areas: '"i l l" "n n n"'
        - grid-template-rows: 33% auto
        - grid-template-columns: 33% auto
      icon:
        - width: 28px
        - padding: 0px 0px 0px 0px
        - color: var(--button-card-light-color-no-temperature)
      label:
        - font-size: 12px
        - justify-self: right
        - padding: 0px 0px 0px 0px
        - color: var(--secondary-text-color)
      name:
        - justify-self: middle
        - align-self: end
        - font-size: 14px
        - padding: 0px 0px 0px 0px
        - color: var(--primary-text-color)
        - white-space: normal

And the card

entities:
  - type: custom:hui-element
    card_type: horizontal-stack
    cards:
      - entity: binary_sensor.bathroom_motion
        tap_action:
          action: more_info
        template: red_border
        type: custom:button-card
        name: Bathroom
      - entity: switch.living_room
        template: light_button
        type: custom:button-card
      - entity: binary_sensor.garage_motion
        tap_action:
          action: more_info
        template: red_border
        type: custom:button-card
        name: Garage
      - entity: switch.entry
        template: light_button
        type: custom:button-card
type: entities


4 Likes

Thanks for the help !
Unfortunately there is an error. In the Lovelace view the button says " custom element does not exist: hui-element.

You need to add the plugin from the 1st step; that is giving you the error message.

I am trying to create a button which resets a particular filter value on my vacuum based on an input select, but can’t seem to get it right. Hoping someone can give me some tips on how to get this working!

Example using ‘Services’:

service: vacuum.send_command
target:
  entity_id: vacuum.robomac
data:
  command: reset_consumable
  params:
    - sensor_dirty_time

My button code:

              tap_action:
                action: call-service
                service: vacuum.send_command
                target:
                  entity_id: vacuum.robomac
                data_template:
                  command: reset_consumable
                  params: "{{ input_select.robomac_reset }}_time"

Where ‘input_select.robomac_reset’ will be one of the following:

  • sensor_dirty
  • filter
  • main_brush
  • side_brush

try {{states(input_select.robomac_reset)}}_time

No luck Im afraid, this is the error I get when I call it:

I have never used a manual plugin, so probably that is why I made the mistake.
I have only copied the hui-element.js to the www. Folder.
And then ofcourse the other steps
I assume that is not correct ?

I’ll send you a guide to help you out. At “Work” at the moment.

nice wiggle, just found it and added to the templates:

wiggle:
  state:
    - value: 'on'
      styles:
        card:
          - animation: wiggle 0.16s 6
  extra_styles: |
    @keyframes wiggle {
      0% { transform: rotate(0deg); }
      33% { transform: rotate(10deg); }
      66% { transform: rotate(-10deg); }
      100% { transform: rotate(0deg); }
    }

seeing this in the inspector though…

Unhandled Promise Rejection: SyntaxError: Custom element name contains a character that is not allowed

must we ignore, or can we fix…

1 Like

Four things to check:

For jinja tempates, the entity should be in quotes (in this case single quotes within your double quotes as you have it on one line):

"{{ states('input_select.robomac_reset') }}_time"

Secondly, however, I believe this custom card is an exception in that it uses javascript templates, not jinja templates.

Thirdly, I think (but might be wrong) that calling a service from this card uses service_data not data_template. But obviously I can’t test this, so I can’t guarantee this will work at all:

              tap_action:
                action: call-service
                service: vacuum.send_command
                service_data:
                  entity_id: vacuum.robomac
                  command: reset_consumable
                  params: "[[[ return states['input_select.robomac_reset'] + '_time'; ]]]"

Finally, I assume you have confirmed that your robot model actually supports a send_command command called reset_consumable? Not all models can use this service, and even then the commands available for it will vary quite a bit.

TBH I never even noticed.
You are though, the ‘Inspector Inspector’ (apoplogies if the dry humour fails to translate…) so I am hoping now that you can tell me :wink:

1 Like

Quotes, of course! + JS instead of jinjia2

getting close! It’s not spitting up any errors but its not resetting either. I can confirm my vacuum supports it as I was able to reset the dirt sensor using the ‘Services’ section perfectly fine.

I had to update my input selects to match the instructions below, but the code I am using below (also tried with a ; as shown) doesn’t seem to reset anything.

              tap_action:
                action: call-service
                service: vacuum.send_command
                service_data:
                  entity_id: vacuum.robomac
                  command: reset_consumable
                  params: "[[[ return states['input_select.robomac_reset'] + '_time' ]]]"

So I think it is running the command ok but passing incorrect parameters???

Ok its definitely the passing of the parameters causing the issue, as this works below to reset the filter:

             tap_action:
                action: call-service
                service: vacuum.send_command
                service_data:
                  entity_id: vacuum.robomac
                  command: reset_consumable
                  params: ['filter_work_time']

Does anything about incorrect parameters show in the Home Assistant logs when you press the button?

I think the yaml is expecting the parameter to be passed as a list within square brackets, but I’m getting to the limits of my JavaScript knowledge here, so not sure how that can be done.