Fun with custom:button-card

Yep, used the eather weekend with covid lockdown to play with the button cards.
Beside the actors I still wanted to group my sensors. And it ended up in a smartphone-alike screen per room … thanks to the fact that a using % on a rectangle button card does these fancy curves :slight_smile:

In detail it’s a CB per room with nothing in in but several CBs for each entity. (so that I could make use of more-info from all of these.

Though it might fit in here “fun with …” and yeah I had lots of fun.
Especially getting the windrose done which I wanted to rotate against having the directions arrow running around in cicles. Was a bit painful to get this going using custom:canvas-gauge since placement with inthe CB was very strange for me.

Impressive array of charts! The wind gauge looks interesting. What are you using to get all of those measurements, like wifi strength in each room?

Had a handfull of ESP8266 mini d1 boards lying around and added some bme280 sensors and some other sensors. Currently I’m after this idea: https://www.thingiverse.com/thing:3860911 but it’s a bit tricky to get correct values back from the watermeter.

For the number of charts. I tried the same using apexcharts first since they do look more impressive but this brought my pi4 to it’s knees after 10 charts side by side.

Could be because I’m still a HA noob not really understanding about the advantages of lovelace: YAML mode and !include. Means the code is a real pain, and I must read lots more to prevent redundancy of codeblocks.

As said ealier, the windgauge was a real pain since that custom:canvas-gauge things did show a complete different behaviour as other objects with the buttoncard when it comes to getting this into the expected position. Looks as if my brains too short to get it why this happens.

Could someone help me, please? I can NOT finger out how to add an image to my button. I want to add /local/image/me_g3-1.png in the middle of the person’s name and their current location.

type: 'custom:button-card'
entity: person.g3_1
aspect_ratio: 1/1
name: null
icon: null
styles:
  card:
    - background-color: transparent
    - border-radius: 10%
    - padding: 4%
    - color: ivory
    - font-size: 10px
    - text-shadow: 0px 0px 5px black
    - text-transform: capitalize
  grid:
    - grid-template-areas: '"n n" "i i" "location location" "battery battery" "power power"'
    - grid-template-columns: 1fr 1fr
    - grid-template-rows: 1fr min-content min-content min-content min-content
  name:
    - margin-top: '-70'
    - font-weight: bold
    - font-size: 13px
    - color: white
    - align-self: start
    - justify-self: middle
  img_cell:
    - justify-content: start
    - align-items: start
    - margin: none
  icon: null
  custom_fields:
    location:
      - font-size: 12px
      - color: white
      - align-self: null
      - justify-self: null
      - padding-bottom: 4px
    power:
      - entity: device_tracker.g3_1_iphone_12_pro_max_2
      - align-self: middle
      - justify-self: start
    battery:
      - padding-bottom: 2px
      - align-self: middle
      - justify-self: start
      - '--text-color-sensor': >-
          [[[ if (states["sensor.g3_1_iphone_12_pro_max_battery_state_2"].state
          < 20) return "red"; ]]]
custom_fields:
  location: |
    [[[
      return `</ha-icon><span> ${entity.state}</span>`
    ]]]
  power: |
    [[[
      return `<ha-icon
        icon="mdi:battery-charging"
        style="width: 12px; height: 12px; color: deepskyblue;">
        </ha-icon><span>: ${states['device_tracker.g3_1_iphone_12_pro_max_2'].attributes.battery_status} </span>`
    ]]]
  battery: |
    [[[
      return `<ha-icon
        icon="mdi:battery"
        style="width: 12px; height: 12px; color: deepskyblue;">
        </ha-icon><span> : <span style="color: var(--text-color-sensor);">${states['device_tracker.g3_1_iphone_12_pro_max_2'].attributes.battery_level}%</span></span>`
    ]]]

@G3GhostTech, you probably need another custom field and use that instead of “i i” in the grid-template-areas.

I noticed all of your grid-template-areas are doubled up, so you essentially have just one column and can remove the duplicate names: '"n" "i" "location" "battery" "power"'.

1 Like

why do you keep posting in this thread, while there is a huge thread with so many more people to help and get inspiration from? Not saying you shouldn’t, it just that the other thread has all the examples you would need to get you all going.

I know I am doing some basic wrong. I have put this into my raw configuration but am getting this error:

Button-card template 'container' is missing!

This is the config. I am fairly new to dashboards with HA so I am quite certain it is probably something in the wrong place sort of thing. Any help would be appreciated. Of course I truncated the config to just enough to show the error.

Thanks!

title: Home
template:
  button_card_templates:
    container:
      color_type: label-card
      color: dimgray
      styles:
        card:
          - padding: 0
        name:
          - border-radius: 0.4em 0.4em 0 0
          - padding: 0.1em
          - width: 100%
          - font-weight: bold
        grid:
          - grid-template-areas: '"i" "n" "buttons"'
          - grid-template-columns: 1fr
          - grid-template-rows: 1fr min-content min-content
        custom_fields:
          buttons:
            - background-color: 'rgba(0,0,0,0.3)'
            - margin: 0
            - padding: 0.3em
views:
  - path: default_view
    title: Home
    cards:
      - type: 'custom:button-card'
        template: container
        color: '#EDE7B0'
        name: Eating & Patio
        custom_fields:
          buttons:
            card:
              type: horizontal-stack
              cards:
                - entity: switch.ge_14291_in_wall_smart_switch_switch_2
                  name: Kitchen
                  template: standard
                  icon: 'mdi:wall-sconce-flat'
                  type: 'custom:button-card'

Do you have the first section that begins with “button card templates:”? It’s something like this and is at the very beginning of your Lovelace raw config.

button_card_templates:
  standard:
    color_type: card
    size: 80%
    hold_action:
      action: more-info
    styles:
      card:
        - padding: 0.2em
        - '--mdc-ripple-color': yellow
        - '--mdc-ripple-press-opacity': 0.5
      icon:
        - opacity: 0.75
      name:
        - font-size: 0.5em
        - white-space: normal
      state:
        - font-size: 0.5em
        - white-space: normal
      label:
        - font-size: 0.5em
        - white-space: normal
  wide:
    template: standard
    styles:
      grid:
        - position: relative
        - grid-template-areas: '"i n"'
        - grid-template-columns: 1fr 1fr
        - grid-template-rows: 1fr
  container:
    color_type: label-card
    color: dimgray
    styles:
      card:
        - padding: 0
      name:
        - border-radius: 0.4em 0.4em 0 0
        - padding: 0.0em
        - width: 100%
        - font-weight: bold
        - font-size: 0.6em
      grid:
        - grid-template-areas: '"i" "n" "buttons"'
        - grid-template-columns: 1fr
        - grid-template-rows: 1fr min-content min-content
      custom_fields:
        buttons:
          - background-color: 'rgba(0,0,0,0.3)'
          - margin: 0
          - padding: 0.15em
  standard-button:
    template: standard
    variables:
      value_on: 'on'
      value_off: 'off'
      background_color_on: gold
      background_color_off: slategrey
      text_color_on: blue
      text_color_off: white
    styles:
      label:
        - color: '[[[ return variables.text_color_off ]]]'
    state:
      - id: value_on
        value: '[[[ return variables.value_on ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_on ]]]'
          name:
            - color: '[[[ return variables.text_color_on ]]]'
          icon:
            - color: '[[[ return variables.text_color_on ]]]'
            - opacity: 1
      - id: value_off
        value: '[[[ return variables.value_off ]]]'
        styles:
          card:
            - background-color: '[[[ return variables.background_color_off ]]]'
          name:
            - color: '[[[ return variables.text_color_off ]]]'
          icon:
            - color: '[[[ return variables.text_color_off ]]]'
            - opacity: 0.5
  option-button:
    template: standard
    show_icon: false
    aspect_ratio: 1/1
    styles:
      card:
        - border-radius: 20%
  dimmer-option:
    template: option-button
    tap_action:
      action: call-service
      service: light.turn_on
      service_data:
        entity_id: entity
        brightness: '[[[ return variables.set_value ]]]'
    state:
      - operator: default
        styles:
          card:
            - background-color: '[[[ return variables.option_button_off_color ]]]'
            - color: '[[[ return variables.option_text_off_color ]]]'
      - operator: template
        value: >-
          [[[ return (entity.attributes.brightness||0) >= variables.range_start
          && (entity.attributes.brightness||0) <= variables.range_stop ]]]
        styles:
          card:
            - background-color: '[[[ return variables.option_button_on_color ]]]'
            - color: '[[[ return variables.option_text_on_color ]]]'
  presets:
    template: standard
    color_type: icon
    tap_action:
      action: none
    styles:
      card:
        - background-color: 'rgba(0,0,0,0.3)'
      icon:
        - color: white
      grid:
        - grid-template-areas: '"i opt1 opt2 opt3 opt4" "n opt1 opt2 opt3 opt4"'
        - grid-template-columns: 1fr 1fr 1fr 1fr 1fr
      custom_fields:
        opt1:
          - margin: 0.1em
          - overflow: visible
        opt2:
          - margin: 0.1em
          - overflow: visible
        opt3:
          - margin: 0.1em
          - overflow: visible
        opt4:
          - margin: 0.1em
          - overflow: visible
    variables:
      option_template: dimmer-option
      option_button_on_color: var(--paper-item-icon-active-color)
      option_text_on_color: white
      option_button_off_color: var(--paper-card-background-color)
      option_text_off_color: white
      option1_name: Low
      option1_set_value: 51
      option1_range_start: 1
      option1_range_stop: 77
      option2_name: Med
      option2_set_value: 102
      option2_range_start: 78
      option2_range_stop: 170
      option3_name: High
      option3_set_value: 255
      option3_range_start: 171
      option3_range_stop: 255
      option4_name: 'Off'
      option4_set_value: 0
      option4_range_start: 0
      option4_range_stop: 0
    custom_fields:
      opt1:
        card:
          type: 'custom:button-card'
          entity: '[[[ return variables.entity ]]]'
          template: '[[[ return variables.option_template ]]]'
          name: '[[[ return variables.option1_name ]]]'
          variables:
            set_value: '[[[ return variables.option1_set_value ]]]'
            range_start: '[[[ return variables.option1_range_start ]]]'
            range_stop: '[[[ return variables.option1_range_stop ]]]'
            option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
            option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
            option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
            option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
      opt2:
        card:
          type: 'custom:button-card'
          entity: '[[[ return variables.entity ]]]'
          template: '[[[ return variables.option_template ]]]'
          name: '[[[ return variables.option2_name ]]]'
          variables:
            set_value: '[[[ return variables.option2_set_value ]]]'
            range_start: '[[[ return variables.option2_range_start ]]]'
            range_stop: '[[[ return variables.option2_range_stop ]]]'
            option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
            option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
            option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
            option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
      opt3:
        card:
          type: 'custom:button-card'
          entity: '[[[ return variables.entity ]]]'
          template: '[[[ return variables.option_template ]]]'
          name: '[[[ return variables.option3_name ]]]'
          variables:
            set_value: '[[[ return variables.option3_set_value ]]]'
            range_start: '[[[ return variables.option3_range_start ]]]'
            range_stop: '[[[ return variables.option3_range_stop ]]]'
            option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
            option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
            option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
            option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
      opt4:
        card:
          type: 'custom:button-card'
          entity: '[[[ return variables.entity ]]]'
          template: '[[[ return variables.option_template ]]]'
          name: '[[[ return variables.option4_name ]]]'
          variables:
            set_value: '[[[ return variables.option4_set_value ]]]'
            range_start: '[[[ return variables.option4_range_start ]]]'
            range_stop: '[[[ return variables.option4_range_stop ]]]'
            option_button_on_color: '[[[ return variables.option_button_on_color ]]]'
            option_button_off_color: '[[[ return variables.option_button_off_color ]]]'
            option_text_on_color: '[[[ return variables.option_text_on_color ]]]'
            option_text_off_color: '[[[ return variables.option_text_off_color ]]]'
  alerter:
    template: standard
    show_last_changed: true
    color_type: icon
    extra_styles: |
      [[[ return `
        @keyframes pulse {
          20% {
            background-color: ${variables.color};
          }
        }
      `]]]
    variables:
      color: var(--paper-item-icon-active-color)
    state:
      - value: 'on'
        id: value_on
        styles:
          card:
            - animation: pulse 1s infinite
  alerter-dual:
    template: standard
    show_last_changed: true
    color_type: icon
    extra_styles: |
      [[[ return `
        @keyframes pulse1 {
          20% {
            background-color: ${variables.color_initial};
          }
        }
        @keyframes pulse2 {
          20% {
            background-color: ${variables.color_extended};
          }
        }
        @keyframes color {
          0% {
            color: unset;
            opacity: 0.5
          }
          99% {
            color: unset;
            opacity: 0.5
          }
          100% {
            color: ${variables.color_extended};
          }
        }
      `]]]
    variables:
      color_initial: var(--paper-item-icon-active-color)
      color_extended: 'rgba(240,52,52, 0.9)'
      color_seconds: 60
    state:
      - value: 'on'
        id: value_on
        styles:
          card:
            - animation: >-
                [[[ return `pulse1 1s ${variables.color_seconds}, pulse2 1s
                ${variables.color_seconds}s infinite` ]]]
          icon:
            - color: '[[[ return variables.color_extended ]]]'
            - opacity: 1
            - animation: '[[[ return `color ${variables.color_seconds}s 1` ]]]'
          name:
            - font-weight: bold

check this Lovelace config:

title: Ha Rpi4 Data

button_card_templates: !include lovelace/buttons/button_card_templates.yaml    # <------- this is where you save your templates
decluttering_templates: !include_dir_named lovelace/decluttering_templates
custom_header: !include lovelace/custom_header/custom_header_data.yaml

views:
  - !include lovelace/views/view_Home_assistant.yaml         #0
  - !include lovelace/views/view_Light_data.yaml             #1
  - !etcetcetc

in that file you should copy what you now show below template: (which isnt a valid key in the first place)

safe below code in a button_card_templates.yaml file in the directory of your naming (and reference that in the main lovelace-ui.yaml like I suggested above)

container:
  color_type: label-card
  color: dimgray
  styles:
    card:
      - padding: 0
    name:
      - border-radius: 0.4em 0.4em 0 0
      - padding: 0.1em
      - width: 100%
      - font-weight: bold
    grid:
      - grid-template-areas: '"i" "n" "buttons"'
      - grid-template-columns: 1fr
      - grid-template-rows: 1fr min-content min-content
    custom_fields:
      buttons:
        - background-color: 'rgba(0,0,0,0.3)'
        - margin: 0
        - padding: 0.3em
2 Likes

That decluttering is a good move.

@qoheleth Yes, it is there, it is the third line in the config that I posted.

ah, that was my problem. I removed templates and everything started working. Not sure why I put that in there in the first place. Many thanks!!

@Mariusthvdb One more thing if I may. I tried to move the templates to a separate template file like you did via this:

button_card_templates: !include lovelace/buttons/button_card_templates.yaml

I put that in the Raw configuration editor and when I try to save it I get the following error:

Unable to parse YAML: YAMLException: unknown tag !<!include> at line 3, column 76: ... ttons/button_card_templates.yaml ^

I have used the !include in the main configuration file with no issues. Do I need to do something special here for HA to recognize the macro?

tbh, I dont know, I dont use the Raw config editor, but use yaml mode.

speaking of which, my main setting in configuration.yaml is:

lovelace:
  mode: yaml
  resources: !include /config/lovelace/resources.yaml
  dashboards:
      etcetc

but I don’t think that has anything to do with the error you see. Of course, the folder name and the path need to be exactly the same, are you sure you have done that alright?

Ok, I am going NUTS! I almost have this how I want it. - the fact the Street does not do ST and the STATE does not do a two letter. My malfunction is I CAN NOT get the line after the <br> to justify start like the line before!

so code is this…

  ln1: |
    [[[
      return `<img
        src='https://developers.google.com/maps/images/maps-icon.svg'
          style="width:12px;height:12px">
        </ha-icon> ${states['sensor.g3_1_iphone'].attributes.Street}, ${states['sensor.g3_1_iphone'].attributes.City}<br>${states['sensor.g3_1_iphone'].attributes.State}, ${states['sensor.g3_1_iphone'].attributes['Postal Code']}`
    ]]]

And this code is whats sposta tell it to all align to start.

    ln1:
      - font-size: 11px
      - align-self: start
      - justify-self: start
      - padding-botom: 4px

instead, the outcome is like this…

icon Street Name, City Name
      FullStateName, Zip

This is the whole code incase someone wants to use it. Really nice looking card - the kink above…

type: 'custom:button-card'
entity: person.g3_1
show_icon: false
show_name: true
aspect_ratio: 1/1
styles:
  card:
    - background-color: transparent
    - border-radius: 10%
    - padding: 14%
    - font-size: 10px
    - text-shadow: 0px 0px 5px black
    - text-transform: capitalize
  grid:
    - grid-template-areas: '"n n""i i""zone zone""battery battery""ln1 ln1"'
    - grid-template-columns: 1fr 1fr
    - grid-template-rows: 1fr min-content min-content min-content min-content
  name:
    - font-weight: bold
    - font-size: 12px
    - align-self: start
    - justify-self: middle
  custom_fields:
    zone:
      - font-size: 12px
      - self-start: center
      - align-self: center
      - justify-self: start
      - padding-bottom: 4px
    battery:
      - entity: sensor.g3_1_iphone_12_pro_max_battery_state_2
      - font-size: 12px
      - align-self: center
      - justify-self: start
      - padding-bottom: 4px
      - '--text-color-sensor': >-
          [[[ if (states["sensor.g3_1_iphone_12_pro_max_battery_state_2"].state
          <= 20) return "red"; ]]]
    ln1:
      - font-size: 11px
      - align-self: start
      - justify-self: start
      - padding-botom: 4px
custom_fields:
  i: |
    <img width= 38% src='/local/images/me_g3-1.png'>
  zone: |
    [[[
      if (states['person.g3_1'].state ='Home')
        return `<ha-icon
          icon="mdi:google-maps"
          style="width:12px;height:12px;color:SteelBlue">
          </ha-icon><span> <span style="color: var(--text-color-sensor);">${states['person.g3_1'].state}</span></span>`
       else 
        return `<ha-icon
          icon="mdi:google-maps"
          style="width:12px;height:12px;color:DarkOrange">
          </ha-icon><span> <span style="color: var(--text-color-sensor);">${states['person.g3_1'].state}</span></span>`
    ]]]
  battery: |
    [[[
      if (states['device_tracker.g3_1_iphone_12_pro_max_2'].attributes.battery_status.state =='Charging')
        return `<ha-icon
          icon="mdi:battery-charging"
          style="width:12px;height:12px;color:lime">
          </ha-icon><span> <span style="color: var(--text-color-sensor);">${states['sensor.g3_1_iphone_12_pro_max_battery_state_2'].state}%</span></span>`
       else 
        return `<ha-icon
          icon="mdi:battery"
          style="width:12px;height:12px">
          </ha-icon><span> <span style="color: var(--text-color-sensor);">${states['sensor.g3_1_iphone_12_pro_max_battery_state_2'].state}%</span></span>`
    ]]]
  ln1: |
    [[[
      return `<img
        src='https://developers.google.com/maps/images/maps-icon.svg'
          style="width:12px;height:12px">
        </ha-icon> ${states['sensor.g3_1_iphone'].attributes.Street}, ${states['sensor.g3_1_iphone'].attributes.City}<br>${states['sensor.g3_1_iphone'].attributes.State}, ${states['sensor.g3_1_iphone'].attributes['Postal Code']}`
    ]]]

@portigui, the raw configuration editor does not support !include. You have to do your dashboard in yaml mode for that feature. I don’t know why they don’t support that feature in GUI mode. I wish they did.

@G3GhostTech, have you tried using - text-align: left?
You can also use the browser’s developer pane (usually F12 to turn it on) to examine the styling being applied and experiment with different styling.

Side note, did you intend to have </ha-icon> in your ln1 definition? It may not be causing any problem, but it’s not doing anything. Also, the extra <span>...</span> is redundant and can be removed.

1 Like

Help with variable.

I have some custom fields that i would like to move to an template.

custom_fields:
  sensor_1: "[[[ return `${states['sensor.hallway_mirror_power'].state} W` ]]]"

Is there a way to change the above “return statement” to replace the part “hallway_mirror” with a variable? so i can use the same template for multiple buttons with minimal code in the card.

like a variable i set in the card:

variables:
  var_sensor_name: "hallway_mirror"
custom_fields:
  sensor_1: "[[[ return `${states[ variables.var_sensor_name + '_power' ].state} W` ]]]"
1 Like