Fun with custom:button-card

Works like a charm, thank you very much!

Hey, @ktownsend-personal.

Thanks for the input, but in the end, because those buttons were actually running scripts, their states were precisely the problem… After all a script will change its state to ‘on’ when you run it, but turn back to ‘off’ the next second.

The solution I came with, even do it was quite a roundabout way, was to create two binary sensors: one for the angle the fan was and the other for the mode. Then I had to create input booleans for all the angles and modes, using those for automations that would turn on/off the input booleans according to ‘numeric state’, for the angles, and ‘state’ changes, for the modes.

Ex:
On - change to ‘30º’
Off - change from ‘30º’
…and so on.

alias: 30º angle - fan
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.fan_angle #sensor that I created to read the attribute 'angle'
    to: "30" #if value change to '30' 
    id: "on" #automation with id trigger
    enabled: true
  - platform: state
    entity_id:
      - sensor.fan_angle
    from: "30" #if value changes from '30'
    id: "off"
    enabled: true
condition:
  - condition: state
    entity_id: fan.fan
    state: "on" #condition - fan is on
action:
  - choose:
      - conditions:
          - condition: trigger
            id: "on"
        sequence:
          - service: input_boolean.turn_on
            data: {}
            target:
              entity_id: input_boolean.fan_30 #input boolean for 30º
      - conditions:
          - condition: trigger
            id: "off"
        sequence:
          - service: input_boolean.turn_off
            data: {}
            target:
              entity_id: input_boolean.fan_30
mode: single

Then I changed the card, adding a template relating it with the state of the input booleans.

type: vertical-stack
cards:
  - type: entity
    entity: fan.fan
    state_color: true
    attribute: percentage
    unit: '%'
  - type: horizontal-stack
    cards:
      - show_name: true
        show_icon: true
        type: custom:button-card
        name: 30º
        tap_action:
          action: call-service
          service: script.fan_30
        show_state: false
        color_type: card
        icon: ''
        state:
          - operator: template
            value: |
              [[[ return states['input_boolean.fan_30'].state === 'on' ]]]
            color: rgb(66, 134, 244)
          - operator: default
            color: rgb(44, 44, 44)
      - show_name: true
        show_icon: false
        color_type: card
        type: custom:button-card
        name: 60º
        tap_action:
          action: call-service
          service: script.fan_60
        show_state: false
        icon: ''
        state:
          - operator: template
            value: |
              [[[ return states['input_boolean.fan_60'].state === 'on' ]]]
            color: rgb(66, 134, 244)
          - operator: default
            color: rgb(44, 44, 44)
      - show_name: true
        show_icon: false
        type: custom:button-card
        name: 90º
        tap_action:
          action: call-service
          service: script.fan_90
        show_state: false
        color_type: card
        icon: ''
        state:
          - operator: template
            value: |
              [[[ return states['input_boolean.fan_90'].state === 'on' ]]]
            color: rgb(66, 134, 244)
          - operator: default
            color: rgb(44, 44, 44)
      - show_name: true
        show_icon: false
        type: custom:button-card
        name: 120º
        tap_action:
          action: call-service
          service: script.fan_120
        show_state: false
        color_type: card
        icon: ''
        state:
          - operator: template
            value: |
              [[[ return states['input_boolean.fan_120'].state === 'on' ]]]
            color: rgb(66, 134, 244)
          - operator: default
            color: rgb(44, 44, 44)
  - type: horizontal-stack
    cards:
      - show_name: true
        show_icon: true
        type: custom:button-card
        name: Normal
        color_type: card
        tap_action:
          action: call-service
          service: script.fan_normal
        show_state: false
        icon: ''
        state:
          - operator: template
            value: >
              [[[ return states['input_boolean.fan_normal_mode'].state === 'on'
              ]]]
            color: rgb(66, 134, 244)
          - operator: default
            color: rgb(28, 28, 28)
      - show_name: true
        show_icon: true
        color_type: card
        type: custom:button-card
        name: Breeze
        tap_action:
          action: call-service
          service: script.fan_breeze
        show_state: false
        icon: ''
        state:
          - operator: template
            value: >
              [[[ return states['input_boolean.fan_breeze_mode'].state === 'on'
              ]]]
            color: rgb(66, 134, 244)
          - operator: default
            color: rgb(28, 28, 28)

