Lovelace: Button card

Cool!
please make that a templatable field…? that would be really magic.

Hi,

I was wondering if it is possible to highlight a button when clicked upon?

For example, I have several button cards that are used to navigate between different views, and I would like to highlight the selected button when the linked view / navigation path is shown.

I know how to style the button, but I don’t know how to apply the style after clicking on one. Also, to undo the applied style when clicking another navigation button.

Thanks!

You can use JS templates and window.location for that

Any link with more info on this?
Maybe a tutorial or something?

Thanks for pointing me in the right direction, though. Appreciate it!

@RomRider love your work :grinning: many thanks for your time and dedication in creating this wonderful custom card. I was hoping that you could help me with this issue that I haven’t been able to solve.

font-size styling is not working for me when using custom fields in a grid that falls inside your vertical stack-in-card. Other styling works fine, e.g. border-radius, however font-size has no affect (see lines in code marked “font-size not working here”) As a result the font-size from body font in the default theme is used instead. Please find enclosed YAMP code and photo of the card.

card

cards:
  - name: Display
    show_icon: false
    show_name: false
    custom_fields:
      line1:
        card:
          color: blue
          color_type: card
          entity: sensor.display_line_1
          show_icon: false
          show_name: true
          show_state: true
          type: 'custom:button-card'
      line2:
        card:
          color: green
          color_type: card
          entity: sensor.display_line_2
          show_icon: false
          show_name: true
          show_state: true
          type: 'custom:button-card'
    styles:
      card:
        - background-color: gold
      custom_fields:
        line1:
          - width: 100%
          - justify-self: center
          # font-size not working here
          - font-size: 20px
          - border-radius: 30%
        line2:
          - width: 100%
          - justify-self: center
          # font-size not working here
          - font-size: 20px
          - border-radius: 30%
      grid:
        - grid-template-areas: '"line1" "line2"'
    tap_action:
      action: none
    type: 'custom:button-card'
keep:
  background: 'true'
  border_radius: 'true'
  box_shadow: 'true'
mode: vertical
type: 'custom:stack-in-card'

using this template:

button_shortcut_menu:
  variables:
    dashboard: >
      [[[ return window.location.pathname.split('/')[1] ]]]
    view: >
      [[[ return window.location.pathname.split('/').slice(-1) ]]]
  size: 25px
  styles:
    icon:
      - color: var(--secondary-text-color)
    card:
      - box-shadow: none
      - background: >
          [[[ return variables.view == variables.path
              ? 'var(--secondary-background-color)' : 'var(--card-background-color)';
          ]]]

and this for a button:

  - type: custom:button-card
    template: button_shortcut_menu
    icon: mdi:home
    tap_action:
      action: navigate
      navigation_path: /lovelace/home
    variables:
       path: home
    styles:
      icon:
        - color: >
            [[[
              return (states['sensor.count_alerts_notifying'].state > 0)
              ? 'red': 'green';
            ]]]
    state:
      - operator: template
        value: >
          [[[ return (states['sensor.count_alerts_notifying'].state > 0) ]]]
        spin: true

to color the active view

1 Like

What is wrong here? “.state > 5 )” + "else return ‘Redo’ " Works fine but not ".state > 60 ) "

state:
  - icon: 'mdi:coffee'
    name: Starta Bryggaren<br><b><i>
    value: 'off'
  - icon: 'mdi:coffee'
    name: |
      [[[
        if (states['sensor.fibaro_switch_power'].state > 5 ) return 'Värmeplatta på';
        if (states['sensor.fibaro_switch_power'].state > 60 ) return 'Bryggning pågår';
        else return 'Redo';
      ]]]
    value: 'on'

You need to use “else if” for the second one. Please consider learning basic javascript before posting here.

Try full syntax.

      [[[
        if (states['sensor.fibaro_switch_power'].state > 60) {
          return 'Bryggning';
        } else if (states['sensor.fibaro_switch_power'].state > 5) {
          return 'Värmeplatta på';
        } else {
          return 'Redo';
        }
      ]]]

