Lovelace: Button card

Ok, I have a circumstance with Templates and Merging States that confuses me a bit. This is specifically dealing with Merging States that are based on the same value.

Based on my current template, when an entity is 'on' I apply a specific theme to the corresponding button. However, when that entity is a Fan, I also want to apply spin: true. Because of the way state merging behaves (and my template), the end result will always be spinning icons for all entities when turned on.

My current work around is to leverage two different templates where the only difference is spin: true but I feel like that sort of defeat the purpose of templates. What do you folks think?

Here’s the Template YAML in case anyone is curious or needs clarification on what I’m describing.

button_card_templates:
  homekit_style_settings:  #Globally unique theme settings regardless of button type or design.
    styles:
      card:
        - border-radius: 10px
    state:
      # - value: 'on'
      #   id: fan_speed
      #   spin: true
      #   styles:
      #     card:
      #       - box-shadow: 0px 0px 10px 1px var(--button-card-light-color)
      - value: 'on'
        id: buttons
        styles:
          card:
            - box-shadow: 0px 0px 10px 1px var(--button-card-light-color)
      - value: 'off'
        styles:
          card:
            - filter: opacity(50%)
          icon:
            - filter: grayscale(100%)
 
  homekit_button_settings:  # Specific settings for Square Homekit buttons
    template: homekit_style_settings
    show_state: true
    show_label: true
    show_icon: true
    aspect_ratio: 1/1
    styles:
      grid:
        - grid-template-areas: '"i" "n" "s" "l"'
        - grid-template-columns: 1fr
        - grid-template-rows: 1fr min-content min-content min-content
      img_cell:
        - justify-content: start
        - align-items: start
      name:
        - justify-self: start
        - padding-left: 10px
        - font-weight: bold
        - text-transform: Titlecase
        - font-size: 14px
      label:
        - font-size: 11px
        - padding: 0px 10px
        - justify-self: start
      state:
        - justify-self: start
        - padding-left: 10px
        - text-transform: lowercase
        - font-size: 12px
      icon:
        - height: 70%

  homekit_light:  #Light and Switch entity specific settings 
    template: homekit_button_settings

  homekit_fan:   #Fan entity specific settings 
    template: homekit_button_settings
    state:
      - value: 'on'
        id: fan_speed

  homekit_dimmer:   #Dimmer entity specific settings 
    template: homekit_button_settings
    tap_action:
      action: toggle
    hold_action:
      action: more-info
1 Like

Actually, you missed the purpose of id, but what you’re doing is almost right, here’s the solution (see inline comments for explanation):

button_card_templates:
  homekit_style_settings:  #Globally unique theme settings regardless of button type or design.
    styles:
      card:
        - border-radius: 10px
    state:
      - value: 'on'
        id: state_on  # I changed the id
        styles:
          card:
            - box-shadow: 0px 0px 10px 1px var(--button-card-light-color)
      - value: 'off'
        styles:
          card:
            - filter: opacity(50%)
          icon:
            - filter: grayscale(100%)
 
  homekit_button_settings:  # Specific settings for Square Homekit buttons
    template: homekit_style_settings
    show_state: true
    show_label: true
    show_icon: true
    aspect_ratio: 1/1
    styles:
      grid:
        - grid-template-areas: '"i" "n" "s" "l"'
        - grid-template-columns: 1fr
        - grid-template-rows: 1fr min-content min-content min-content
      img_cell:
        - justify-content: start
        - align-items: start
      name:
        - justify-self: start
        - padding-left: 10px
        - font-weight: bold
        - text-transform: Titlecase
        - font-size: 14px
      label:
        - font-size: 11px
        - padding: 0px 10px
        - justify-self: start
      state:
        - justify-self: start
        - padding-left: 10px
        - text-transform: lowercase
        - font-size: 12px
      icon:
        - height: 70%

  homekit_light:  #Light and Switch entity specific settings 
    template: homekit_button_settings

  homekit_fan:   #Fan entity specific settings 
    template: homekit_button_settings
    state:
      # I changed this block, this will ADD spin: true to the state with the id state_on from the template homekit_style_settings
      - id: state_on
        spin: true

  homekit_dimmer:   #Dimmer entity specific settings 
    template: homekit_button_settings
    tap_action:
      action: toggle
    hold_action:
      action: more-info
2 Likes

I understand now. That makes much more sense. Not sure how I got that mixed up. Thank you very much, @RomRider!

