Lovelace: Button card

You can try setting the title attribute:

  - type: custom:button-card
    name: >

      [[[
         return `<span title="Calendar">Cal</span>`
      ]]]

well not sure anymore, I have tried a lot of things, up to this:

  - type: custom:button-card
    template: button_shortcut_menu
    extra_styles: |
      /* Tooltip container */
      .tooltip {
        position: relative;
        display: inline-block;
      }

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

        /* Position the tooltip text - see examples below! */
        position: absolute;
        z-index: 1;
      }

      /* Show the tooltip text when you mouse over the tooltip container */
      .tooltip:hover .tooltiptext {
        visibility: visible;
      }
    name: >
       [[[ return `<div class='tooltip'><ha-icon icon='mdi:calendar'</ha-icon>
          <span class='tooltiptext'>Tooltip text</span>
        </div>` ]]]

    tap_action:
      action: navigate
      navigation_path: /lovelace/tijd_agenda

which does give me the icon,


and navigates. It simply refuses to give me a tooltip. Even when I simply use the name: Hover here instead of the icon

(which if course is a trick, but using the icon: field doesn’t show an icon…)

You might need to put your mouse there for longer. Try out:

  - type: custom:button-card
    template: button_shortcut_menu
    name: >
       [[[ return `<ha-icon icon='mdi:calendar' title='Calendar'></ha-icon>` ]]]
    tap_action:
      action: navigate
      navigation_path: /lovelace/tijd_agenda

dont understand this really, where’s the tooltip text in your example? You seem to be mixing name, icon and tooltip in 1 go :wink: ?

in all examples online, the tooltip is immediate…

The tooltip text is the title='Calendar' part.

well I be d…

immediately tried this:

    icon: >
      [[[ return `<ha-icon icon='mdi:calendar' title='Calendar'></ha-icon>` ]]]

