A different take on designing a Lovelace UI

thanks for your time anyway

looks like you’ve cloned my repo. install.md doesn’t tell you to do that

all my accounts are Administrator.

It might be faster to just start a new install of HA from fresh, I needed to restart 3 or 4 times myself.

and this time don’t clone the repo, only move the files over when called out in the install.md.

@Mattias_Persson, I did find it odd that he had a secrets_redacted.yaml, and no secrets.yaml in the provided screenshot. but if that was the case he would not have gotten green in the config validation screenshot

@Faecon says they have !secret homeassistant_latitude in configuration.yaml
secrets.yaml doesn’t exist in the screenshot, that would absolutely log errors.

I am playing around in the light.yaml template trying to find a way to have it show scene buttons dependant on what entity the pop-up is called for.

But I can’t for the life of me understand how to achieve this correctly.
I first tried attaching the extra card to the lights.push section, then realised that duplicates the scene card for every light entry.
Only other “valid” way of arranging the code that I found is below, but I seem to only be able yo return one of the sets of data (either return lights; or return buttons;)

light:
  template:
    - base
    - circle
    - loader
  double_tap_action:
    action: fire-dom-event
    browser_mod:
      service: browser_mod.popup
      data:
        title: >
          [[[
            return !entity || entity.attributes.friendly_name;
          ]]]
        content:
          type: entities
          card_mod:
            style: |
              #states {
                padding-top: 0.5em;
              }
          entities: >
            [[[
              if (entity.attributes.friendly_name === 'Twi-lights') {
                  let lights = [],
                      buttons = [],
                      id = Boolean(entity.attributes.entity_id)
                          ? [entity.entity_id].concat(entity.attributes.entity_id)
                          : [entity.entity_id];
                  for (let i = 0; i < id.length; i++) {
                      lights.push({
                          "type": "custom:mushroom-light-card",
                          "entity": id[i],
                          "fill_container": false,
                          "primary_info": "name",
                          "secondary_info": "state",
                          "icon_type": "icon",
                          "use_light_color": true,
                          "show_brightness_control": true,
                          "show_color_temp_control": true,
                          "show_color_control": true,
                          "collapsible_controls": false,
                          "layout": "default"
                      });
                  }
                  buttons.push({
                      "type": "custom:mushroom-chips-card",
                      "chips": [
                        {
                          "type": "action",
                          "icon_color": "pink",
                          "icon": "mdi:palette-outline",
                          "tap_action": {
                            "action": "call-service",
                            "service": "scene.turn_on",
                            "target": {
                              "entity_id": "scene.colourful"
                            }
                          },
                          "card_mod": {
                            "style": "ha-card {--chip-background: rgba(var(--rgb-pink), 0.2);}"
                          }
                        }
                      ]
                  });
                  return buttons;
              }
              if (entity) {
                  let lights = [],
                      id = Boolean(entity.attributes.entity_id)
                          ? [entity.entity_id].concat(entity.attributes.entity_id)
                          : [entity.entity_id];
                  for (let i = 0; i < id.length; i++) {
                      lights.push({
                          "type": "custom:mushroom-light-card",
                          "entity": id[i],
                          "fill_container": false,
                          "primary_info": "name",
                          "secondary_info": "state",
                          "icon_type": "icon",
                          "use_light_color": true,
                          "show_brightness_control": true,
                          "show_color_temp_control": true,
                          "show_color_control": true,
                          "collapsible_controls": false,
                          "layout": "default"
                      });
                  }
                  return lights;
              }
            ]]]
  variables:
    circle_input: >
      [[[
        if (entity) {
            // if light group get brightness from child to remove bounce
            let child = entity.attributes.entity_id,
                brightness = child && states[child[0]].attributes.brightness
                    ? Math.round(states[child[0]].attributes.brightness / 2.54)
                    : Math.round(entity.attributes.brightness / 2.54);
            return brightness === 0 && entity.state !== 'off'
                ? 1
                : brightness
        }
      ]]]
    circle_input_unit: "%"

