A different take on designing a Lovelace UI

Thanks. Yes so we were in the same boat. Programming is not always a pro when working with projects I’ve learned. Conditional media for me was also weird mostly because I kept trying to apply logic and syntax from JS frameworks which is obviously not the correct syntax.

I’m working on the video now. I’ve added some new stuff lately too such as pet detection with a customized frigate NVR etc. I am considering doing several video tutorials because my prior text ones seem to be too much for normal users to follow.

I adore this community but despite most of us being geeks there are plenty of people just starting out and I think HA really shines for them too.

This is amazing. Thank you.

Finally done and ready to share some of my screenshots
I kept the dashboard pretty vanilla, but with some small changes/additions specific to my usecase:

Main dashboard:

Alternative to Media for me, is a remote, for when I have a cat laying on me, and can’t reach the physical remote:
image

Pop-up for environment sensors such as the bottom left of the first block of four called “Woonkamer”
It’s not perfect, but it gives the information I want at a glance, hovering over the graphs gives the actual values in a small popup tooltip
image

Ventilation popup

Garbage popup is nothing more than next garbage days:
image

Weather popup

Doorbell popup

OpnSense popup
image

I think that’s mostly it.
As I said, a lot is just default, but some custom adjustments
Still needs some work here and there, not happy with every popup, but overall it works very well for me :slight_smile:

8 Likes

If anyone is willing:
I want to make an XBOX animated logo. I currently have one that fills the X with green, but am having trouble adding a glow on the outside of the logo. Ideally, I would like it to be the ‘white’ glow around the whole logo that shows up after the green fill and lasts a second. It would be cool if the green would glow in the sections up top that have a gap for the X but that might be stretching it.

Here is what I have so far: XBOX Animated Logo - JSFiddle - Code Playground

PS: I have made a repository of icons that I have made. If anyone would like icons they have made, feel free to reach out and I will add them. I think it would be nice to have different ones in one place instead of searching through this massive thread. Link: GitHub - LilTrublMakr/Home-Assistant-Icons

Hi Mattias,
First thanks for sharing your great work.
I have a problem and I will appriciate your help here:

  1. I have both adjustable brightness light that are showing and working well, but must of my light are ON\OFF switches and the precentage in the circle are showing just % without a number, how I can configure it to show OFF when in Off state and 100% when in On state?
    image

Thanks for your help.

Hi Mason,

Maybe another question,

I would like to use a static image as conditional media place holder when nothing is playing.

currently using:

                  card:
                    type: picture
                    image: /local/waiting5.png
                    name: Media console
                    tap_action:
                      action: none
                    template:
                      - conditional_media

but It is not so nice, would like to use custom:button-card.
Cant figure out the needed adjustments in media.yaml
Many thanks.

use base instead

I am SO looking forward to this video.

2 Likes

so you would like a button card that just shows a static image?

add a new template file named static_image.yaml

static_image:
  show_state: false
  template:
    - base
  variables:
    path: background.png
  styles:
    card:
      - background-color: none
      - background-size: cover
      - background-position: center
      - background-image: >
          [[[
            let path = `/local/${variables.path}`
            return `url(${path})`;
          ]]]

and use it like so

- type: custom:button-card
  template:
    - static_image
  variables:
    path: img/Switch.jpeg

this is what it looks like, if you don’t set a path it will use the background image

Thanks Mattias

Does anyone know why my node red starts to crash and my tablet hangs in update and not updating the clock, whenever i add the sidebar.yaml??