but the field icon still doesnt show an icon.;-(

now, next challenge, how to get the tooltip to show in the button:

  - type: custom:button-card
    template: button_shortcut_menu
    icon: mdi:light-switch
    tap_action:
      action: navigate
      navigation_path: /lovelace/lights
    variables:
      path: lights
    styles:
      icon:
        - color: >
            [[[
              return (states['group.all_inside_lights'].state == 'on')
              ? 'gold': 'grey';
            ]]]
[[[ return variables.path.replace('_',' ').toUppercase() ]]]

as tooltip

Try removing any other icon declarations. Try this:

    icon: >
      [[[ return `<ha-icon icon='${entity.attributes.icon}' title='${variables.path.replace('_',' ').toUppercase()}'></ha-icon>` ]]]

my buttons don’t have an entity… so I cant use entity.attributes.icon I am afraid. Hence the icon declaration in my current buttons.

maybe use the

[[[ return<ha-icon icon='mdi:light-switch' title=’${variables.path.replace(’_’,’ ‘).toUppercase()}’></ha-icon> ]]]

What about

    variables:
      path: lights
      icon: mdi:light-switch
    icon: >
      [[[ return `<ha-icon icon='${variables.icon}' title='${variables.path.replace('_',' ').toUppercase()}'></ha-icon>` ]]]

I have the following template for a transparent label card and it works fine for most the groups except for lights. When one of the entities in the group turns on, then the label fades out. This happens only on light theme backgrounds. How do I fix this?

transparent_header_card:
  color_type: label-card
  color: transparent
  show_icon: false
  styles:
    card:
      - background-color: transparent
      - box-shadow: none
    name:
      - font-size: 20px
      - text-align: center
      - letter-spacing: '-0.01em'
      - font-weight: bold
              - type: 'custom:button-card'
                template: transparent_header_card
                name: Lights
                entity: group.lights
                tap_action:
                  action: toggle
                confirmation:
                  text: '[[[ return `Are you sure you want to turn on or off all ${entity.attributes.friendly_name}?` ]]]'

Screen Shot 2020-09-12 at 1.15.03 PM Screen Shot 2020-09-12 at 1.15.12 PM

1 Like

Hi Petro,

thank you for help!

i copy an paste your Code with my entities:

type: picture-elements
image: /local/images/transparent_1to1.png
style: |
  ha-card { 
    border-radius: 15px;
  }
elements:
- type: custom:mini-graph-card
  style:
    top: 40%
    left: 50%
    width: 100%
    height: 80%
    translate: translate(-50%, -50%)
    '--paper-card-background-color': 'rgba(0, 0, 0, 0.0)'
    '--ha-card-background': "rgba(0, 0, 0, 0.0)"
    '--ha-card-box-shadow': 'none'
    z-index: 3
    pointer-events: none
  entities:
    - sensor.owm_temperature
  group: true
  points_per_hour: 1
  hour24: true
  line_color: var(--paper-item-icon-active-color)
  line_width: 10
  hours_to_show: 24
  update_interval: 600
  show:
    name: false
    icon: false
    state: false
    points: false
    legend: false
    average: false
    extrema: false
    labels: false
    fill: false
    labels_secondary: false
    name_adaptive_color: false
    icon_adaptive_color: false
- type: custom:button-card
  style:
    top: 50%
    left: 50%
    width: 100%
    translate: translate(-50%, -50%)
  aspect_ratio: 1/1
  entity: sensor.owm_temperature
  color: var(--paper-item-icon-color)
  show_name: true
  show_label: true
  show_icon: true
  show_last_changed: true
  size: 70%
  tap_action:
    action: more-info
    haptic: light
  styles:
    icon:
    - opacity: 0.3
    - width: 100%
    img_cell:
    - top: 0%
    - left: 30%
    - position: absolute
    - z-index: 2
    grid:
    - grid-template-areas: '"info info" "n n" "l l"'
    - grid-template-columns: 40% 1fr
    - grid-template-rows: 1fr min-content min-content
    - position: relative
    card:
    - padding: 10px
    - z-index: 1
    name:
    - justify-self: start
    - align-self: end
    - font-weight: bold
    - font-family: Helvetica 
    - font-size: 12px
    - text-align: start
    - background-image: linear-gradient(to right, white 0%, white 80%, rgba(0,0,0,0))
    - -webkit-background-clip: text
    - -webkit-text-fill-color: transparent
    - position: relative
    - display: inline-block
    - width: 100%
    - align-content: start
    - text-align: start
    - text-overflow: unset
    - z-index: 5
    label:
    - justify-self: start
    - align-self: end
    - font-weight: bold
    - font-family: Helvetica 
    - font-size: 12px
    - text-align: start
    - background-image: linear-gradient(to right, var(--paper-item-icon-color) 0%, var(--paper-item-icon-color) 80%, rgba(0,0,0,0))
    - -webkit-background-clip: text
    - -webkit-text-fill-color: transparent
    - position: relative
    - display: inline-block
    - width: 100%
    - align-content: start
    - text-align: start
    - text-overflow: unset
    - z-index: 5
    custom_fields:
      info:
      - align-self: start
      - width: 40%
      - z-index: 5
  custom_fields:
    info: >
      [[[
        var entity_id = (entity === undefined) ? 'Invalid Entity' : entity.entity_id;
        var statestr = (entity === undefined || entity.state === undefined) ? null : entity.state;
        var units = (statestr && entity.attributes.unit_of_measurement) ? entity.attributes.unit_of_measurement : null;
        var date = (statestr && entity.attributes.device_class === 'timestamp') ? new Date(statestr) : null;
        var value;
        if (statestr && date === null) {
          if (statestr.split('.').length - 1 <= 1){
            var test = parseFloat(parseFloat(statestr).toFixed(2));
            value = (isNaN(test)) ? null : test;
            // test if units are in the state because some sensors are stupid.  Looking
            //   at you synology.
            const expr = /[^-.0-9]+/;
            var has_units = expr.test(statestr.trim());
            // console.log(`${entity_id}: "${statestr}" ${matches}`);
            if (value && has_units)
              units = statestr.replace(/[.0-9]+/, ''); 
          }
        }
        // console.log(`${entity_id}: ${statestr}, ${units}, ${date}, ${value}`);
        const length = 50;
        const width = 3;
        var radius = length / 2;
        if (date){
          let now = new Date();
          var tdelta = Math.floor((now - date)/1000);
          // console.log(`${entity_id}: ${tdelta}`);
          function plural(descriptor, divisor){
            var ret = Math.floor(tdelta/divisor);
            return (ret == 1) ? [ret, descriptor] : [ret, `${descriptor}s`];
          }
          var values;
          if (tdelta < 60)
            values = plural('second', 1);
          else if (tdelta < 60 * 60)
            values = plural('minute', 60);
          else if (tdelta < 60 * 60 * 24)
            values = plural('hour', 60 * 60);
          else if (tdelta < 7 * 60 * 60 * 24)
            values = plural('day', 60 * 60 * 24);
          else
            values = plural('week', 7 * 60 * 60 * 24);
          return `
            <svg viewBox="0 0 50 50">
              <circle cx="25" cy="25" r="${radius}" fill="var(--paper-item-icon-active-color)" />
              <text x="50%" y="43%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${values[0]}<tspan x="50%" dy="1.2em" font-size="10" font-weight="normal" >${values[1]}</tspan>
              </text>
            </svg>
            `;
        }
        else if (value && units && units === '%') {
          radius = (length - 3) / 2;
          const circumference = radius * 2 * Math.PI;
          return `
            <svg viewBox="0 0 50 50">
              <circle cx="25" cy="25" r="${radius}" fill="none" stroke="var(--paper-item-icon-color)" opacity="0.5" stroke-width="${width}" />
              <circle style="
                  transform: rotate(-90deg);
                  transform-origin: 50% 50%;
                  stroke-dasharray: ${circumference};
                  stroke-dashoffset: ${circumference - value / 100 * circumference};
                "
                id="c_brightness" cx="25" cy="25" r="${radius}" stroke="var(--paper-item-icon-active-color)" stroke-width="${width}" fill="none" stroke-linecap="round" />
              <text x="50%" y="54%" fill="var(--primary-text-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan font-size="10" font-weight="normal" >%</tspan>
              </text>
            </svg>
            `;
          }
        else if (value && units && units.includes('°')) {
          return `
            <svg viewBox="0 0 50 50">
              <circle cx="25" cy="25" r="${radius}" fill="var(--paper-item-icon-active-color)" />
              <text x="50%" y="54%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan font-size="10" font-weight="normal" >${units}</tspan>
              </text>
            </svg>
            `;
        }
        else if (value && units && units.length > 1) {
          var y = (String(value).length > units.length) ? "50%" : "43%";
          return `
            <svg viewBox="0 0 50 50">
              <circle cx="25" cy="25" r="${radius}" fill="var(--paper-item-icon-active-color)" />
              <text x="50%" y="${y}" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan x="50%" dy="1.2em" font-size="10" font-weight="normal" >${units}</tspan>
              </text>
            </svg>
            `;
          }
        else if (value) {
          return `
            <svg viewBox="0 0 50 50">
              <circle cx="25" cy="25" r="${radius}" fill="var(--paper-item-icon-active-color)" />
              <text x="50%" y="54%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${value}<tspan font-size="10" font-weight="normal" >${units}</tspan>
              </text>
            </svg>
            `;
        }
        return `
            <svg viewBox="0 0 50 50">
              <circle cx="25" cy="25" r="${radius}" fill="var(--paper-item-icon-active-color)" />
              <text x="50%" y="54%" fill="var(--paper-card-background-color)" font-weight="bold" font-size="14" text-anchor="middle" alignment-baseline="middle">${statestr}
              </text>
            </svg>
            `; 
      ]]]

but it doesn’t show me anything and I have no error in the log or anything.

nope, sorry. as long as I use the icon: field, no icon is displayed using the templates we tried.


I can use the name field and have the icon displayed, but then it appears is an incorrect format:

also, it doesnt like the template, so above I took that out for testing purposes, trying to take it one step at a time…

button-card.js?v=3.3.6:1643 ButtonCardJSTemplateError: TypeError: variables.path.replace(...).toUppercase is not a function in 'return `<ha-icon icon='mdi:light-switch' title='${variables.path.replace('_',' ').toUppercase()}'>...

all in all, it seems this is either not possible, or we need the hand of the author to make it possible. Hope Rom is having a look anytime soon…

I guess, what would be easiest is a dedicated tooltip variable, set that in the button_card template as follows:

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)
# add a new styles field for the tooltip here
      - tooltip: >
          [[[ return variables.tooltip ]]]
    card:
      - box-shadow: none
      - background: >
          [[[ return variables.view == variables.path
              ? 'var(--secondary-background-color)' : 'var(--card-background-color)';
          ]]]
  extra_styles: |
    /* Tooltip container */
    .tooltip {
      position: relative;
      display: inline-block;
      border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
    }

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

      /* Position the tooltip text - see examples below! */
      position: absolute;
      z-index: 1;
    }

    /* Show the tooltip text when you mouse over the tooltip container */
    .tooltip:hover .tooltiptext {
      visibility: visible;
    }

