Lovelace: Button card

remove height and margin from the card style. more specifically, margin is pushing it. You can probably keep height. But typically if you want buttons that are the same size, use ratio don’t use height. Height will make the button look weird on specific platforms. May look great on mobile but then on desktop it’ll look small.

You’ll have to specify what happens for the unavailable state:

color: auto
entity: light.08836146600194dc5165
icon: 'mdi:lamp'
name: Trent
type: 'custom:button-card'
state:
  - value: unavailable
    color: THE_COLOR_YOU_WANT

Okey, but how do get them located example 30px away from the edge and with 30px gap between them?
I don’t want them to collide or get the glow to be cut off by the edge…

image

You have to use card-mod to change the margin between elements on the horizontal-stack not on button-card.

Can you please give me an example with 3 buttons that are separated ?
I do not understand how to use card-mod based on the examples that I can find.
Thanks !

So here’s a little hack for those who want to have feedback on tap (works for hold and double_tap) (cc: @petro). However, it doesn’t work well if the entity of the card is updated before the animation is finished :smiley:

        tap_action:
          action: call-service
          always_execute: | # The key can be anything, but not a official documentation value
            [[[
              this.shadowRoot.getElementById('card').style.background = "COLOR_ON_CLICK";
              window.setTimeout(() => {
                this.shadowRoot.getElementById('card').style.background = "COLOR_YOU_WANT_UNCLICKED"; // if your color is different based on the state, well, you'll have to handle it here or use css variables :)
              }, 500)
            ]]]

You can use that hack for anything else also that you want to execute on tap/double_tap/hold :slight_smile:

I’m using it to do this for example:
Apr-25-2020 17-00-07

      - type: custom:button-card
        show_icon: true
        icon: mdi:skip-next
        size: 100%
        color: rgba(255, 255, 255, 0.8)
        styles:
          card:
            - background: none
            - box-shadow: none
          icon:
            - transition: all 1s ease-in-out
            - opacity: 0
        tap_action:
          action: call-service
          service: media_player.media_next_track
          service_data:
            entity_id: media_player.sonos_connect
          always_execute: |
            [[[
              this.shadowRoot.getElementById('icon').style.opacity = 1;
              window.setTimeout(() => {
                this.shadowRoot.getElementById('icon').style.opacity = 0;
              }, 1000)
            ]]]
4 Likes

Hey cool. I got a new phone so I have haptic feedback now. This requirement is a thing of the past! I was using an iphone 5 for the longest time…

Anyways, I can see a use for it in other areas, thanks!

What did you do to get the background to display the graph for a sensor card? Are you leveraging the html objects?

EDIT: You have to be, I’m guessing you have that positioned in the center in the with a low z order?

EDIT: The only thing I can see you doing is using hui-graph-base but you feed it coordinates that you calculate.

LAST EDIT: FFS, I didn’t notice you built in the ability to embed cards… been on a damn wild goose chase looking through the code. Should have checked the docs sooner :man_facepalming:

Actually, I’m using a picture-elements with a button-card and a mini-graph-card inside (it is a decluttering-card template)

square_numeric_sensor_with_graph:
  defaults:
    - entity:
    - name:
  card:
    type: picture-elements
    image: /local/Transparent_Square.png
    elements:
      - type: custom:mini-graph-card
        style:
          top: 40%
          left: 50%
          width: 100%
          height: 80%
          translate: translate(-50%, -50%)
        entities:
          - '[[entity]]'
        group: true
        points_per_hour: 1
        line_color: rgba(255, 255, 255, 0.8)
        hour24: true
        line_width: 10
        hours_to_show: 24
        update_interval: 600
        show:
          name: false
          icon: false
          state: false
          points: false
          legend: false
          average: false
          extrema: false
          labels: false
          fill: false
          labels_secondary: false
          name_adaptive_color: false
          icon_adaptive_color: false
      - type: custom:button-card
        style:
          top: 50%
          left: 50%
          width: 100%
          translate: translate(-50%, -50%)
        template: square_base_numeric_sensor
        entity: '[[entity]]'
        name: '[[name]]'

(Edit: Would have used the card inside button-card but it would refresh the whole graph everytime. I need to improve that on the button-card)

I’m almost there with the button card. Much larger config that yours… but it’s almost done.

what do you mean refresh the whole graph? If you use a embedded sensor card it refreshes the whole graph?

I have this so far

  - type: custom:button-card
    aspect_ratio: 1/1
    entity: sensor.cpu_temperature
    show_name: true
    show_label: true
    show_last_changed: true
    styles:
      grid:
      - grid-template-areas: '"info" "graph" "n" "l" "i" "s"'
      - grid-template-rows: 1fr min-content min-content min-content min-content min-content
      card:
      - border-radius: 15px
      - padding: 10px 0px
      name:
      - justify-self: start
      - align-self: end
      - font-weight: bold
      - font-family: Helvetica 
      - font-size: 12px
      - text-align: start
      - background-image: linear-gradient(to right, var(--paper-item-icon-color) 0%, var(--paper-item-icon-color) 80%, rgba(0,0,0,0))
      - -webkit-background-clip: text
      - -webkit-text-fill-color: transparent
      - position: relative
      - display: inline-block
      - width: calc(100% - 20px)
      - align-content: start
      - text-align: start
      - text-overflow: unset
      - padding: 0px 10px
      label:
      - justify-self: start
      - align-self: end
      - font-family: Helvetica 
      - font-size: 11px
      - text-align: start
      - background-image: linear-gradient(to right, var(--paper-item-icon-color) 0%, var(--paper-item-icon-color) 80%, rgba(0,0,0,0))
      - -webkit-background-clip: text
      - -webkit-text-fill-color: transparent
      - position: relative
      - display: inline-block
      - width: calc(100% - 20px)
      - align-content: start
      - text-align: start
      - text-overflow: unset
      - padding: 0px 10px
      custom_fields:
        info:
        - align-self: start
    custom_fields:
      info: >
        [[[
          return `
            <svg viewBox="0 0 50 50"
              <circle cx="25" cy="25" r="20.5" fill="var(--paper-item-icon-color)" stroke="none" />
            </svg>
            `;
        ]]]
      graph:
        card:
          type: custom:mini-graph-card
          style: |
            .graph { padding: 0px; }
            .flex { padding: 0px; }
          entities:
          - sensor.cpu_temperature
          show:
            fill: false
            name: false
            icon: false
            state: false