> [22:13:46] INFO: Starting Node-RED...
> start
> node $NODE_OPTIONS node_modules/node-red/red.js "--settings" "/etc/node-red/config.js"
21 Nov 22:13:50 - [info] 
Welcome to Node-RED
===================
21 Nov 22:13:50 - [info] Node-RED version: v3.0.2
21 Nov 22:13:50 - [info] Node.js  version: v16.17.1
21 Nov 22:13:50 - [info] Linux 5.15.61-v8 arm64 LE
21 Nov 22:13:51 - [info] Loading palette nodes
Mon, 21 Nov 2022 21:13:55 GMT node-telegram-bot-api deprecated Automatic enabling of cancellation of promises is deprecated.
In the future, you will have to enable it yourself.
See https://github.com/yagop/node-telegram-bot-api/issues/319. at node:internal/modules/cjs/loader:1126:14
21 Nov 22:13:59 - [info] Dashboard version 3.2.0 started at /endpoint/ui
21 Nov 22:14:00 - [warn] ------------------------------------------------------
21 Nov 22:14:00 - [warn] [node-red-contrib-telegrambot-home/bot] 'telegrambot-config' already registered by module @danielnguyen/node-red-contrib-telegrambot-home
21 Nov 22:14:00 - [warn] [node-red-contrib-telegrambot-home/command] 'telegrambot-command' already registered by module @danielnguyen/node-red-contrib-telegrambot-home
21 Nov 22:14:00 - [warn] [node-red-contrib-telegrambot-home/switch] 'telegrambot-switch' already registered by module @danielnguyen/node-red-contrib-telegrambot-home
21 Nov 22:14:00 - [warn] [node-red-contrib-telegrambot-home/notify] 'telegrambot-notify' already registered by module @danielnguyen/node-red-contrib-telegrambot-home
21 Nov 22:14:00 - [warn] [node-red-contrib-telegrambot-home/payload] 'telegrambot-payload' already registered by module @danielnguyen/node-red-contrib-telegrambot-home
21 Nov 22:14:00 - [warn] ------------------------------------------------------
21 Nov 22:14:00 - [info] Settings file  : /etc/node-red/config.js
21 Nov 22:14:00 - [info] Context store  : 'default' [module=memory]
21 Nov 22:14:00 - [info] User directory : /config/node-red/
21 Nov 22:14:00 - [warn] Projects disabled : editorTheme.projects.enabled=false
21 Nov 22:14:00 - [info] Flows file     : /config/node-red/flows.json
21 Nov 22:14:00 - [info] Server now running at http://127.0.0.1:46836/
[22:14:00] INFO: Starting NGinx...
21 Nov 22:14:01 - [info] Starting flows
21 Nov 22:14:02 - [info] Started flows
21 Nov 22:14:02 - [info] [mqtt-broker:701d4c9a.51c814] Connected to broker: mqtt://192.168.1.47:1883
21 Nov 22:14:04 - [error] [api-current-state:someone i home?] InputError:  group.anyone_home
21 Nov 22:14:06 - [info] [server:Home Assistant] Connecting to http://supervisor/core
21 Nov 22:14:06 - [info] [server:Home Assistant] Connected to http://supervisor/core
Received state update for unknown entity sensor.template_sidebar
Received event for unknown subscription 20. Unsubscribing.
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar
Received state update for unknown entity sensor.template_sidebar

SIDEBAR code

