A different take on designing a Lovelace UI

Is it possible to add a collapsable button for the bullet points here?

I would suggest to start playing with the overall page layout to see what happens. Look at lines 40-47 of the ui-lovelace-tablet.yaml file. Maybe change the 4 to a 3 or remove some of the columns listed.

Hello every one. How to fix it? I seem to have done everything, as here, but then the card-mod was updated and I see this problem again

Modifying this part just affects the sizes of the tiles. But not about being able to put more than 4 in the same section

in themes/tablet.yaml under

  card-mod-more-info-yaml: |
    .: |

add

      .content:focus-visible {
        outline: none;
      }

example

...
  card-mod-more-info-yaml: |
    .: |
      :host {
        --ha-card-border-width: 0;
      }

      ha-dialog {
          --vertical-align-dialog: var(--tablet-popup-align-dialog) !important;
          --dialog-surface-margin-top: var(--tablet-popup-margin-top) !important;
      } 

      ha-dialog>div.heading>ha-dialog-header {
          font-family: var(--primary-font-family);
          background-color: var(--tablet-popup-header-color);
          border-bottom: var(--tablet-popup-border-style);
      }

      .content:focus-visible {
        outline: none;
      }
1 Like

Many thanks! Another question, this is the popup auto-close timer line, as far as I understand. Is there a way to make it invisible too?

I don’t have that enabled so I’m not sure, but you could try adding this in that same section

      .progress {
        display: none;
      }

Thank you!

the auto timer is configured here

You have to set the media.player entities you want to track in packages/tv_media.yaml.

  - select:
      - name: conditional_media
        state: >
          {% set recently_added = 'Plex Recently Added' %}
          {% set paused_timeout_minutes = 15 %}
          {% set media_players = [
            states.media_player.lr_tv,
            states.media_player.bedroom_apple_tv ] %}

Afterwards you should be renaming the media DEVICE names. Not entity names. For example I have these two: BR Apple TV, LR TV. After doing so, in ui-lovelace.yaml, at the media section, rename the device names to these, and obviously their respective entities must be correct too.

      - type: grid
        title: Media
        view_layout:
          grid-area: entrance
        columns: 1
        cards:

          - type: custom:swipe-card
            parameters:
              speed: 550
              spaceBetween: 40
              threshold: 5
            cards:

              - type: horizontal-stack
                cards:

                  - type: conditional
                    conditions:
                    
                      - entity: select.conditional_media
                        state_not: LR TV

                      - entity: select.conditional_media
                        state_not: BR Apple TV
                        
                    card:
                      type: custom:button-card
                      entity: sensor.plex_recently_added
                      name: Plex Recently Added
                      tap_action:
                        action: none
                      template:
                        - conditional_media
                        - icon_plex

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: LR TV
                    card:
                      type: custom:button-card
                      entity: media_player.lr_tv
                      template:
                        - conditional_media
                        - icon_plex

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: BR Apple TV
                    card:
                      type: custom:button-card
                      entity: media_player.bedroom_apple_tv
                      template:
                        - conditional_media
                        - icon_apple_tv


Looking forward to this day!

After upgrading to the new version of ‘home assistant’, the title text of the pop-up window has become very small and there has been confusion, which is completely different from the previous layout. How can I solve this problem? The image I uploaded is a screenshot provided by a friend in the forum!
20230812034037

SOLVED. For others with the same issue, create a trigger that waits to see if the device comes back on, and then react. It causes a delayed response, but it is better than nothing. This thread helped, and my code is at the end of it: https://community.home-assistant.io/t/automation-trigger-of-state-change-after-being-at-a-state-for-a-time/116494/35

Is anyone else experiencing extra padding for their popup graphs? I’m on 2023.8.1 currently. I tried comparing my popup code to Matt’s but I’m not seeing a difference. I didn’t have this issue with 2023.7.X. I would like to stay with 2023.8.1 unless a fix can’t be found. Here’s a picture with my issue.

The code:

action: fire-dom-event
browser_mod:
  service: browser_mod.popup
  data:
    title: NAS Information
    card_mod:
      style:
        #popup header
        .:
    content:
      type: custom:mod-card
      card_mod:
        style:
          hui-vertical-stack-card:
            $: |
              hui-horizontal-stack-card {
                padding: 0em 2em 2.3em 2em;
              }
            $hui-entities-card:
              $: |
                .card-content {
                  padding: var(--tablet-popup-content-padding);
                  padding-bottom: 0.8em;
                }
                ha-card {
                  border-right: 1.5px solid rgba(0, 0, 0, 0.2);
                  border-radius: 0;
                  transition: none;
                }
                /* portrait */
                @media screen and (max-width: 1200px) {
                  ha-card {
                    border-right: none;
                    border-bottom: 1.5px solid rgba(0, 0, 0, 0.2);
                  }
                }
              $hui-horizontal-stack-card:
                # horizontal bottom buttons
                $: |
                  #root {
                    justify-content: space-evenly;
                    margin-top: 1.7em;
                    max-width: 82vw; /* iphonex */
                  }

      card:
        type: vertical-stack
        cards:
          - type: entities
            state_color: true
            show_header_toggle: false
            card_mod:
              class: header
              style: |
                ha-card {
                  border: none !important;
                }
            entities:
              - entity: sensor.truenas_status
                name: System Status
                icon: cil:synology-nas
    
              - entity: sensor.truenas_temperature_c
                name: CPU Temperature
    
              - entity: sensor.truenas_system_uptime
                name: Last Restart
    
              - type: custom:bar-card
                width: 55%
                height: 2em
                decimal: 0
                unit_of_measurement: '%'
                positions: &bar_card_positions
                  icon: outside
                  indicator: 'off'
                  name: outside
                severity: &bar_card_severity
                  - color: '#6d2525'
                    from: 85
                    to: 999
                entity_row: true
                entities:
    
                  - entity: sensor.truenas_system_cpu_usage
                    name: Processor
                    
                  - entity: sensor.truenas_system_memory_usage
                    name: Memory
    
                  - entity: sensor.nas_storage_usage_rounded
                    name: Storage - 10.7TB
    
              - type: custom:hui-horizontal-stack-card
                cards:  
                  - type: custom:button-card
                    name: Reboot
                    icon: mdi:restart-alert
                    confirmation:
                      text: Are you sure you want to reboot the NAS?
                    tap_action:
                      action: call-service
                      service: browser_mod.sequence
                      service_data:
                        sequence:
                          - service: browser_mod.notification
                            data:
                              message: Rebooting the NAS...
                          - service: rest_command.truenas_reboot
#                  confirm: >
#                    [[[
#                      return `[[[
#                        if (window.confirm('Are you sure you want to reboot the NAS?')) {
#                          hass.callService('browser_mod', 'toast', { message: 'Rebooting the NAS...', duration: 3000 });
#                          hass.callService('rest_command', 'truenas_reboot');
#                        }
#                      ]]]`
#                    ]]]
                    template: icon_name
    
                  - type: custom:button-card
                    state:
                      - value: 'off'
                        icon: mdi:power
                        name: Turn On
                      - value: 'on'
                        icon: mdi:close-circle-outline
                        name: Shutdown
                    entity: switch.truenas
                    tap_action:
                      confirm: >
                        [[[
                          return `[[[
                            if (states['sensor.truenas_status'].state === 'on') {
                              if (window.confirm('Are you sure you want to shutdown the NAS?')) {
                                hass.callService('browser_mod', 'toast', { message: 'Shutting down the NAS...', duration: 3000 });
                                hass.callService('rest_command', 'truenas_shutdown');
                              }
                            } else {
                              hass.callService('browser_mod', 'toast', { message: 'Turning on the NAS...', duration: 3000 });
                              hass.callService('script', 'truenas_turnon');
                            }
                          ]]]`
                        ]]]
                    template: icon_name
    
          - type: custom:mini-graph-card
            hours_to_show: 24
            points_per_hour: 1
            tap_action: none
            entities:
              - entity: sensor.truenas_ada0_c
                name: ada0
              - entity: sensor.truenas_ada1_c
                name: ada1
              - entity: sensor.truenas_ada2_c
                name: ada2
              - entity: sensor.truenas_ada3_c
                name: ada3
              - entity: sensor.truenas_ada4_c
                name: ada4
              - entity: sensor.truenas_ada5_c
                name: ada5
              - entity: sensor.nightstate
                type: area
                color: gray
                name: Night
                show_line: false
                show_points: false
                show_legend: false
                y_axis: secondary
                show_extrema: true
            align_state: left
            height: 220
            hour24: true
            show:
              icon: false
              name: false
              labels: false
              labels_secondary: false
            # Needed to remove bottom padding between graph and popup border
            card_mod:
              style:
                .: |
                  ha-card {
                    margin-bottom: -4px !important;
                  }

Any help is appreciated, thanks!

1 Like

Headers for my popoup’s are messed up after i updated home assistant. Any suggestion what i am missing?

@Mattias_Persson: BIG BIG Thx for this really cool looking Dashboard, it´s very fantastic :slight_smile:

I´ve got soooo many inspirations here, so, in case anyone is interested, i will share my code for my Floor Lamp Icon with state OFF/ON. In my case it is a switch that don´t have any light color :smiley: But if the switch is on, the lights are colored:

My native language is german, so the name and state are in german. Picture left, switch is OFF, right side is ON.

forum_162594

icon_floorlamp:
  styles:
    custom_fields:
      icon:
        - width: 100%
        - margin-left: -10%
  custom_fields:
    icon: >    
       [[[  
        if (variables.state === 'on') {
            return `
              <svg viewBox="0 0 24 24" fill="none">
               <path d="m8.25 22c0-0.4142 0.33579-0.75 0.75-0.75h6c0.4142 0 0.75 0.3358 0.75 0.75s-0.3358 0.75-0.75 0.75h-6c-0.41421 0-0.75-0.3358-0.75-0.75z" clip-rule="evenodd" fill-rule="evenodd" style="fill:#9da0a2"/>
               <path d="M12.0001 8C14.3369 8 16.2992 6.71758 16.8475 4.98449C17.0141 4.45792 16.5524 4 16.0001 4H8.00009C7.4478 4 6.98608 4.45792 7.15266 4.98449C7.70094 6.71758 9.66331 8 12.0001 8Z" style="fill:#9da0a2"/>
               <path d="m12 2c1.6569 0 3 0.89543 3 2h-6c0-1.1046 1.3431-2 3-2z" opacity=".5" style="fill:#ffeb00;opacity:1"/>
               <path d="m6.4548 11.98c0.02295-0.0294 0.04528-0.059 0.067-0.0889 0.7652-1.0545 0.77421-2.448 0.10717-3.498-0.30478-0.47976-0.96798-0.39753-1.3176 0.05002l-2.5321 3.2414c-0.34961 0.4476-0.27389 1.1174 0.25965 1.3043 1.2008 0.4207 2.5847 0.0551 3.4159-1.0089z" style="fill:#9da0a2"/>
               <path d="m12 8c0.2548 0 0.5052-0.01525 0.7498-0.04468v9.9412l2e-4 0.0403v1.0632l-2e-4 0.0158v2.2341h-1.5v-3.3467c-0.0101-1.0339-0.4882-2.0049-1.2951-2.6366l-3.9001-2.8632c0.14374-0.1259 0.27787-0.2672 0.40006-0.4237 0.02294-0.0293 0.04527-0.059 0.06699-0.0889 0.16433-0.2265 0.29378-0.4685 0.38916-0.7195l3.9408 2.8926 0.0117 9e-3c0.1353 0.1051 0.2643 0.2166 0.3865 0.334v-6.4517c0.2447 0.02946 0.4952 0.04472 0.7502 0.04472z" opacity=".5" style="fill:#9da0a2;opacity:1"/>
               <path d="m2.439 8.7863c0.69922-0.8951 1.9852-1.0488 2.8724-0.34332l-2.5321 3.2414c-0.88714-0.7055-1.0395-2.003-0.34026-2.8981z" opacity=".5" style="fill:#ffeb00;opacity:1"/>
              </svg>
            `;
        }
        if (variables.state === 'off') {
            return `
              <svg viewBox="0 0 24 24" fill="none">
                <path d="M9 22H15" stroke="#9da0a2" stroke-width="0.8640000000000001" stroke-linecap="round"/> <path d="M12 22V8" stroke="#9da0a2" stroke-width="0.8640000000000001" stroke-linecap="round"/> <path d="M12.0001 8C14.3369 8 16.2992 6.71758 16.8475 4.98449C17.0141 4.45792 16.5524 4 16.0001 4H8.00009C7.4478 4 6.98608 4.45792 7.15266 4.98449C7.70094 6.71758 9.66331 8 12.0001 8Z" stroke="#9da0a2" stroke-width="0.8640000000000001"/> <path d="M12 2C13.6569 2 15 2.89543 15 4H9C9 2.89543 10.3431 2 12 2Z" stroke="#9da0a2" stroke-width="0.8640000000000001"/> <path d="M12 19V17.9368C12 16.6554 11.4101 15.4467 10.4035 14.6655L6.52181 11.8909M2.7793 11.6844L5.31139 8.44298M2.7793 11.6844C2.4297 12.132 2.50541 12.8018 3.03895 12.9887C4.2398 13.4094 5.62367 13.0438 6.45481 11.9798C6.47776 11.9505 6.50009 11.9208 6.52181 11.8909M2.7793 11.6844C1.89216 10.9789 1.73982 9.6814 2.43904 8.7863C3.13826 7.8912 4.42425 7.73749 5.31139 8.44298M5.31139 8.44298C5.661 7.99543 6.3242 7.9132 6.62898 8.39296C7.29602 9.44296 7.28701 10.8364 6.52181 11.8909" stroke="#9da0a2" stroke-width="0.8640000000000001" stroke-linecap="round"/>
              </svg>
            `;
        }
       ]]]