and then set the button card config like:

  - type: custom:button-card
    template: button_shortcut_menu
    icon: mdi:light-switch
    variables:
      path: lights
      tooltip: Light panel  # <----
    tap_action:
      action: navigate
      navigation_path: /lovelace/lights
    styles:
      icon:
        - color: >
            [[[
              return (states['group.all_inside_lights'].state == 'on')
              ? 'gold': 'grey';
            ]]]

for now I’m forced to go back to my tooltip-less shortcut menu bar :wink:

Capitialization:

    variables:
      path: lights
      icon: mdi:light-switch
    icon: >
      [[[ return `<ha-icon icon='${variables.icon}' title='${variables.path.replace('_',' ').toUpperCase()}'></ha-icon>` ]]]

toUppercase toUpperCase

Is there anyway I can get a camera view to take up the whole of the button space please? No matter what I do, I get a small snapshot in a larger button

type: 'custom:button-card'
entity: camera.front_door
show_entity_picture: 'true'
styles:
  card:
    - height: 300px

Nicely spotted. thanks.

doesnt work though, no icon using the icon field… (error has gone , so that’s good :wink: )

have a look:

button-card-template:

button_shortcut_menu:
  variables:
    dashboard: >
      [[[ return window.location.pathname.split('/')[1] ]]]
    view: >
      [[[ return window.location.pathname.split('/').slice(-1) ]]]
  size: 25px
  icon: >
    [[[ return `<ha-icon icon='${variables.icon}' title='${variables.path.replace('_',' ').toUpperCase()}'></ha-icon>` ]]]
  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)';
          ]]]
  extra_styles: |
    /* Tooltip container */
    .tooltip {
      position: relative;
      display: inline-block;
      border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
    }

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

      /* Position the tooltip text - see examples below! */
      position: absolute;
      z-index: 1;
    }

    /* Show the tooltip text when you mouse over the tooltip container */
    .tooltip:hover .tooltiptext {
      visibility: visible;
    }

and buttons like:

  - type: custom:button-card
    template: button_shortcut_menu
    variables:
      path: home
      icon: mdi:home
    tap_action:
      action: navigate
      navigation_path: /lovelace/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

  - type: custom:button-card
    template: button_shortcut_menu
#    icon: mdi:light-switch
    variables:
      path: lights
      icon: mdi:light-switch
    tap_action:
      action: navigate
      navigation_path: /lovelace/lights
    styles:
      icon:
        - color: >
            [[[
              return (states['group.all_inside_lights'].state == 'on')
              ? 'gold': 'grey';
            ]]]

this works ok for the icon to show

  icon: >
    [[[ return variables.icon ]]]

though somehow my background color gets killed…

type: 'custom:button-card'
entity: camera.front_door
show_entity_picture: 'true'
styles:
  card:
    - height: 300px
size: 100%

should work I think

1 Like

perfect thank you… it was that simple :smiley:

Any idea how often the thumbnail refreshes please?

First of all, completely remove the extra_styles. You don’t have to, but you should.
I think it might be that the way that button-card renders the icons ha-icon won’t work. We’ll see what happens…

Probably as often as the entity_picture refreshes and button-card bothers to check…