Exemple - cards:
fan

1 Like

Formatting seems to be wrong after 2022.11 and the new rounded “icons”
image

I am putting over a white box which is just blank when the timer/machine is not running and it just looks weird now:

type: custom:button-card
      entity: sensor.washer_power
      state_display: '[[[ return Math.round(entity.state) + " W" ]]]'
      margin: none
      show_name: false
      show_icon: false
      show_state: true
      styles:
        card:
          - box-shadow: none
          - font-size: 12px
        state:
          - color: |
              [[[
                if (states['sensor.washer_power'].state > 2)
                  return "red";
                else
                  return "white";
              ]]]

Any idea if it can be hidden again and how?

2 Likes

same problem here, all cards are messed up and get a thin frame

I set ha-card-border-width: "0px" in my theme to fix it.

1 Like

How did you do that? I just have the default theme on

You can add the following to your card to hide the border.

          styles:
            card:
              - border: none

Sweet, it works thanks.

Can also use card-mod for cards that don’t have style

- type: weather-forecast
  card_mod:
    style: |
      ha-card {
       border:none
      } 
  ...

Does anyone know whether this integration takes into account regex when templating? I have the card code below in my dashboard and it returns original entity value instead of the regex_replace string. Testing this in the template tester returns the regex_replace values correctly.

type: custom:button-card
entity: binary_sensor.kippy_sade
show_state: true
show_name: false
show_icon: false
icon: mdi:paw
color: rgb(0, 150, 0)
show_entity_picture: true
entity_picture: /local/img/sade_avatar_1.png
state:
  - operator: template
    value: >
      {{ states('binary_sensor.kippy_sade') | regex_replace(find="on", replace="En casa", ignorecase=False) | regex_replace(find="off", replace="Fuera", ignorecase=False) }}
styles:
  state:
    - font-size: 10px
  card:
    - height: 68px

Would someone give me a hand? :relaxed:

I am trying to create a reeeeally simple button-card with just the icon.
But I would like the icon to be aligned horizontally left/start and vertically middle/center.

How do I do this? I get all kinds of strange icon sizes and placement during my trial & errorrrrrr

      - type: custom:button-card
        entity: input_boolean.start_datetime_24h
        show_label: false
        show_name: false
        state:
          - value: 'on'
            styles:
              icon:
                - color: white
          - value: 'off'
            styles:
              icon:
                - color: grey

Thank you :slight_smile:

Tried playing with grid, but also to no success.
The card’s content is just not vertically centered.

image

Maybe I misunderstand, but wouldn’t adding this move the icon to the left and still be vertically center?

layout: icon_name_state

1 Like

It is then not vertically centered, no.

I think this problem might only be visible when the card is scaled, e.g. in a grid.

Here is the full code of the vertical stack card containing a grid at the top.