Had to move the statements, it was bigger than 5 and that was returned first without any other options.

1 Like

Thx! That code did it =)

Don’t think that’s it. The order of the template is what is causing this behavior. 60 is more than 5 so the first evaluation is true and returns that result, never to look any further.

more over, we dont need the ‘else’ in either line:

      [[[
        if (states['sensor.fibaro_switch_power'].state > 60 ) return 'Bryggning pågår';
        if (states['sensor.fibaro_switch_power'].state > 5 ) return 'Värmeplatta på';
        return 'Redo';
      ]]]

would do nicely.

Just verifying you read my latest post, which hopefully resolved it. Your solution works though as well, and it’s smaller too!

You have to style it in the custom_field button-card styles object, not in the main card styles object.

cards:
  - name: Display
    show_icon: false
    show_name: false
    custom_fields:
      line1:
        card:
          color: blue
          color_type: card
          entity: sensor.display_line_1
          show_icon: false
          show_name: true
          show_state: true
          styles:
            card:
              - font-size: 20px
          type: 'custom:button-card'
      line2:
        card:
          color: green
          color_type: card
          entity: sensor.display_line_2
          show_icon: false
          show_name: true
          show_state: true
          styles:
            card:
              - font-size: 20px
          type: 'custom:button-card'
    styles:
      card:
        - background-color: gold
      custom_fields:
        line1:
          - width: 100%
          - justify-self: center
          - border-radius: 30%
        line2:
          - width: 100%
          - justify-self: center
          - border-radius: 30%
      grid:
        - grid-template-areas: '"line1" "line2"'
    tap_action:
      action: none
    type: 'custom:button-card'
keep:
  background: 'true'
  border_radius: 'true'
  box_shadow: 'true'
mode: vertical
type: 'custom:stack-in-card'

Both solutions from @KTibow and @Mariusthvdb work it’s just a lot more readable using else if :slight_smile:

Done, please check the beta release 3.4.0-0 and the release notes. :wink:

@RomRider awesome, thank you :grinning: resolved!

So cool, the tooltip now works right out of the box!

  tooltip: >
    [[[ function capitalizeFirstLetter(string) {
              return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
              }
    return capitalizeFirstLetter(variables.path.replace('_',' ') ) ]]]

only thing is how to style on position, because now, it pops up, exactly covering the button…

and tooltip:


Do we need to set the location the tooltip box/container?
I take it all of this:

