Fun with custom:button-card

Here’s how I work with a tri-state input select helper. You should be able to use a variation for yours and the color option.

                  name: |
                    [[[
                      if (states["input_select.good_night_phase"].state == "ready") return "";
                      if (states["input_select.good_night_phase"].state == "bed") return "in bed...";
                      return "Good Night";
                    ]]]
                  icon: |
                    [[[
                      if (states["input_select.good_night_phase"].state == "lights") return "mdi:lightbulb-group";
                      if (states["input_select.good_night_phase"].state == "bed") return "mdi:bed";
                      return "mdi:power";
                    ]]]

my case is> the state of my entity could be a very long string like you see in my foto, and i dont control that , i just want to something happen if the string “cozinha” is inside of that long string.

But i can,t find the anwser for that so i am seeing now how to do it with mushroom buttons, there i can use the jinja2 template.

Hey team

Does anyone have any great ideas on how to achieve this.

I have a button that has a timer template on it as a custom_field and want to basically draw the custom_field OVER the icon and turn the icon off when the state is on

eg:

state_on:
  icon: off
  custom field: on

state_off:
  icon: on
  custom field: off

I have tried to trick the card by styling both of them using things like transparent colors on both and realize that transparency IS NOT REALLY TRANSPARENT (if the custom field text and background color is set to transparent it blanks out the icon and you cannot see the icon thru the text)