1 Like

The other one, i like the Neumorphism design, so i´ve made a little change in base.yaml (yeah i know, don´t touch the base…). But because i want it in every card, i put it in there. It´s only one row under “styles → card”:

- box-shadow: "inset 1px 1px 1px 0px rgba(255,255,255,0.2), 4px 4px 5px 1px rgba(0,0,0,0.3)"

It´s looks like this:
forum_162594_button_shadow

Or a different shadow:

- box-shadow: inset 2px 2px 2px 0px rgba(255,255,255,.5), 7px 7px 20px 0px rgba(0,0,0,.1), 4px 4px 5px 0px rgba(0,0,0,.1)

It´s looks like this:
forum_162594_button_shadow_2

I made my footer update like this.

image

is there any way to make a button for updating the update entity beside every line? eg: place an icon with a service call?

code for the popup card

- type: custom:button-card
  entity: sensor.template_current_version
  template: 
    - updates_hass
    - hacs_iframe
  variables:
    available: sensor.template_updates
    latest: sensor.template_latest_version
    hass_core: update.home_assistant_core_update
    hass_supervisor: update.home_assistant_supervisor_update
    hass_operating_system: update.home_assistant_operating_system_update

- type: custom:button-card
  variables:
    updates: sensor.template_updates
    other_updates: sensor.template_other_updates
    hacs_installed: sensor.hacs_installed
  template: 
    - updates
    - hacs_iframe

update template (for the second part, Integrations)

updates:
  template:
    - base_updates
    - settings
  state_display: |
    [[[
      // variables
      let output = '',
          updates = states[variables.updates],
          hacs_installed = states[variables.hacs_installed]?.attributes.repositories,
          other_updates = states[variables.other_updates],
          hacs_update = states['update.hacs_update']?.attributes.installed_version,
          no_updates = variables.translate_no_updates,
          update_available = variables.translate_update_available,
          updates_available = variables.translate_updates_available;

      const rename = a => {
          return a.release_url && a.release_url.indexOf('github.com') > -1
              ? `${a.release_url.split('/')[3]}/${a.release_url.split('/')[4]}`
              : a?.friendly_name;
      };

      // update entities
      Object.keys(states).forEach(key => {
        let s = states[key], e = s.entity_id, a = s.attributes;
        if (e.includes('update.') && !e.includes('update.home_assistant') && s.state === 'on') {
            output += `<li><b><a href="#" onclick="window.open('${a.release_url}');">${rename(a)}</a></b > ${a.installed_version} <b>&rarr;</b> ${a.latest_version}</li>`
        }
      });

      // other updates
      let attr = Object.fromEntries(
          Object.entries(other_updates?.attributes).filter(([, value]) => value != false));
      for (const [, value] of Object.entries(attr)) {
        output += `<li>${value}</li>`;
      }

      // subtitle
      let count = updates?.attributes.update_entities + updates?.attributes.other_updates,
          subtitle = count === 0
              ? `${no_updates} <b>&larr;</b> ${hacs_update || ''}`
              : `${count} ${count === 1 ? update_available : updates_available} ${String.fromCodePoint('0x1f389')}`;

      return `
        <ha-icon icon="mdi:package-up"></ha-icon> <span class="title">Integrations</span><br>
        <p class="subtitle">${subtitle}</p>
        <ul>${output}</ul>
      `;
    ]]]
3 Likes

Hi daniel,

Can you share the hole configuration of you’re setup ? You did mention that you can swipe to see all of your entities for an example. I tried to copy your code but it doesn’t work on Mattias config. I also did added the template before I did a change in the ui file. Doesn’t work. I did start with the batteries and no luck. Plz share the whole setup if you can like Mattias :slight_smile:

update:

i manged to make button for update. But call function is not working.
image

button creation:

      // update entities
      Object.keys(states).forEach(key => {
        let s = states[key], e = s.entity_id, a = s.attributes;
        if (e.includes('update.') && !e.includes('update.home_assistant') && s.state === 'on') {
            output += `
              <li>
                <b><a href="#" onclick="window.open('${a.release_url}');">${rename(a)}</a></b >
                ${a.installed_version} <b>&rarr;</b> ${a.latest_version}
                <button class="service-button" onclick="callService()">Update</button>
              </li>`;
        }
      });

callservice function:

      // Function to call a service
      function callService() {
        hass.callService('light', 'turn_on', { entity_id: 'light.office_group_1' });
      };

BTW I am only trying to turn on a light for testing.
Can any one help me to write the function properly or use such function properly?

1 Like