I’ve done a bunch of googling to try and understand how to template this without luck. I suspect I don’t need to be using button.push at all, but am unsure how to append the code that follows otherwise.

I’m also certain there’s a way to append the code to the original if (entity) section with if (entity.attributes.friendly_name === 'Twi-lights') prefixing the card I want to add from within it.

Someone, enlighten my feeble brain!

what is in the config folder? is it possible that you have added the above files to the wrong location?

@nullae, it is possible to do what you want but I don’t think you should.

I would copy the full light card code and add a new template called light_with_scene

then modify that to have the seen button, any light group that has a scene use the new template.
I can’t think of a reason why not to use this approach, this way if / wen the light template gets any updates, your scene cards will still work and can be updated when you have time.

Did anyone else have the problem, that if u click on a light button, only the loader appears, but the light didnt go on/off?
If I double click, the popup appears and I click on the icon the light go on/off.
image

Even homekit works, only the button on my dashboard didnt work.

all working ok for me

That makes a lot of sense.

The wall I’m hitting however is that regardless of making a copy of the template, is that I can’t seem to figure out how to add the extra scene cards into the code that the light template uses.

I don’t have a great understanding of how to template in this way, so I haven’t managed to get the pop-up to display both cards together while still having the light card auto-populate entities based on the group that calls it.

oh ok then, this is an example I just throw together

light:
  template:
    - base
    - circle
    - loader
  double_tap_action:
    action: fire-dom-event
    browser_mod:
      service: browser_mod.popup
      data:
        title: >
          [[[
            return !entity || entity.attributes.friendly_name;
          ]]]
        content:
          type: vertical-stack
          cards:
            - type: entities
              card_mod:
                style: |
                  #states {
                    padding-top: 0.5em;
                  }
              entities: >
                [[[
                  if (entity) {
                      let lights = [],
                          id = Boolean(entity.attributes.entity_id)
                              ? [entity.entity_id].concat(entity.attributes.entity_id)
                              : [entity.entity_id];

                      for (let i = 0; i < id.length; i++) {
                          lights.push({
                              "type": "custom:mushroom-light-card",
                              "entity": id[i],
                              "fill_container": false,
                              "primary_info": "name",
                              "secondary_info": "state",
                              "icon_type": "icon",
                              "show_brightness_control": true,
                              "use_light_color": true,
                              "show_color_temp_control": true,
                              "show_color_control": true,
                              "collapsible_controls": true
                          });
                      }
                      return lights;
                  }
                ]]]
            - type: custom:mod-card
              card_mod:
                style:
                  hui-horizontal-stack-card$: |
                    #root {
                      justify-content: space-evenly !important;
                      padding: var(--tablet-popup-button-padding);
                    }
              card:
                type: horizontal-stack
                cards:
                  - type: custom:button-card
                    name: scene 1
                    icon: mdi:fire

                  - type: custom:button-card
                    name: scene 2
                    icon: mdi:party-popper
  variables:
    circle_input: >
      [[[
        if (entity) {
            // if light group get brightness from child to remove bounce
            let child = entity.attributes.entity_id,
                brightness = child && states[child[0]].attributes.brightness
                    ? Math.round(states[child[0]].attributes.brightness / 2.54)
                    : Math.round(entity.attributes.brightness / 2.54);
            return brightness === 0 && entity.state !== 'off'
                ? 1
                : brightness
        }
      ]]]
    circle_input_unit: '%'

so in the code above entities: is just the entities section of a normal entities card, if you look at other popups, you will see that content can only be passed one card, the way around this is to pass a layout card or in this case a vertical-stack, then the vertical-stack can be passed the entities card, and our new card, in this case just a horizontal-stack with some buttons, but you can replace that with your example from above.

The hard part is going to be getting the list of scenes passed to the template to dynamically create the buttons

2 Likes

that was Fun

after little more time this is what I have