#    /* Tooltip text */
    .tooltip .tooltiptext {
      visibility: hidden;
      width: 120px;
      background-color: black;
      color: red;
      text-align: center;
      padding: 5px 0;
      border-radius: 6px;

can be set directly, like in the doc’s example for color.

still, not all of these work I think, (Ive commented to ones that dont), using:

  styles:
    tooltip:
      - color: var(--text-color-off)
      - font-size: 10px
      - background: var(--background-color-off)
#      - opacity: 0.5
      - transition: opacity 0.5s
#      - width: 100px
#      - background-color: black # instead use background:
#      - text-align: center # default?
      - padding: 5px
#      - border-radius: 30px
#      - position: absolute
#      - z-index: 1
#      - bottom: 125%
#      - left: 50%
#      - margin-left: -60px

but its getting there :wink:

transition: overrides the default 1.5 sec nicely, above settings make it popup almost immediately, which I like a lot.
Main issue I experience now is the tooltip wont go outside the buttons limits. Is this to be expected? Id love it to pop up outside the button, not covering it.

tooltips on button-card

Hi,

I’m trying to create an if statement that goes like:

“If entity X is off or entity Y is off, then set this, else set that”

It seems as if the OR side of things is the problem because none of the examples that I’ve tried works e.g:

      styles:
        card:
          - box-shadow: |
              [[[
                return states['group.lights_study'].state == 'off' || states['group.windows_study'].state == 'off'
                ? '0px 0px 5px grey': '0px 0px 5px red';
              ]]]
          - box-shadow: |
              [[[
                if ( (states['group.lights_study'].state 
                == 'off') 
                || (states['group.windows_study'].state
                == 'off') 
                ) return '0px 0px 5px grey';
                else return '0px 0px 5px red';
              ]]]

Individually it works ok:

          - box-shadow: |
              [[[
                return states['group.lights_study'].state == 'off'
                ? '0px 0px 5px grey': '0px 0px 5px red';
              ]]]

Does anyone know if this is possible please?

sure, you should put the enclosing ( and ) around the full ‘or’ evaluation. so:

 [[[
    if ( states['group.lights_study'].state == 'off' ||
         states['group.windows_study'].state == 'off' )
    return '0px 0px 5px grey';
    return '0px 0px 5px red';
 ]]]

or

 [[[ 
   return ( states['group.lights_study'].state == 'off' ||
            states['group.windows_study'].state == 'off' )
   ? '0px 0px 5px grey' : '0px 0px 5px red'; 
]]]

note I didn’t check anything else in the template…

Thank you for your help!

Unfortunately neither example worked for me, it seems like there’s a fundamental issue somewhere that prevents the OR from working.

Here is a stripped back button example that I just created to try and test this. For me this doesn’t change the button box shadow when the entities change.

      - type: custom:button-card
        entity: group.windows_study_open
        show_state: true
        show_icon: false
        name: Test
        styles:
          card:
            - border-radius: 15px
            - border: 'solid 1.5px rgb(0,0,0)'
            - font-size: 17px
            - width: 200px
            - padding: 4%
            - box-shadow: |
                [[[
                  return ( states['group.lights_study'].state == 'off' ||
                           states['group.windows_study_open'].state == 'off' )
                  ? '0px 0px 5px grey' : '0px 0px 5px red';
                ]]]

If I just have a single entity in there it works:

      - type: custom:button-card
        entity: group.windows_study_open
        show_state: true
        show_icon: false
        name: Test
        styles:
          card:
            - border-radius: 15px
            - border: 'solid 1.5px rgb(0,0,0)'
            - font-size: 17px
            - width: 200px
            - padding: 4%
            - box-shadow: |
                [[[
                  return ( states['group.windows_study_open'].state == 'off' )
                  ? '0px 0px 5px grey' : '0px 0px 5px red';
                ]]]

copying just 1 of my comparable templates:

      card:
        - animation: >
            [[[ return (states['sensor.hubs_badge'].state > 0 ||
                      states['sensor.critical_badge'].state > 0)
                ? 'blink 2s ease infinite' :'none';
            ]]]

must see if there’s anything in the config preventing this from working… did you try either state in the single template?

btw, if the entity for the button is ‘group.windows_study_open’ you can simply use ‘entity.state’ in the template

Yep, tried either group entity in the single template and they both worked ok. I’m just baffled as to why it’s not working.

Just tried with individual entities in case groups was the problem, but still no luck.

            - box-shadow: |
                [[[
                  return ( states['light.study_desk_lamp'].state == 'off' ||
                           states['binary_sensor.window_study_main_contact'].state == 'off' )
                  ? '0px 0px 5px grey' : '0px 0px 5px red';
                ]]]

Hmm, even trying on another style doesn’t work either:

      - type: custom:button-card
        entity: binary_sensor.window_study_main_contact
        show_state: true
        show_icon: false
        name: Test
        styles:
          card:
            - border-radius: 15px
            - border: 'solid 1.5px rgb(0,0,0)'
            - font-size: 17px
            - width: 200px
            - padding: 4%
            - box-shadow: |
                [[[
                  return ( states['light.study_desk_lamp'].state == 'off' ||
                           states['binary_sensor.window_study_main_contact'].state == 'off' )
                  ? '0px 0px 5px grey' : '0px 0px 5px red';
                ]]]
          name:
            - color: |
                [[[
                  return ( states['light.study_desk_lamp'].state == 'off' ||
                           states['binary_sensor.window_study_main_contact'].state == 'off' )
                  ? 'grey' : 'red';
                ]]]

It just defaults to the first option (grey in the example above). If I swap grey and red text around, text becomes red:
image