Here you go. I use nested templates to achieve this look, although it appears I need to update the templates to be more in line with recent changes to button-card.

button_card_templates:
  iphone-button-settings:   # Applies to all Rounded-Rectangular Buttons
    show_state: true
    show_label: true
    tap_action:
      action: toggle
    styles:
      grid:
        - grid-template-areas: '"n i" "s i" "l i"'
        - grid-template-columns: auto 50px
      card:
        - border-radius: 10px
        - height: 55px
        - background-color: '#222222'
      label:
        - font-weight: bold
      icon:
        - height: 35px
        - width: 35px
      name:
        - justify-self: start
        - padding-left: 8px
        - font-weight: bold
        - text-transform: Titlecase
        - font-size: 14px
      state:
        - justify-self: start
        - padding-left: 14px
        - font-size: 10px
        - text-transform: uppercase

  fan-button-settings:  # Fan Domain Rounded-Rectangular Buttons
    template: iphone-button-settings
    icon: mdi:fan
    state:
      - value: 'on'
        color_type: icon
        color: rgb(181, 142, 49)
        spin: true
      - value: 'off'
        styles:
          card:
            - filter: opacity(50%)
          icon:
            - filter: grayscale(100%)
2 Likes

I’ve tried that, but it put the icon to the left and left lots of space between the icon and label (which was surprising to me, given the description of layout: icon_label, stating they are concatenated)

anyway, I’ve tried some more and end up now with what I had in mind designing this set of buttons. Not yet confident this is all necessary, seems overly complicated for such a simple button, but is works now. Posting for reference, and example to others struggling with the css for grid and items to display. If you spot any detail that can be improved on, don’t hesitate.

Whats beyond me is why the padding for the card is necessary to have the icon show. Would have thought padding made available space in the button even smaller?

52

type: vertical-stack
cards:

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: horizontal-filler

      - type: 'custom:button-card'
        template: button_default_state
        entity: group.all_living_ceiling_spots
        aspect_ratio: 12/1
        label_template: >
          if (states['sensor.spots_badge'].state !== 0) return 'Ceiling spots on: ' + states['sensor.spots_badge'].state;
          return 'Ceiling spots';
        layout: icon_label
        show_icon: true
        size: 40%
        show_label: true
        show_state: false
        show_name: false
        styles:
          img_cell:
            - justify-content: flex-end
          card:
            - padding: 4px
            - border-radius: 6px
          label:
            - justify-self: start
#            - text-align: left
            - font-size: 16px
            - font-weight: bold
            - padding-left: 0px
          grid:
            - grid-template-areas: '"i l"'
            - grid-template-columns: 1fr 65%

      - type: custom:button-card
        template: horizontal-filler

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: horizontal-filler

      - type: custom:button-card
        template: button_spots_group
        entity: light.living_ceiling_1_cds
        name: Cd's - 1
        icon: mdi:grid

      - type: custom:button-card
        template: button_spots_group
        entity: light.living_ceiling_3_wall
        name: 3 - Wall
        icon: mdi:theater
        styles:
          grid:
            - grid-template-areas: '"n i"'
            - grid-template-columns: 1fr 40%

      - type: custom:button-card
        template: horizontal-filler

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: horizontal-filler

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_1
        name: 1
        icon: mdi:grid

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_2
        name: 2
        icon: mdi:grid

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_3
        name: 3
        icon: mdi:grid

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_4
        name: 4
        icon: mdi:theater

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_5
        name: 5
        icon: mdi:theater

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_6
        name: 6
        icon: mdi:theater

      - type: custom:button-card
        template: horizontal-filler

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: horizontal-filler

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_7
        name: 7
        icon: mdi:nature