- sensor:
    - unique_id: sidebar
      state: template
      attributes:
        time: >
          {% set hours = now().strftime('%H') %}
          {% set minutes = now().strftime('%M') %}
          <span class="time">
            {{ hours }}<span class="time-colon">:</span>{{ minutes }}
          </span>
        date: |
          <font color='#6a7377'><b>
          {%- if strptime(states('sensor.date'), '%Y-%m-%d').day != null %}
          {%- set days = ['Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag', 'Søndag'] %}
          {%- set months = ['Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni',
          'Juli', 'August', 'September', 'Oktober', 'November', 'December'] %}
            {{- days[now().weekday()] }}<br>
            {{- strptime(states('sensor.date'), '%Y-%m-%d').day }} {{ months[now().month-1] }}
          {%- endif -%}
          </b></font>
        heatoff: |
          {% if is_state('input_boolean.clima_off_outside_temp', 'off') -%}
            Klima: varme slukket
          {%- else %}
            Klima: varme er tændt
          {%- endif %}
        Clima: |
          {%- set clima = states('sensor.median_humidity_rooms') %}
          {% if not is_state('sensor.median_humidity_rooms', 'unknown') %}
            {%- if clima | float(default=0) <= 60 -%}
            Klima OK {{clima}}%
            {%- elif clima | float(default=0) > 60 -%}
            <font color='#e01b1e'>Fugtigheden er for høj {{clima}}%  </font>
            {%- endif %}
          {%- else %}
            kan ikke måle fugtigheden 
          {%- endif %}
        elpris: |
          {%- set elpris = states('sensor.nordpool_kwh_dk2_dkk_3_099_025') %}
          {% if elpris | float(default=0) >= 0.0 -%}
          {{-'\u26a1'}} {{elpris}} kr. pr kWh
          {%- else %}
            Kan ikke indlæse elpris
          {%- endif %}
        weatherforecast: |
          {%- set temperature = states('sensor.weather_hjem_temperature_forecast_today') %}
          {%- set apparent = states('sensor.hjem_realfeel_temperature_max_0d') | round %}
          {%- set precip = states('sensor.weather_precipitation_probability') | round %}
          {%- set windforecast = states('sensor.weather_hjem_wind_forecast_today') | round %}
          {% if not is_state('sensor.pirateweather_temperature', 'unknown') %}
          {% if is_state('binary_sensor.morning_weather', 'on') -%}
              Vejret i dag: Temp. {{temperature}}°, Feel max {{ apparent}}°, vind {{windforecast}} m/s., risko for nedbør {{ precip }}%
            {%- endif %}
          {%- else %}
            Kan ikke indlæse vejret....
          {%- endif %}
        weather: |
          {%- set temperature = states('sensor.weather_outside_temperature') %}
          {%- set apparent = states('sensor.hjem_realfeel_temperature') | round %}
          {%- set precip = states('sensor.weather_precipitation_probability') | round %}
          {%- set wind = states('sensor.weather_hjem_windspeed_current') | round %}
          {% if not is_state('sensor.weather_outside_temperature', 'unknown') %}
            {%- if temperature | float(default=0) <= 0.0 -%}
            Temp er {{temperature}}° men føles som {{ apparent}}°, med en vind på {{wind}} m/s. og {{ precip }}% risiko for sne {{'\u2744\uFE0F'}}
            {%- elif temperature | float(default=0) > 0.0 -%}
              Temp er {{temperature}}° men føles som {{ apparent}}°, med en vind på {{wind}} m/s. og {{ precip }}% risiko for regn {{ '\u2614\uFE0F' if precip > 30 }}
            {%- endif %}
          {%- else %}
            Kan ikke indlæse vejret....
          {%- endif %}
        active: |
          <b>
          {%- set lights = [
            states.light.office,
            states.light.livingroom,
            states.light.bedroom,
            states.light.kitchen,
            states.light.dining_room,
            states.light.bathroom,
            states.light.entre
          ] %}
          {%- set switches = [
            states.media_player.phillips_tv,
            states.light.fan_bathroom,
            states.switch.plug1,
            states.switch.pc_laptop
          ] %}
          {%- set media_players = [
            states.media_player.phillips_tv,
            states.media_player.mini,
            states.media_player.googlehome7393,
            states.media_player.chromecast8347,
            states.media_player.nestaudio0625,
            states.media_player.under_seng
          ] %}
          {%- set lights_on = lights | selectattr('state','eq','on') | list %}
          {%- set lights_name = lights | selectattr('state','eq','on') | map(attribute='name') | join(', ') %}
          {%- set switches_on = switches | selectattr('state','eq','on') | list %}
          {%- set media_players_playing = media_players | selectattr('state','eq','playing') | list %}
          {%- set append = switches_on + media_players_playing %}
          {%- set switches_name = append | map(attribute='name') | join(', ') %}
          {%- if (lights_on | length == 0) and (switches_on | length > 0) -%}
            {{ switches_name | regex_replace(',([^,]*)$',' og\\1') }} er tændt
          {%- elif (lights_on | length == 1) and (switches_on | length == 1) -%}
            {{ lights_name }} og {{switches_name }} er tændt
          {%- elif (lights_on | length == 1) and (switches_on | length == 1)-%}
            {{ lights_name }} og {{switches_name }} er tændt
          {%- elif (lights_on | length == 1) and (switches_on | length > 1) -%}
            {{ lights_name }}, {{ switches_name | regex_replace(',([^,]*)$',' og\\1') }} er tændt
          {%- elif (lights_on | length > 1) and (switches_on | length == 1) -%}
            {{ lights_on | length }} lamper og {{ switches_name }} er tændt
          {%- elif (lights_on | length > 1) and (switches_on | length > 1) -%}
            {{ lights_on | length }} lamper, {{ switches_name | regex_replace(',([^,]*)$',' og\\1') }} er tændt
          {%- elif (lights_on | length == 1) and (switches_on | length == 0) -%}
            {{ lights_name }} er tændt
          {%- elif (lights_on | length > 1) and (switches_on | length == 0) -%}
            {{ lights_on | length }} lys er tændt
          {%- else %}
            <font color='#6a7377'>Alt er slukket</font>
          {%- endif -%}
          </b>
        Windows: |
          <b>
          {%- set windows = [
            states.binary_sensor.window_bathroom_contact,
            states.binary_sensor.window_bedroom_contact
          ] %}
          {%- set windows_state = windows | selectattr('state','eq','on') | list %}
          {%- set windows_name = windows | selectattr('state','eq','on') | map(attribute='name') | join(', ') %}
          {%- if (windows_state | length == 1 ) -%}
              {{-'\uD83E\uDE9F'}} {{ windows_name }} er åbent
          {%- elif (windows_state | length == 2 ) -%}
              {{-'\uD83E\uDE9F'}} {{ windows_name | regex_replace(',([^,]*)$',' og\\1')  }} er åbne
          {%- endif -%}
          </b>
        vacuum: |
          {% set entity_id = 'vacuum.xiaomi_vacuum_cleaner' %}
          {%- if is_state(entity_id, 'cleaning') -%}
            <b>SugeLone støvsuger</b>
          {%- elif is_state(entity_id, 'returning') -%}
            <b>Sutte Lone er færdig</b>
          {%- endif %}
        battery: |
          {% set entities = [
            'sensor.phillips_hue_switch_battery',
            'sensor.shade_bedroom_battery',
            'sensor.pir2_battery',
            'sensor.pir_bathroom_battery',
            'sensor.pir_kitchen_battery',
            'sensor.pir_office_battery',
            'sensor.switch_cover_bedroom_battery',
            'sensor.switch_kitchen_battery',
            'sensor.tablet_battery_level',
            'sensor.thermometer_bathroom_battery',
            'sensor.thermometer_livingroom_battery',
            'sensor.thermometer_kitchen_battery',
            'sensor.thermometer_bedroom_battery',
            'sensor.thermometer_office_battery',
            'sensor.thermostat_livingroom_2_battery',
            'sensor.thermostat_livingroom_battery',
            'sensor.thermostat_bedroom_battery',
            'sensor.thermostat_kitchen_battery',
            'sensor.thermostat_office_battery',
            'sensor.thermostat_bathroom_battery',
            'sensor.bath_window_battery',
            'sensor.bedroom_window_battery',
            'sensor.switch_bedroom_battery',
            'sensor.waterleak_hydroponic_battery' ] %}
          {%- for sensor in entities if states(sensor) != 'unknown' and states(sensor) != 'unavailable' and states(sensor) != 'None' and states(sensor) | int(default=0) <= 7 %}
            {%- if loop.first %} {{-'\u26A0\uFE0F'}} Battery {% else %}, {% endif -%}
            {{ state_attr(sensor, 'friendly_name') }} {{ states(sensor) }}%
          {%- endfor %}
        calendar: |
          {%- set message = state_attr('calendar.family', 'message') %}
          {%- set start_time = state_attr('calendar.family', 'start_time') %}
          {%- set end_time = state_attr('calendar.family', 'end_time') %}
          {% if start_time != None %}
            {%- set time = as_timestamp(start_time) | timestamp_custom('%H:%M') %}
            {%- set time_end = as_timestamp(end_time) | timestamp_custom('%H:%M') %}
            {%- set hours = as_timestamp(start_time) | timestamp_custom('%H') | int(default=0) / 24 %}
            {%- set count = (as_timestamp(start_time) - as_timestamp(now())) / 86400 - hours %}
            {%- set day = strptime(start_time, '%Y-%m-%d %H:%M:%S').strftime('%A')
            | replace('Monday', 'Mandag')
            | replace('Tuesday', 'Tirsdag')
            | replace('Wednesday', 'Onsdag')
            | replace('Thursday', 'Torsdag')
            | replace('Friday', 'Fredag')
            | replace('Saturday', 'Lørdag')
            | replace('Sunday', 'Søndag') %}
            {%- if count <= 0.0 -%}
              {{ message }}  {{ time }}-{{ time_end }}
            {%- elif count <= 1.0 -%}
              {{message}} i morgen mellem {{ time }}-{{ time_end }}
            {%- elif count <= 2.0 -%}
              {{message}} i overmorgen mellem {{ time }}-{{ time_end }}
            {%- else -%}
              {{message}} om {{ (count + hours) | round }} dage på {{ day }} mellem {{ time }}-{{ time_end }}
            {%- endif %}
          {%- endif %}
        calendarnemlig: |
          {%- set start_time = state_attr('calendar.nemlig', 'start_time') %}
          {%- set end_time = state_attr('calendar.nemlig', 'end_time') %}
          {% if start_time != None %}
            {%- set time = as_timestamp(start_time) | timestamp_custom('%H:%M') %}
            {%- set time_end = as_timestamp(end_time) | timestamp_custom('%H:%M') %}
            {%- set hours = as_timestamp(start_time) | timestamp_custom('%H') | int(default=0) / 24 %}
            {%- set count = (as_timestamp(start_time) - as_timestamp(now())) / 86400 - hours %}
            {%- set day = strptime(start_time, '%Y-%m-%d %H:%M:%S').strftime('%A')
            | replace('Monday', 'Mandag')
            | replace('Tuesday', 'Tirsdag')
            | replace('Wednesday', 'Onsdag')
            | replace('Thursday', 'Torsdag')
            | replace('Friday', 'Fredag')
            | replace('Saturday', 'Lørdag')
            | replace('Sunday', 'Søndag') %}
            {%- if count <= 0.0 -%}
              {{'\U0001F6D2'}} Nemlig idag mellem {{ time }}-{{ time_end }}
            {%- elif count <= 1.0 -%}
              Nemlig imorgen mellem {{ time }}-{{ time_end }}
            {%- elif count <= 2.0 -%}
              Nemlig i overmorgen mellem {{ time }}-{{ time_end }}
            {%- else -%}
              Nemlig om {{ (count + hours) | round }} dage på {{ day }} mellem {{ time }}-{{ time_end }}
            {%- endif %}
          {%- endif %}

