NSPanel Pro UI Design with Lovelace

Hi @veli ,
I followed you design style. I’m creating custom buttons within custom buttons now, trying to make it look stylish and slick. I still want to use the top bar, So i’ll have to make it smaller, but i’m almost there :wink: after this, it’s templating and creating differen designs (don’t like the colors etc, but it’s just a first try with a random background on it.

how would you go from figma to the grid cards so it’s easy to use different designs?

greetings,
Tom

1 Like

What layout are you using? Is this a Grid Layout and mind sharing the code for this? I’m looking into this and also want a similar layout on my NSPanel Pro

Is this Figma or screenshot from NSPanel? Looks very nice! :star:

after this, it’s templating and creating differen designs (don’t like the colors etc, but it’s just a first try with a random background on it.

If you’re doing the lovelace code (for auto-entities, and not just for personal use), the colors would/should/will follow the theme the user has selected, same with font family ,size, weight; card border radii and margin, padding etc… if you inspect page with dev tools you find the css variables like

var(--primary-text-color)
var(--ha-card-background)
var(--ha-card-box-shadow)
var(--ha-card-border-radius)
var(--ha-card-header-font-family)
...etc...

So the results will vary based on active theme, like:

1_3_1 1_3 1_2 1_1

For layout, custom: layout-card is what I use with mode: grid.
Just gotta learn CSS grids to make use of it :smiley: Happy hunting!

Hi! Looks great, but mine gets too high for the nspnanel pro. How do I comment out the 26%, 3 hours ago, Effect, and Attributes? Have tried a bunch of different stuff without getting it right. Copy pasted your yaml config in this post

The shadow-root css is a bit too weird for me, and the code keeps changing in each update, so i didn’t bother to clean the tests of background-color:weid, etc out, but this is something:

Can’t seem to get the height to 100% still…

2024-06-29_18-08.03

type: custom:more-info-card
entity: light.bedside
card_mod:
  style:
    $: |
      :host{
        --control-slider-color:green !important;
        --control-slider-border-radius: 2rem !important;
        
      }
      ha-card ha-control-slider{
        --control-slider-thickness: 10rem !important;
        width: 200% !important;
        background orange !important;
      }
      ha-card{


      --control-slider-color:orange !important;
      }
      ha-card ha-more-info-state-header{

      }
      .card-header {
      font: var(--h6-font) !important;
      padding: 1rem 0 !important;
      text-align:center;
      background: red !important;
      display:none !important;
      }
      ha-card .card-content{

      }
      ha-card more-info-content{

      }      

      ha-more-info-control-select-container{
      display:none;
      }
      ha-control-slider{
      display:none;background:red;
      --control-slider-thickness: 10rem !important;
      }
      ha-card div{

      }      
      ha-card .last-changed{
      background: red !important;
      }
    .: |
      :host{
        --control-slider-color:cyan !important;
      }    
      ha-card ha-more-info-state-header{
      background: orange !important;
      }
      ha-card .last-changed{
      background: green !important;
      }
      ha-more-info-control-select-container{
      display:none;
      background:green;
      }    
      .card-content {
      padding: 0;
      margin: 0;
      }
      .card-content .controls{
        background: yellow !important;
      }
      ha-card{
      background: transparent;
      } 
      ha-card state-card-content{
      display:none;
      background: orange !important;
      }
      ha-card more-info-content{

      }              
      ha-card more-info-light{

      }                            
      ha-card ha-attributes{
      display:none;              
      } 
      ha-card more-info-content{
      background: red;
      }
      more-info-card{
      background:red;
      }
      .controls{
        margin: 0 !important;

      }
    more-info-content$more-info-light:
      $: >
        div{


        }      

        ha-attributes{
         display:none;
        }             

        :host{
         --control-slider-color: amber !important;
         display:flex;
         align-items:center;
         justify-content:middle;
         padding: 4rem 0;
        }

        hui-card-options{

        display:none;

        }

        .controls{


        width: 100% !important;

        margin: 0 !important;


        } 

        .controls:last-child{
          background: orange !important;
        }

        div:nth-child(1){

        background:green !important


        }

        ha-more-info-control-select-container{

        display:none;

        }

        ha-attributes{

        display:none !important;

        opacity:0.5;

        height:0px;

        overflow:hidden;

        }

        ha-state-control-light-brightness, light-color-temp-picker{

        margin-top: 4rem;



        overflow:hidden;

        margin: 0 !important;

        max-height:100vh !important;

        flex: 2 1 auto;

        }    

        ha-control-slider{

        background: gold !Important;

        height: 200vh !important;

        --control-slider-thickness: 10rem !important;

        }

        .container{

        background: magenta !important;

        opacity: 0.2;



        overflow:hidden;

        margin: 0 !important;

        height:200vh !important;

        }                

        ha-control-slider{

        background:orange !Important;

        height:200vh !important;

        }

        ha-state-control-light-brightness ha-control-slider,
        light-color-temp-picker ha-control-slider{

        height: 100vh !important;

        background: green !important;

        --control-slider-thickness: 10rem !important;

        }

        ha-icon-button-group{

        background: transparent !important;

        flex: 0;

        }

        ha-icon-button-group > *{

        background: transparent !important;

        transition: all 1s ease-out;        

        }

        ha-icon-button-group > *:nth-child(2),

        ha-icon-button-group > *:nth-child(3),

        ha-icon-button-group > *:nth-child(4),

        ha-icon-button-group > *:nth-child(5){

        background: transparent !important;

        opacity:0;


        display:none;

        }     

        ha-icon-button-group > *:nth-child(1){

        opacity:0.2;

        }        

        ha-icon-button-group:hover > *{

        opacity:1;

        display:block;

        }

        ha-more-info-light-brightness, ha-more-info-toggle,
        light-color-temp-picker{

        flex: 5;

        margin: 0 !important;


        }                

        .buttons{

        flex:0 1 1rem;

        padding: 0 !important;

        margin: 0 !important;

        background: red !important;

        }

        .buttons > *{

        margin: 0 !important;

        --md-sys-color-outline: var(--primary-background-color);

        --md-sys-color-on-surface-variant: var(--primary-color);

        background: red !important;

        }                

        .buttons ha-button-menu md-outlined-icon-button{

        --md-sys-color-outline: var(--primary-background-color);

        --md-sys-color-on-surface-variant: var(--state-light-inactive-color);

        background: red !important;

        }


        .buttons > md-outlined-icon-button:nth-child(2){

        display:none;

        }              

        ha-more-info-state-header{

        background: cyan !important;

        display: none !important;

        }
      .: |
        ha-attributes{
         background: blue;
         background: orange !important;
        } 
        .controls{
        background: green !important;
        }
        ha-more-info-state-header{
        background: green !Important;
        display:none !important;
        }        
    more-info-content$more-info-light$ha-more-info-state-header:
      $: |
        :host{
        background: red !important;
        display:none;
        }  
        .state{
        background:green !important;
        display:none;
        }    
    more-info-light$ha-more-info-control-select-container:
      $: |
        :host{
        background: orange !important;
        }  
        .controls{
        background: green !important;
        }
    more-info-light$md-outlined-icon-button:
      $: |
        md-outlined-icon-button{
        background: red !important;
        }                 
    md-outlined-icon-button$ha-button-menu:
      $: |
        md-outlined-icon-button{
        background: red !important;
        }                                 
    more-info-light$ha-control-slider:
      $: |
        :host{
          background: magenta !important;
          height: 100vh !important;
          --control-slider-thickness: 10rem !important;
        }         
    more-info-light$ha-state-control-light-brightness$ha-control-slider:
      $: |
        :host{
          background: cyan !important;
          height: 100vh !important;
        } 
        .handle{
          background: orange !important;
          height: 100vh !important;
        }
      .: |
        :host{
          background: yellow !important;
          height: 100vh !important;
        }         
    more-info-light$ha-state-control-light-brightness:
      $: |
        :host{
        --control-slider-border-radius:1rem !important;
        width:200% !important;
        max-height: none !important;
        }    
    ha-card$ha-control-slider:
      $: |
        :host{
         width:200% !important;
         height: 100vh !important;
         max-height: none !important;
        }            
    ha-card$ha-state-control-light-brightness:
      $: |
        :host{
         width:200% !important;
         height: 100vh !important;
         background: orange !important;
        }                    
    ha-state-control-light-brightness$ha-control-slider:
      $: |
        :host{
         --control-slider-border-radius:1rem !important;
         width:200% !important;
         height: 200vh !important;
         max-height: none !important;
         background:green !important
        }            
        .container{
          background: purple !important;
          height: 100vh;
        }
    more-info-light$ha-more-info-toggle:
      $: |
        ha-control-switch{
        --control-slider-border-radius:1rem !important;
        height: 100% !important;
        width: 200% !important;
        max-height: none !important;
        }                         
    more-info-light$ha-more-info-state-header:
      $: |
        :host{
          display:none !important;
        }
        .name{
        font:var(--h5-font) !important;
        text-overflow:ellipsis;
        overflow:hidden;
        white-space: nowrap;
        padding: 0 0 1rem 0;
        margin: 0 !important;
        } 
        .state, .last-changed{
        display:none !important;
        }       
      .: |
        .name{
        font:var(--h5-font) !important;
        text-overflow:ellipsis;
        overflow:hidden;
        white-space: nowrap;
        padding: 0 0 1rem 0;
        margin: 0 !important;
        } 
        .state, .last-changed{
        display:none;
        }                  
    more-info-light$ha-control-select-menu:
      $: |
        :host{
         display:none;
        } 
    more-info-cover:
      $: |
        ha-attributes{
        display:none;
        }             
        .controls{
        display:flex;
        flex: 4;
        height: 100%;
        margin:0;
        flex-direction: column;
        }            
        .main-control{
        margin:0 !important;
        width: 100%;
        }
        ha-more-info-cover-position, ha-more-info-toggle{
        flex: 5;
        width: 100%;
        height: 100%;
        margin: 0 !important;
        }                
        .buttons{
        flex:0 1 1rem;
        padding: 0 !important;
        margin: 0 !important;
        }
         .buttons > *{
         margin: 0 !important;
         --md-sys-color-outline: var(--primary-background-color);
         --md-sys-color-on-surface-variant: var(--primary-color);
         }                
         .buttons ha-button-menu md-outlined-icon-button{
         --md-sys-color-outline: var(--primary-background-color);
         --md-sys-color-on-surface-variant: var(--accent-color);
         }
         .buttons > md-outlined-icon-button:nth-child(2){
         display:none;
         }          
    more-info-cover$ha-more-info-cover-position:
      $: |
        ha-control-slider{
        --control-slider-border-radius:1rem !important;
        width:100% !important;
        height: 50vh !important;
        max-height: none !important;
        }       
    more-info-light$ha-more-info-cover-position$ha-control-slider:
      $: |
        .slider{
        height:100vh;
        background: var(--secondary-background-color);
        }                
    more-info-light$ha-more-info-light-brightness$ha-control-slider:
      $: |
        .slider{
        height:100vh;
        background: var(--secondary-background-color);
        }                                
    ha-more-info-toggle:
      $: |
        ha-control-switch{
        height: 100%;
        width: 100%;
        }
      .: |
        ha-control-switch{
        height: 100%;
        }              
    ha-more-info-toggle$ha-control-switch:
      $: |
        :host{
        background: red;
        }
    ha-more-info-control-select-container:
      $: |
        :host{
          background: red;
        }
    more-info-content$more-info-light$ha-state-control-light-brightness$ha-control-slider:
      $: |
        :host{
          height: 100%
          
        }    
    ha-state-control-light-brightness:
      $: |
        :host{
          background: orange !important;
          height: 100vh !important;
        }    

Hi,

I’m trying to create these 3 sensors without success. Homeassistant is complaining about the length of the template. Here is an example:

I this the right process to create a sensor template?

Settings - Device&Services - Helpers - Create Helper - Template - Template a sensor

PS: Thank you for this nice UI for NSpanel Pro.

1 Like

I think UI (adding a “helper”) might limit this:

Instead, I use “template:”, YAML has no limits :slight_smile:

Thank you for your reply. I’m few steps closer to make it work.
Now I have an issue with sensor.solar not changing the frendly_name to select the right image

Update: Now the sensors are working fine, I moved all the Figma files in /homeassistant/www/emoji folder, I changed home assistant theme to metro and the end resut is this:

It is strange, because the other code that you give is working:

Do you have any ideeas?

The attributes seem to be included correctly :+1:

Do not set a name manually, it comes automatically from template:


- sensor:
    - unique_id: solar
      name: >-
        {%- set elevation = state_attr('sun.sun', 'elevation') | int -%}
        {%- set rising = state_attr('sun.sun', 'rising') -%}
        {%- set azimuth = state_attr('sun.sun', 'azimuth') | int -%}
        {%- if elevation <= -12 -%}
          {%- if (0 <= azimuth <= 10) or (350 <= azimuth <= 360) -%}
            Midnight 
          {%- else -%}
            Night 
          {%- endif -%}
        {%- elif -6 < elevation <= 0 -%}
          {{- 'Sunrise' if rising else 'Sunset' -}}
        {%- elif -12 < elevation <= -6 -%}
          {{- 'Dawn' if rising else 'Dusk' -}}
        {%- else -%}
          {%- if 160 <= azimuth <= 200 -%}
            Noon
          {%- else -%}
            Day
          {%- endif -%}
        {%- endif -%}

edit:

the position and sizes seem to be theme dependent:

Sensor.solar is working fine now:
Capture

I still have 2 issues:
First is sensor.weather is not showing the temperature. What weather integration are you using? I think mine (Open-Meteo) doesn’t have the right attributes
Capture

The second, the code is not loading the images from /local/emoji/ folder. I have all the files downloaded from your Figma link and added to /www folder. (ex. /www/emoji/moon/full_moon.svg)

I have Metrology integration installed and I’m using “Metro Blue” theme

what does the link say:
http://homeassistant.local:8123/local/emoji/moon/full_moon.svg - check the file location and folder permissions, the “www” is mapped to “local” and should be public.

Forecast was met.no default, but the Home Assistant or integration code has yet again changed, so it does not work for me either. Check, test and change in http://homeassistant.local:8123/developer-tools/template for what should it be: {{ states.weather.home.attributes }}

is showing full moon image

is showing:

I should charge you for one-on-one consultation :smile:

  1. Use a weather service call.
  2. Add to template:

- trigger:
    - platform: time_pattern
      hours: "/1"
  action:
    - service: weather.get_forecasts
      data:
        type: hourly
      target:
        entity_id: weather.home
      response_variable: hourlyforecast
  sensor:
    - name: "Weather Forecast Hourly"
      unique_id: weather_forecast_hourly
      icon: mdi:weather-cloudy-clock
      state: "{{ now().isoformat() }}"
      attributes:
        forecast: >-
          {{ hourlyforecast['weather.home']['forecast'] }}

    - platform: time_pattern
      days: "/1"
  action:
    - service: weather.get_forecasts
      data:
        type: daily
      target:
        entity_id: weather.home
      response_variable: dailyforecast
  sensor:
    - name: "Weather Forecast Daily"
      unique_id: weather_forecast_daily
      icon: mdi:weather-cloudy-clock
      state: "{{ now().isoformat() }}"
      attributes:
        forecast: >-
          {{ dailyforecast['weather.home']['forecast'] }}

- sensor:
    - unique_id: weather_forecast
      name: Weather Forecast
      icon: >-
        mdi:weather-{{ states('weather.home') }}
      state: >-
        {{ states('weather.home') | replace('_',' ') | capitalize }}
      attributes:
        forecast_high: >-
            {{ state_attr('sensor.forecast_home_hourly','forecast')[0].temperature | int(0) }}
#          {{ state_attr('sensor.weather_forecast_daily','temperature') | int(0) | default(0) }}
        forecast_low: >-
            {{ state_attr('sensor.forecast_home_hourly','forecast')[6].temperature | int(0) }}
#          {{ state_attr('sensor.weather_forecast_daily','temperature') | int(0) | default(0) }}
        entity_picture: >-
          {%- set elevation = state_attr('sun.sun', 'elevation') | int -%}
          {%- set rising = state_attr('sun.sun', 'rising') -%}
          {%- set azimuth = state_attr('sun.sun', 'azimuth') | int -%}          
          {% set weather = states('weather.hernes') %}
          {% if weather == 'sunny' and elevation <= 0 %}
            {{ state_attr('sensor.moon_phase','entity_picture') }}
          {% else %}      
            {% if weather in ['unknown','unavailable'] %}
              /local/emoji/weather/{{ ['unicorn','sparkles','rainbow'] | random }}.svg
            {% else %}
              /local/emoji/weather/{{weather}}.svg
            {% endif %}   
          {% endif %}
        emoji: >-
          {%- set elevation = state_attr('sun.sun', 'elevation') | int -%}
          {%- set rising = state_attr('sun.sun', 'rising') -%}
          {%- set azimuth = state_attr('sun.sun', 'azimuth') | int -%}
          {% set values = {'cloudy':'☁️','fog':'🌁','lightning-rainy':'⛈️','lightning':'🌩️','partlycloudy':'⛅','rainy':'🌧️','snowy':'❄️','snowy-rainy':'🌨️','sunny':'☀️','windy':'🌬️'} %}
          {% set value = states('weather.hernes') %}  
          {% if values[value] == '☀️' and elevation <= 0 %}
          {{ state_attr('sensor.moon_phase','emoji') }}
          {% else %}      
          {{ values[value] if value in values.keys() else '🦄' }}       
          {% endif %}

I’m not sure it is ok or not but using this code:

is showing the temperature:
Capture

“Forecast low” is not that important to me

can you provide a copy of your templates.yaml file with the sensors in. :pray: :heart_hands:

Hi
Do you have information of my last post including high latency on the lovelace GUI ?

Hello, I have a problem with screensaver. I tried steps for debug and I checked all post in a thread, other code works very well but unfortunately code of screen saver won’t work for me

Old post but i’m interesting to see the yaml!

Does anyone here know how to send sound to the panel? Like I wanna send sound if I arm the alarm.

Hello,

After updating to 2025.1.1 the view broke. Only the moon/sun icon and the section of the day (Midnight, Noon, etc) is displayed. In the editor, the preview shows all parts normally. I checked all the dynamic parts in the template editor and they look good… I don’t understand what happened, did anyone face the same issue or maybe have some ideas?