light:
  template:
    - base
    - circle
    - loader
  double_tap_action:
    action: fire-dom-event
    browser_mod:
      service: browser_mod.popup
      data:
        title: >
          [[[
            return !entity || entity.attributes.friendly_name;
          ]]]
        content:
          type: vertical-stack
          cards:
            - type: entities
              card_mod:
                style: |
                  #states {
                    padding-top: 0.5em;
                  }
              entities: >
                [[[
                  if (entity) {
                      let lights = [],
                          id = Boolean(entity.attributes.entity_id)
                              ? [entity.entity_id].concat(entity.attributes.entity_id)
                              : [entity.entity_id];
                      for (let i = 0; i < id.length; i++) {
                          lights.push({
                              "type": "custom:mushroom-light-card",
                              "entity": id[i],
                              "fill_container": false,
                              "primary_info": "name",
                              "secondary_info": "state",
                              "icon_type": "icon",
                              "show_brightness_control": true,
                              "use_light_color": true,
                              "show_color_temp_control": true,
                              "show_color_control": true,
                              "collapsible_controls": true
                          });
                      }

                      return lights;
                  }
                ]]]
            - type: custom:mod-card
              card_mod:
                style:
                  hui-horizontal-stack-card$: |
                    #root {
                      justify-content: space-evenly !important;
                      padding: var(--tablet-popup-button-padding);
                    }
              card:
                type: horizontal-stack
                cards: >
                  [[[
                    if (variables.scene_groupe) {
                      console.log(states);
                      console.log(variables.scene_groupe);

                      let scenes = [];
                      for (let i = 0; i < variables.scene_groupe.length; i++) {
                        let e = "scene." + variables.scene_groupe[i]
                          scenes.push({"type": "custom:mushroom-chips-card",
                          "alignment": "center",

                        "chips":[
                        {
                          "type": "entity",
                          "entity": e,
                          "content_info": "name",
                          "tap_action": {
                            "action": "call-service",
                            "service": "scene.turn_on",
                            "target": {
                              "entity_id": e
                            }
                            }
                          }
                        ]
                    });
                      }
                      return scenes;

                    }
                    return []
                  ]]]
  variables:
    circle_input: >
      [[[
        if (entity) {
            // if light group get brightness from child to remove bounce
            let child = entity.attributes.entity_id,
                brightness = child && states[child[0]].attributes.brightness
                    ? Math.round(states[child[0]].attributes.brightness / 2.54)
                    : Math.round(entity.attributes.brightness / 2.54);
            return brightness === 0 && entity.state !== 'off'
                ? 1
                : brightness
        }
      ]]]
    circle_input_unit: '%'

used

- type: custom:button-card
  entity: light.light_kitchen_cabinet
  name: Cabinet
  template:
    - light
    - icon_wled
  variables:
    scene_groupe: ['t1','t2']

2 Likes

Oh this is fantastic.

I knew I was going to struggle with card mod a bit to get things displaying nicely, but the dynamic scenes might have been beyond me!

This will be a useful reference for turning other pop-ups I have into templates too.

Thank you so much!

happy to help, as I said this one was fun.

I would like to auto add the scenes based on if the scene has any of the provided lights in it. im going to give that a go now.

if you have any other issues feel free to ask, I love that you had made a good attempt and I could see what you wanted based on the information that you provided.

1 Like

and we have improvements, @Mattias_Persson, this might be something to add to the base repo, it could use some css magic

now it should auto detect any scenes that use any of the lights and add them, if you have a light but you don’t want the scenes to be added then you can add the following on the button card

  variables:
    show_scenes: false

templates