# cant have a butto with the same height and width of 6 small buttons, so use blank card to fill the gap
      - type: custom:button-card
        color_type: blank-card
      - type: custom:button-card
        color_type: blank-card
      - type: custom:button-card
        color_type: blank-card
      - type: custom:button-card
        color_type: blank-card

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_14
        name: 14
        icon: mdi:sofa

      - type: custom:button-card
        template: horizontal-filler

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: horizontal-filler

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_8
        name: 8
        icon: mdi:nature

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_9
        name: 9
        icon: mdi:nature

      - type: custom:button-card
        template: button_spot
        entity: light.hue_ambiance_spot_10
        name: 10
        icon: mdi:nature

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_11
        name: 11
        icon: mdi:sofa

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_12
        name: 12
        icon: mdi:sofa

      - type: custom:button-card
        template: button_spot_right
        entity: light.hue_ambiance_spot_13
        name: 13
        icon: mdi:sofa

      - type: custom:button-card
        template: horizontal-filler

  - type: horizontal-stack
    cards:

      - type: custom:button-card
        template: horizontal-filler

      - type: custom:button-card
        template: button_spots_group
        entity: light.living_ceiling_2_terrace
        name: Terrace - 2
        icon: mdi:nature

      - type: custom:button-card
        template: button_spots_group
        entity: light.living_ceiling_4_sofa
        name: 4 - Sofa
        icon: mdi:sofa
        styles:
          grid:
            - grid-template-areas: '"n i"'
            - grid-template-columns: 1fr 40%

      - type: custom:button-card
        template: horizontal-filler

  - type: custom:button-card
    template: vertical-filler

Welcome to the CSS world :woman_shrugging:

1 Like

haha lol, yes, thank you for the initiation… :wink:

going forward on that, here’s my template for button_default_state:

button_default_state:
  state:
    - value: 'on'
      styles:
        card:
          - box-shadow: '0px 0px 2px 1px #555B65'
          - background-color: '#F0C209'
        icon:
          - color: '#555B65'
        name:
          - color: '#555B65'
        label:
          - color: '#555B65'
      id: on-icon
    - value: 'off'
      styles:
        card:
          - box-shadow: '0px 0px 2px 1px #F0C209'
          - background-color: '#555B65'
        icon:
          - color: '#F0C209'
        name:
          - color: '#F0C209'
        label:
          - color: '#F0C209'
      id: off-icon
    - value: 'unavailable'
      styles:
        card:
          - opacity: 0.4
          - color: grey
          - --paper-item-icon-color: grey

which is more or less setting an on color and an off color for all parts, with a juxtaposed border color.

Tried to set the color in the card style first, but that would not work for all parts, so ended up describing them verbose, for each single item individually.

Can that be simplified somehow?

Defining color on the card should work for everything appart from the icon where you have to define it specifically.

thanks for confirming. And it would have to go under

styles:
  card:
    - color: '#F0C209' ## good for border, state, name and label
    - background-color: '#555B65'
    - box-shadow: '0px 0px 2px 1px'  ##<<---- no more border color either, when using the color: ?
  icon:
    - color: '#F0C209'

Making great progress on my Xbox controller layout!

5 Likes

This looks pretty awesome, but is it functional as well? Could you actually play a game with it?

That would be awesome but sounds like impossible haha.

Still looks awesome!

Haha, functional for navigation purposes only. The Harmony Hub isn’t recognized as a connected controller for gameplay purposes. It basically sends the same commands as the Xbox One Media Remote.

trying to get the full grips here of the workings of the button and options, I am puzzeled about the color/background-color.

we can use:

state:
  - operator: #whatever
    styles:
      card:
        - background-color: '#555B65'

but

state:
  - operator: #whatever
    color: '#555B65'

does the same? Or is the latter incorrect, I found these settings but they don’t seem to work reliably (or at all)?

using state: ‘on’ etc

        state:
          - value: 'on'
            color: '#F0C209'

          - value: 'off'
            color: '#555B65'

works though as is described here https://github.com/custom-cards/button-card/tree/dev#state
I am confused…

Would it be possible to add a config option to specify the number of times to repeat a hold_action?
for example:

hold_action:
  action: more-info
  repeat: 1
  repeat_amount: 1

This way we could have the more-info dialog pop up before releasing the button.
When you are on mobile it is hard to see the ripple underneath the finger so its hard to known when you can release it.

I’m using a transparent label for some of my buttons, I’m wondering if anybody knows how to get rid of the small black edge?

1 Like

@Corey_Maxim
Try this:

box-shadow: ‘rgba(0,0,0,0.0)’

1 Like
  • With color_type: card, color outside of styles and outside of state acts on the background color of the card when state is on
  • With color_type: icon (which is the default), color outside of styles and outside of state acts on the color of the icon when on

Based on this info above, if defined in states, it acts accordingly based on the matching state (either on the background or the icon).
So you could see this as a shortcut for simplicity when you don’t have crazy styles in place.
If you have some complex styles in case, I would suggest to avoid using color outside of styles.