Looks like:

image

1 Like

Yes everytime on of the entity of the button-card is updated, it would recreate the whole mini-graph-card instead of reusing the current one thus introducing some glitches.

ah ok, maybe I’ll switch then.

Wait so how does that work with aspect ratio and a series of buttons next to each other? Ah never mind, I see the work around with the transparent square image.

:tada::tada: Version 3.3.1 :tada::tada:

Breaking Change

  • triggers_update is a new field that enables you to define which entities should trigger an update of the card itself (this rule doesn’t apply for nested cards in custom_fields as they are always updated with the latest state. This is expected and fast!). Before 3.3.0, if you were using javascript [[[ ]]] templates, the card would update itself everytime ANY entity was updated in HA introducing a lot of load on the browser.
    If you don’t have javascript [[[ ]]] templates in your config, you don’t need to do anything, else read further.
    If unset, the card will parse your code and look for entities that it can match (it only matches states['ENTITY_ID']) so:
     return states['switch.myswitch'].state // will match switch.myswitch
     // but
     const test = switch.myswitch
     return states[test].state // will not match anything
    
    In this second case, you have 2 options:
    • Set the value of triggers_update to all (This was the behavior of button-card < 3.3.0)
      triggers_update: all
      
    • Set the value of triggers_update to a list of entities. When any of the entities in this list is updated, the card will be updated. The logic is the same as the internal home-assistant * templates integration (see here for example):
      type: custom:button-card
      entity: sensor.mysensor # No need to repeat this one in the triggers_update, it is added by default
      triggers_update:
        - switch.myswitch
        - light.mylight
      

New Features

  • Supports defining multiple button template:
    type: custom:button-card
    template:
      - template1
      - template2
    
    The button templates will be applied in the order they are defined: template2 will be merged with template1 and then the local config will be merged with the result. You can still chain templates together (ie. define template in a button-card template. It will follow the path recursively).
  • The card will display an error on screen instead of just disappearing from your layout when an error occurs. If it is an error in your javascript templates, it will display an error card with ButtonCardJSTemplateError and display the beginning of your template so that you can identify it:
    image

BugFixes

  • The button might not have been clickable in some cases when the action of a *_action was a template.
  • Nested cards should be updated properly now when there is a state change.
  • Fixes when a timer entity was defined and the button was in a vertical-stack/horizontal-stack
  • Fix for button-card using templates not working in Lovelave panels when casting

Other stuff

  • A lot of refactor in the code, I hope I didn’t break too much things :smile:
2 Likes

Hi guys,
I’m trying to figure it out how to toggle my sonoff we the yeelight is unavailable.
is it possible to use templates on tap_action in order to change the identity_id to toggle based on a states attribute?

Something like this:

- type: "custom:button-card"
  entity: light.yeelight_lampadario
  name: Light name
  template: light_button
  icon: "mdi:globe-light"
  tap_action:
    action: call-service
    service: homeassistant.toggle
    service_data:
      entity_id: >
        [[[
          if (states['light.yeelight_lamp'].state == "unavailable")
            return switch.sonoff_lamp;
          return light.yeelight_lamp;
        ]]]

(this in not working) :frowning:

the overall idea is to toggle the sonoff_switch when the yeelight lamp is unavailable.

Thanks Mark

You are missing the quotes:

- type: "custom:button-card"
  entity: light.yeelight_lampadario
  name: Light name
  template: light_button
  icon: "mdi:globe-light"
  tap_action:
    action: call-service
    service: homeassistant.toggle
    service_data:
      entity_id: >
        [[[
          if (states['light.yeelight_lamp'].state == "unavailable")
            return "switch.sonoff_lamp";
          return "light.yeelight_lamp";
        ]]]

damn quotes… now is working perfectly…
Sorry… :slight_smile:

Thanks

Hi,

Your “Covers” header has 3 icons, how did you do that?

Thanks,
Jon

It’s 4 buttons embedded in a stack-in-card

        - type: custom:stack-in-card
          mode: horizontal
          cards:
            - type: custom:button-card
              template: header_with_other_stuff
              name: Covers
            - type: custom:button-card
              template: header_icon_middle
              icon: mdi:arrow-up-thick
              tap_action:
                action: call-service
                service: cover.open_cover
                service_data:
                  entity_id: cover.all_covers
            - type: custom:button-card
              template: header_icon_middle
              icon: mdi:stop
              tap_action:
                action: call-service
                service: cover.stop_cover
                service_data:
                  entity_id: cover.all_covers
            - type: custom:button-card
              template: header_icon_end
              icon: mdi:arrow-down-thick
              tap_action:
                action: call-service
                service: cover.close_cover
                service_data:
                  entity_id: cover.all_covers