I have also tried (what I think is) EVERY combination of show_icon: and show_label: (with the idea that the template could go in the label if-need-be

    state:
      - value: 'on'
        # show_icon: false
        # show_custom_field: true
        styles:
          custom_fields:
            notification:
              # show_notification (code/template)
              - color: black
              - background_color: transparent # can also be aquamarine if needed
          card:
            - background-color: aquamarine
          icon:
            - color: transparent
            -  show_icon: false
      - value: 'off'
        # show_icon: true
        # show_custom_field: false
        styles:
          custom_fields:
            notification:
              # hide_notification (code/template
              - color: transparent
              - background_color: transparent
          card:
            - background-color: blue
          icon:
            - color: red

Ive also tried:

    styles:
      icon:
        - color: >
            [[[
              if (entity.state == 'on') return 'rgba(0,0,0,0)';
              else return 'blue';
            ]]]
      custom_fields:
        notification:
          - color: >
              [[[
                if (entity.state == 'off') return 'rgba(0,0,0,0)';
                else return 'black';
              ]]]

The reason Im doing this is I have a 6x6 grid of buttons that can select any of 36 timers in a custom:vertical-stack-in card and I dont have the real estate to do it any other way as there will be 20 of these cards on one page on a dashboard

Ive read and searched this (and other threads) until Im dizzy and cannot find a solution.

Any help with such a simple thing would be very much appreciated as I have spent two FULL days trying to work this put

After update to 2023.5 I´ve noticed that lock icon when custom:button-card has enabled lock is visible through popup or blurred background while popup.
bazen_1

Any advice how to solve it pls?

I am new to this card and could a little help configuring a custom field.

I have a horizontal stack with 4 cards. The first two cards are for the washer and dryer, I want to show the countdown time at the bottom of the card. I have this working in the below code but the text for the countdown timer is causing the buttons to overlap. How would I go about removing that text entirely?

type: horizontal-stack
cards:
  - type: custom:button-card
    aspect_ratio: 1/1
    custom_fields:
      graph:
        card:
          type: sensor
          entity: sensor.dryer_countdown_time
    styles:
      custom_fields:
        graph:
          - filter: opacity(50%)
          - overflow: unset
      card:
        - overflow: unset
      grid:
        - grid-template-areas: '"i" "n" "graph"'
        - grid-template-columns: 1fr
        - grid-template-rows: 1fr min-content min-content
    entity: sensor.dryer
    hold_action:
      action: more-info
  - type: custom:button-card
    aspect_ratio: 1/1
    custom_fields:
      graph:
        card:
          type: sensor
          entity: sensor.washer_countdown_time
    styles:
      custom_fields:
        graph:
          - filter: opacity(50%)
          - overflow: unset
      card:
        - overflow: unset
      grid:
        - grid-template-areas: '"i" "n" "graph"'
        - grid-template-columns: 1fr
        - grid-template-rows: 1fr min-content min-content
    entity: sensor.washer
    hold_action:
      action: more-info
  - show_name: true
    show_icon: true
    type: button
    entity: binary_sensor.dishwasher
    show_state: true
  - show_name: true
    show_icon: true
    type: button
    tap_action:
      action: toggle
    entity: binary_sensor.van_charging
    icon: mdi:van-utility
    show_state: true

Hi all.

I need to create a button with some information about forecast temperature and old temperature.

- type: custom:button-card
      entity: weather.myhome
      template: temperature_history
      name: Ieri
      label: |
        [[[
        return  states['weather.myhome'].attributes.forecast[0].temperature +'°'
        ]]]

This work until I get the previous temperature with negative index.

return states['weather.myhome'].attributes.forecast[-1].temperature +'°'

In this case the card return errors

Cannot reading properties of undefinied (reading ‘temperature’) in return states[‘weather.myhome’].attributes.forecast[-1].temperature +‘°’

But the code work in editor model, this code return the max temperature of yesterday

{{ state_attr('weather.myhome', 'forecast')[-1].temperature }}

I try using quote, double quote, escape char but not work.

For now the only alternative is to create a sensor, but if possible I would like to try without.

  - sensor:
      - name: Temp yesterday
        state: "{{ state_attr('weather.myhome', 'forecast')[-1].temperature }}"

Any ideas?

Regards,
Marco

@kajmaj, I just updated to 2023.5 this week and started noticing the same thing. I also have a whole button-card that I created doing it too, but only one of the several I have on the dashboard are showing over the popup. Very strange.

I haven’t figured out what is going on yet. If anyone has seen any discussion on this issue elsewhere please reply with a link.

So far no way out yet >>> github

I did some digging with the browser debug window and determined that there is a crucial css variable missing in my theme to ensure a proper z-index of the dialog.

I added this to my theme:

      dialog-z-index: 100
      mdc-dialog-z-index: 100

The first one is what did it, but both were missing.

The error message is telling you, that the sensor is not ready at the time it is setup in the system. Meaning, the sensor is not ready yet.

That’s why it works in the template editor. At that time the values from your weather provider are available, so the sensor works correctly. And on a second note, it depends on how you call the sensor. There is a difference between states['xyz'].attributes... and state_attr. See here (especially the “warning section”):

I love layouts you created. Here is my implementation :


It is very simple. Three separate cards: two for lights in two rooms, one for windows and doors.
However, I have one problem. Once in a while the cards do not load on my phone. When I start HA, the cards are not there, or there is only 1 of 3 or 2 of 3. This happens when I haven’t opened the app on my phone for a long time (a few hours, a day). Switching to a different view in the same dashboard and then back does not help. Switching to another dashboard and then back helps. However, I would like to eliminate this problem. Has anyone encountered this or have any ideas? I can’t find anything related to these events in the logs.
/edit
I’ve now tested on the PC and noticed that the same thing happens in the browser after refreshing the dashboard page - I press F5 and the screenshot tabs disappear. Does anyone have this problem?

Hi.
Is it possible to have smaller size number for decimals? Here is example of my temp sensor:

type: custom:button-card
entity: sensor.vidtemp_dnevna_temp
name: ' '
icon: mdi:sofa
color: orange
show_state: true
styles:
  card:
    - height: 150px
    - width: 175px
    - color: gold
    - box-shadow: 0px 0px 6px rgb(0, 0, 0)
    - background-color: RGB(57,61,71)
    - border-radius: 15px
  state:
    - line-height: 80px
    - font-size: 70px
    - text-shadow: 0px 0px 6px black
state_display: |
  [[[ return entity.state + '°' ]]]

Sry, I’d looked in the documentation more than once and can’t figure out how to get the area name of an entity. One more hint please. :smiley:

Hi,
I resumed an old project but I run into a problem.
I have to give icons values to animate entities with template variables.

button_card_templates:
  position:
    variables:
      origin: rotate(0deg)
    show_state: false
    show_name: false
    show_entity_picture: true
    styles:
      card:
        - box-shadow: none
        - background-color: rgba(0, 0, 0, 0)
        - transform: '[[[ return variables.origin ]]]'
  on_off:
    variables:
      turn: rotate(0deg)
      width_off: 100%
    state:
      - value: 'off'
        entity_picture: /local/floorplan//irrigatore_off.png
        styles:
          icon:
            - animation: blink 5s linear infinite
            - width: '[[[ return variables.width_off ]]]'
      - value: 'on'
        entity_picture: '[[[ return variables.sprinkler ]]]'
        styles:
          icon:
            - animation: '[[[ return` rotate1 10s linear infinite alternate` ]]]'
            - transform-origin: center
    extra_styles: |
      [[[ return `
        @keyframes rotate1 {
          0% {
            transform: rotate(0deg);
          }
          50% {
            transform: ${variables.turn};
          }
          100% {
            transform: rotate(0deg);
          }
        }
      `]]]

and lovelace card

type: picture-elements
image: /local/floorplan/55x55.png
elements:
  - type: custom:button-card
    tap_action: none
    entity: input_boolean.pulsante
    template:
      - position
      - on_off
    variables:
      origin: rotate(0deg)
      turn: rotate(180deg)
      width_off: 150%
      sprinkler: /local/floorplan/MP_rotator_dark.png
    style:
      top: 50%
      left: 50%
      width: 100%
  - type: custom:button-card
    tap_action: none
    entity: input_boolean.pulsante
    template:
      - position
      - on_off
    variables:
      origin: rotate(60deg)
      turn: rotate(90deg)
      width_off: 150%
      sprinkler: /local/floorplan/MP_rotator_dark.png
    style:
      top: 65%
      left: 50%
      width: 100%

It takes the value edited on “turn: rotate(180deg)” of the first card, and in the following cards it keeps the same value even though it is different.
What is not clear to me is that the “origin: rotate(0deg)” value that I use to rotate the card instead in the first one is not kept in the second one which is precisely “origin: rotate(60deg)”
Is there a way without creating a keyframes for every single card?

Thank you for finally mentioning input_button.press. That is what I was missing:

type: custom:button-card
color_type: card
entity: input_button.litterbox_cleaned
icon: mdi:cat
show_label: true
triggers_update: all
tap_action:
  action: call-service
  service: input_button.press
  service_data:
    entity_id: input_button.litterbox_cleaned
styles:
  card:
    - '--mdc-ripple-color': blue
    - '--mdc-ripple-press-opacity': 0.5
label: |-
  [[[
    var n = new Date();
    var c = new Date(states['input_button.litterbox_cleaned'].state);
    var total_seconds = Math.floor(new Number(n.getTime() - c.getTime())/1000);
    if (total_seconds < 0) {
      total_seconds = 0;
    }
    var days = Math.floor(total_seconds / 86400);
    var hours = Math.floor((total_seconds - days * 86400)/3600);
    var minutes = Math.floor((total_seconds - days * 86400 - hours * 3600)/60);

    //return total_seconds + " seconds ago";

    var last_cleaned = "";
    if (days > 0) {
      last_cleaned += days + " d ";
    }
    if (hours > 0) {
      last_cleaned += hours + " h ";
    }
    if (days == 0 & minutes >= 0) {
      last_cleaned += minutes + " min";
    }
    return last_cleaned + " ago";
  ]]]
state:
  - operator: template
    value: |
      [[[
        var n = new Date();
        var c = new Date(states['input_button.litterbox_cleaned'].state);
        var total_seconds = Math.floor(new Number(n.getTime() - c.getTime())/1000);
        var days = total_seconds / 86400;
        return days <= 2.5;
      ]]]
    name: Litterbox Clean
    color: green
  - operator: template
    value: |
      [[[
        var n = new Date();
        var c = new Date(states['input_button.litterbox_cleaned'].state);
        var total_seconds = Math.floor(new Number(n.getTime() - c.getTime())/1000);
        var days = total_seconds / 86400;
        return days > 2.5;
      ]]]
    name: Litterbox Not Clean
    color: red
    styles:
      card:
        - animation: blink 2s ease infinite
  - operator: default
    color: orange
    name: Litterbox State Unknown
    icon: mdi:cat
view_layout:
  position: sidebar

I am trying to figure out some custom fields and how to alter some existing code that I am using in my own dashboard. I am following Mattias_Persson’s code found here.

I am trying to change the person card to show colors similar to what I have been able to do on other cards with one difference. On some cards I am using for input_select entities I have different colored circles for different notifications. I am trying to show a green circle for the home zone, yellow for any other zone, and red for away.

Unfortunately, following Mattias’s code I only get an on or off based and the state_on variable. But I can’t figure out how to add a third option. Additionally, I would like to replace the time in the circle with the icon for the zone that each person is in or the away icon. I have tried countless ways to get this to work and have not been able to get to what I want. Any help would be greatly appreciated.

Here is the code I am trying to modify.

circle_person:
  styles:
    card:
      - --c-stroke-color-on: rgb(0,0,0)
      - --c-stroke-color-off: none
      - --c-fill-color-on: none
      - --c-fill-color-off: rgba(255,255,255,0.04)
      - --c-stroke-width: 2.3
      - --c-stroke-width-dragging: 4
      - --c-font-color: rgb(0,0,0)
      - --c-font-size: 14px
      - --c-unit-font-size: 10.5px
      - --c-font-weight: 700
      - --c-letter-spacing: -0.02rem
  custom_fields:
    circle: >
      [[[
        if (entity) {
            let r = 22.1,
                c = r * 2 * Math.PI,
                tspan = '<tspan dx=".2" dy="-.4">',
                domain = entity.entity_id.split('.')[0],
                state = variables.state_on,
                input = variables.circle_input || ' ',
                unit = variables.circle_input_unit || ' ';

           /* * * * * * * * * * * * * * * * * *
            *                                 *
            *             CIRCLE              *
            *                                 *
            * * * * * * * * * * * * * * * * * */

            let circle = (state, input, unit) => {
                return `
                  <svg viewBox="0 0 50 50">
                    <style>
                      circle {
                        transform: rotate(-90deg);
                        transform-origin: 50% 50%;
                        stroke-dasharray: ${c};
                        stroke-dashoffset: ${typeof input === 'number' && c - input / 100 * c};
                        stroke-width: var(--c-stroke-width);
                        stroke: ${state ? 'var(--c-stroke-color-on)' : 'var(--c-stroke-color-off)'};
                        fill: ${state ? 'var(--c-fill-color-on)' : 'var(--c-fill-color-off)'};
                      }
                      text {
                        font-size: var(--c-font-size);
                        font-weight: var(--c-font-weight);
                        letter-spacing: var(--c-letter-spacing);
                        fill: var(--c-font-color);
                      }
                      tspan {
                        font-size: var(--c-unit-font-size);
                      }
                      #circle_value, tspan {
                        text-anchor: middle;
                        dominant-baseline: central;
                      }
                    </style>
                    <circle id="circle_stroke" cx="25" cy="25" r="${r}"/>
                    <text id="circle_value" x="50%" y="52%">${input}${tspan}${unit}</tspan></text>
                  </svg>

                  ${domain === 'light' && `
                      <input id="circle_slider" type="range" min="0" max="100" value="${input}">
                  `}
                `;
            }

           /* * * * * * * * * * * * * * * * * *
            *                                 *
            *             PERSON              *
            *                                 *
            * * * * * * * * * * * * * * * * * */

            if (domain === 'person') {
                let time = c => {
                    let s = (c/1e3),
                        m = (c/6e4),
                        h = (c/36e5),
                        d = (c/864e5);
                    return s < 60
                        ? parseInt(s) + 's'
                        : m < 60 ? parseInt(m) + 'm'
                        : h < 24 ? parseInt(h) + 'h'
                        : parseInt(d) + 'd';
                };
                let input = states[variables.retain] === undefined || states[variables.retain].state === 'unavailable'
                        ? time(Date.now() - Date.parse(entity.last_changed))
                        : time(Date.now() - Date.parse(states[variables.retain].state)),
                    unit = ' ';
                return circle(state, input, unit);
            }

        }
      ]]]
1 Like

I created this button card. I struggle to put the icon to the right of the text. Is that possible? IMG_2200

Try with this:

Layout: icon_state
styles:
  grid:
    - grid-template-areas: '"n i" "s i" "l i"'
    - grid-template-columns: 1fr 40%

Thx. Pointed in the right direction. Will play around with it.

Hi all,

Does anybody have a yaml example of a gauge/bar chart inside of a custom button card like with humidity, feels or outside ?