Summary
type: vertical-stack
cards:
  - type: custom:layout-card
    layout_type: grid
    layout:
      grid-template-columns: 3fr 1fr
      grid-template-rows: auto
      grid-template-areas: |
        "main1 side1"
        "main2 side2"
    cards:
      - type: custom:config-template-card
        entities:
          - input_boolean.start_datetime_24h
          - input_datetime.start_datetime
        card:
          type: entities
          card_mod:
            style: |
              :host {
                --card-mod-icon-color: white;
              }
              .card-content {
                padding: 0px;
              }
          entities:
            - entity: input_datetime.start_datetime
              icon: |-
                ${ 
                  if (states['input_boolean.start_datetime_24h'].state == 'on')
                    { 'mdi:autorenew' } 
                  else 
                    { 'mdi:numeric-1-box-multiple-outline' }
                  }
              card_mod:
                style: |
                  ha-date-input {
                    --mdc-text-field-fill-color: rgba(0, 0, 0, 0);
                  }
                  ha-time-input {
                    --mdc-text-field-fill-color: rgba(0, 0, 0, 0);
                    --mdc-select-fill-color: rgba(0, 0, 0, 0);
                  }
              tap_action:
                action: call-service
                service: script.start_datetime_1h
              hold_action:
                action: call-service
                service: script.start_datetime_24h
              double_tap_action:
                action: call-service
                service: script.start_datetime_24h
        view_layout:
          grid-area: main1
      - type: custom:config-template-card
        entities:
          - input_boolean.end_datetime_now
          - input_datetime.end_datetime
        card:
          type: entities
          card_mod:
            style: |
              :host {
                --card-mod-icon-color: white;
              }
              .card-content {
                padding: 0px;
              }
          entities:
            - entity: input_datetime.end_datetime
              icon: |-
                ${ 
                  if (states['input_boolean.end_datetime_now'].state == 'on')
                    { 'mdi:autorenew' } 
                  else 
                    { 'mdi:update' }
                  }
              card_mod:
                style: |
                  ha-date-input {
                    --mdc-text-field-fill-color: rgba(0, 0, 0, 0);
                  }
                  ha-time-input {
                    --mdc-text-field-fill-color: rgba(0, 0, 0, 0);
                    --mdc-select-fill-color: rgba(0, 0, 0, 0);
                  }
              tap_action:
                action: call-service
                service: input_boolean.toggle
                target:
                  entity_id: input_boolean.end_datetime_now
              hold_action:
                action: call-service
                service: script.end_datetime_reset
        view_layout:
          grid-area: main2
      - type: custom:button-card
        entity: input_boolean.start_datetime_24h
        show_label: false
        show_name: false
        show_state: true
        styles:
          grid:
            - grid-template-areas: '"i s" "i s" "i s"'
            - grid-template-rows: 1fr 1fr 1fr
            - grid-template-columns: auto
        icon: |
          [[[
            if (entity.state == 'on')
              return "mdi:autorenew";
            else
              return "mdi:autorenew-off";
          ]]]
        state:
          - value: 'on'
            styles:
              icon:
                - color: white
          - value: 'off'
            styles:
              icon:
                - color: grey
        view_layout:
          grid-area: side1
      - type: custom:button-card
        entity: input_boolean.end_datetime_now
        show_label: false
        show_name: false
        show_state: true
        styles:
          grid:
            - grid-template-areas: '"i s" "i s" "i s"'
            - grid-template-rows: 1fr 1fr 1fr
            - grid-template-columns: auto
        icon: |
          [[[
            if (entity.state == 'on')
              return "mdi:autorenew";
            else
              return "mdi:autorenew-off";
          ]]]
        state:
          - value: 'on'
            styles:
              icon:
                - color: white
          - value: 'off'
            styles:
              icon:
                - color: grey
        view_layout:
          grid-area: side2
  - type: entities
    card_mod:
      style: |
        :host {
          --card-mod-icon-color: white;
        }
    entities:
      - entity: input_select.dropdown_wildcards
        card_mod:
          style:
            hui-generic-entity-row $: |
              state-badge {
                display: none;
              }
              :host {
                --mdc-select-fill-color: rgba(0, 0, 0, 0);
              }
      - entity: input_select.dropdown_entities
        card_mod:
          style:
            hui-generic-entity-row $: |
              state-badge {
                display: none;
              }
              :host {
                --mdc-select-fill-color: rgba(0, 0, 0, 0);
              }
      - entity: input_select.dropdown_areas
        card_mod:
          style:
            hui-generic-entity-row $: |
              state-badge {
                display: none;
              }
              :host {
                --mdc-select-fill-color: rgba(0, 0, 0, 0);
              }

Looks like your code didn’t populate in your message.

How weird. Re-added the code :slight_smile:

Thanks for the inspiration on this custom button card, I finally change the icon and layout of the button as per specific requirement. the documentation is really helpful, thanks a lot!

1 Like

@Edwin_D, thanks. That’s definitely the easiest and most universal fix. It took me a while to remember to call the frontend.reload_themes service to see the change.

I set ha-card-border-width: "0px" in my theme to fix it.

@williamZ that’s a nice clean and consistent look. :+1:

@williamZ Looks fantastic. How did you achieve the toggle slider in the upper right-hand corner of each box? I have searched for the answer more than I’d like to admit…