If you think the documentation needs refinement, PRs against the dev branch are welcome :slight_smile:

I don’t think it’s a good idea, you’re trying to fix a problem by introducing a feature. hold action works exactly the same as the core HA one, it waits for 500ms before deciding if it’s a hold action or a simple click. Maybe the blue ripple needs to be bigger when you hold?

1 Like

haha, no I wouldn’t dare to suggest such a thing…thanks for the extra explanation/confirmation. I think I had my flukes where a main config color: was not set to card, in this case auto or the color_type was set. That changed behavior of course, but I hadn’t noticed…

to be precise, when in default (acting on icon) is not only acts on icon, but also on state, name and label. And border color (or box-shadow).

Before, other cards, eg Tiles, this card color setting would also act on icon. Which was rather nice. Wouldn’t you care to consider adapting that? Seems logical to have an overall color setting act on, well, all :wink:

it would make many configs much simpler, not needing a dedicated line for icon color.

          - value: 'off'
            styles:
              card:
                - color: 'black'
                - opacity: 0.8
                - box-shadow: '0px 0px 2px 1px'
    #          icon:
    #            - color: 'black'

@RomRider Is it possible to use button_templates in yaml mode?

I read somewhere in this thread someone mentioned about ‘includes’ but I couldn’t find that.

I have this in ‘ui-lovelace.yaml’ but it didn’t work. I have placed ‘button_card_templates.yaml’ file under ‘www/custom-lovelace’ folder.

title: My Home
resources:
  - url: /local/custom-lovelace/custom-cards/tracker-card.js?v=1.2.5
    type: js
  - url: /local/custom-lovelace/thomasloven/toggle-lock-entity-row.js
    type: js
  - url: /customcards/github/thomasloven/layout-card.js?track=true
    type: js
  - url: /customcards/github/thomasloven/card-tools.js?track=true
    type: js
  - url: /local/custom-lovelace/thomasloven/card-modder.js?v=1
    type: js
  - url: /local/custom-lovelace/thomasloven/useful-markdown-card.js
    type: js
  - url: /local/custom-lovelace/thomasloven/fold-entity-row.js
    type: js
  - url: /customcards/github/thomasloven/popup-card.js?track=true
    type: js
  - url: /local/custom-lovelace/thomasloven/state-switch.js
    type: js
  - url: /local/custom-lovelace/custom-cards/vertical-stack-in-card.js?v=v0.1.1
    type: js
  - url: /local/custom-lovelace/custom-cards/ext-weblink.js?v=0.3.2
    type: js
  - url: /local/custom-lovelace/ciotlosm/monster-card.js?v=0.2.3
    type: js
  - url: https://cdn.jsdelivr.net/gh/bramkragten/custom-ui@master/swipe-card/swipe-card.min.js
    type: module
  - url: /local/custom-lovelace/kalkih/mini-media-player-bundle.js?v=1.0.2
    type: module
  - url: /local/custom-lovelace/kalkih/simple-weather-card.bundle.js?v=0.3.0
    type: module
  - url: https://unpkg.com/[email protected]/moment.js
    type: js
  - url: /local/custom-lovelace/ljmerza/calendar-card.js?v=3.0.0
    type: js
  - url: /local/custom-lovelace/maykar/compact-custom-header.js?track=true
    type: module
  - url: /local/custom-lovelace/custom-cards/upcoming-media-card.js
    type: js
  - url: /customcards/github/maykar/lovelace-swipe-navigation.js?track=true
    type: js
  - url: /local/custom-lovelace/iantrich/text-divider-row.js
    type: module
  - url: /customcards/github/custom-cards/button-card.js?track=true
    type: module
button_card_templates: !include /local/custom-lovelace/button_card_templates.yaml
views:
  - id: 0  
    icon: mdi:home-assistant
    title: Main view
    panel: true
    path: main_view
    cards:

File “/config/deps/lib/python3.7/site-packages/pyupdate/ha_custom/custom_cards.py”, line 32, in construct_include
with open(filename, ‘r’, encoding=‘utf-8’, errors=‘ignore’) as localfile:
FileNotFoundError: [Errno 2] No such file or directory: ‘/local/custom-lovelace/button_card_templates.yaml’

don’t know if this against all UX guidelines these days, but can we animate the buttons to mimic pushing it? Ive tried a few things found on the web, but no succes so far. Can’t tell if it looks ridiculous because of it …