Figured out the XBOX logo: Home-Assistant-Icons/SVG/LTM-XBOX at master · LilTrublMakr/Home-Assistant-Icons · GitHub

I will work on repeating the demo animations later. Too lazy to do it now. Refresh the page to see the animations again.

2 Likes

Working on this now. The OP also updated original documentation which is awesome.

nice logo thx.

have you succes integrated a new xbox series x to Homeassistant ?
this doesnt work in my setup with the microsoft integration.

@svalmorri where exactly did you add this? I have implemented Mattias changes for the borders, but still the sidebar border persists

Hi Mattias,

Tilt and bounce are not working for me,
what can be the problem?

Thanks.

without any template code I can not help resolve the issue, if you still have a border after correctly applying Mattias changes, then you must have a custom card that needs a custom solution, please provide the YAMA for the section of the dashboard that still has a border.

@tomerbs can you provide more details?
what browsers have you tested, what is the issue (not working how, no tilt, to much tilt, tilt on some buttons but not on others, etc), do you get any errors in the browser dev tools?

How did you get the arrows next to “Overig” and “Media”

Tried adding them as to the title, but then they are just added as text :frowning:

I can’t think of a nice way to do anything fancy with the title, it would be nice to replace it with a mushroom card at some point down the line as that would give it a bit more utility

but for now, you can just add the arrow symbol directly, a few to pick from

↔︎⇔⟺⬄⇿⬌⟷


They are just “text”, the don’t actually do anything except indicating that the card below it can be swiped :slight_smile:
Media ↔