light:
  template:
    - base
    - circle
    - loader
  double_tap_action:
    action: fire-dom-event
    browser_mod:
      service: browser_mod.popup
      data:
        title: >
          [[[
            return !entity || entity.attributes.friendly_name;
          ]]]
        content:
          type: vertical-stack
          cards:
            - type: entities
              card_mod:
                style: |
                  #states {
                    padding-top: 0.5em;
                  }
              entities: >
                [[[
                  if (entity) {
                      let lights = [],
                          id = Boolean(entity.attributes.entity_id)
                              ? [entity.entity_id].concat(entity.attributes.entity_id)
                              : [entity.entity_id];
                      for (let i = 0; i < id.length; i++) {
                          lights.push({
                              "type": "custom:mushroom-light-card",
                              "entity": id[i],
                              "fill_container": false,
                              "primary_info": "name",
                              "secondary_info": "state",
                              "icon_type": "icon",
                              "show_brightness_control": true,
                              "use_light_color": true,
                              "show_color_temp_control": true,
                              "show_color_control": true,
                              "collapsible_controls": true
                          });
                      }

                      return lights;
                  }
                ]]]
            - type: custom:mod-card
              card_mod:
                style:
                  hui-horizontal-stack-card$: |
                    #root {
                      justify-content: space-evenly !important;
                      padding: var(--tablet-popup-button-padding);
                    }
              card:
                type: horizontal-stack
                cards: >
                  [[[
                    if (entity) {
                      let id = Boolean(entity.attributes.entity_id)
                            ? [entity.entity_id].concat(entity.attributes.entity_id)
                            : [entity.entity_id];
                      let foundSenes = Object.keys(states).filter(s => s.indexOf("scene.") > -1).map(s=>states[s]).filter(s=>s.attributes.entity_id.some(e=>id.includes(e))),
                      scenes = [];
                      for (let i = 0; i < foundSenes.length; i++) {
                        scenes.push({"type": "custom:mushroom-chips-card",
                          "alignment": "center",
                          "chips":[
                          {
                            "type": "entity",
                            "entity": foundSenes[i].entity_id,
                            "content_info": "name",
                            "tap_action": {
                              "action": "call-service",
                              "service": "scene.turn_on",
                              "target": {
                                "entity_id": foundSenes[i].entity_id
                              }
                              }
                            }
                          ]
                      });
                      }
                      return variables.show_scenes? scenes: [];
                    }
                  ]]]
  variables:
    show_scenes: true
    circle_input: >
      [[[
        if (entity) {
            // if light group get brightness from child to remove bounce
            let child = entity.attributes.entity_id,
                brightness = child && states[child[0]].attributes.brightness
                    ? Math.round(states[child[0]].attributes.brightness / 2.54)
                    : Math.round(entity.attributes.brightness / 2.54);
            return brightness === 0 && entity.state !== 'off'
                ? 1
                : brightness
        }
      ]]]
    circle_input_unit: '%'

3 Likes

Slick as.

Other than some strange scrollbar behaviour, this is perfect.

On PC, depending on screen layout, entity count (I have 5 including the parent group) and which lights are toggled on/off, both vertical and horizontal scrollbars can appear and disappear in very unpredictable ways.

It’s a very small scroll, and isn’t very noticeable on mobile without deliberately dragging.

try replacing --tablet-popup-button-padding with --tablet-card-content-padding

No luck unfortunately.

I’m not sure if the hui-horizontal-stack-card$ or perhaps mod-card itself is functioning in the card at all, I can’t seem to change or add anything there to any effect.

I can confirm that hui-horizontal-stack-card$ is working, I set it to 1000px and could see the change,

FYI if you change any template file or file added via include to a dashboard, you need to also make a change to ui-lovelace.yaml for the change to take effect, this is a home assistant “issue”.

Just remove a letter, save add the same letter back and then save again. if you dont see this message then your change might not take effect

for me on a Mac, using chrome. I can get vertical scrolling but not horizontal even with 6 scenes and long names on my lights.


Oh yeah, adding 1000px defs has an effect (I’m the worst at using or understanding cardmod haha)

I use

alias: Reload lovelace
sequence:
  - service: browser_mod.javascript
    data:
      code: lovelace_reload()
mode: single

mapped to a keyboard shortcut using hass-agent to deal with the updating!

2 Likes