A different take on designing a Lovelace UI

Ah so make it as markdown instead of a grid card?

I tried a grid card with custom:button-cards however the buttons were spaced out huge and I couldn’t figure out how to close the gaps. Mind you, I didn’t do much with the themes.yaml

If you can’t make it work you could try GitHub - DBuit/sidebar-card

I did try the sidebar card initially, however I cannot designate it to a grid area. It renders before all other cards. I’m sure I could make it work somehow but I think I’d prefer to have the nav native in the grid. If I can’t get the buttons to work, I’ll try the sidebar card again and just match the style.

Just need to figure out why the buttons went all crazy and huge when I added a 1 column grid card to the sidebar.

Hi @Mattias_Persson greate and huge work! Is there any instructions how to install this or i have to figure it out by myself ? Just asking to not spend a lot of time trying tu implement it if there is some guide.

There is not really a setup. Mattias shared his config, and its to you to copy those things and change it to your entities and liking.

Most things are straight forward, such as the community files, custom button yaml, ui-lovelace etc.

Just a matter of merging into your setup

I came across mattias’ post in another topic. It’s going to help many here. I know it’ll help me :slight_smile:

Hi, I’m looking for some css help. (I’ve been trying to learn from other sources on the net so as not to bug the community but the context is different in the examples I am seeing so I’m having a difficult time translating the help into my specific situation)

In the theme there is the code:

    #################################################
    #                                               #
    #             Weather Card                      #
    #                                               #
    #################################################

    "grid-layout$hui-element":
      $: |
        ha-card {
          display: flex !important;
          align-items: flex-end !important;
          justify-content: center !important;
        }

Does this css place that card at the bottom of the container? If yes… if I have multiple cards with that code, how does it keep the cards in order. For example in Mattias theme, he has the clock, then a conditional card and then the grid. Is it just the order the cards are in the code?

In my case, I am trying to show a weather card under the clock:

      - type: markdown
        view_layout:
          grid-area: sidebar
        content: |
          {% set attributes = states.sensor.template_sidebar.attributes | default %}
          {% for template in attributes %}
          {{ state_attr('sensor.template_sidebar', template) }}
          {% endfor %}

      - type: "custom:hui-element"
        view_layout:
          grid-area: sidebar
        card_type: weather-forecast
        entity: weather.regina
        show_forecast: false

And in my theme I have:

    #################################################
    #                                               #
    #             SIDEBAR MARKDOWN CARD             #
    #                                               #
    #################################################

    "grid-layout$hui-markdown-card:first-of-type":
      $: |
        /* Markdown strip along left side */
        ha-card {
          background-color: #00000010;
          border-radius: 0;
          min-height: 100vh;
          animation: ha-card 1s forwards;
        }
        @keyframes ha-card {
          0%, 100% {
            border-right: 0.1vw solid rgba(58, 69, 73, 0.2);
          }
        }
        /* phone */
        @media screen and (max-width: 800px) {
          ha-card {
            background: none;
            min-height: 100%;
            animation: none;
          }
      "$ha-card>ha-markdown":
        .: |
          ha-markdown {
            padding: var(--custom-layout-card-padding) 2vw 0 var(--custom-layout-card-padding) !important;
            pointer-events: none;
          }
          /* phone */
          @media screen and (max-width: 800px) {
            ha-markdown {
              padding: 0 !important;
            }
        $: |
          /* clock */
          p {
            font-family: SF Text;
            font-size: var(--markdown-sidebar-clock-font-size);
            font-weight: 200;
            line-height: var(--markdown-sidebar-clock-line-height);
            letter-spacing: -0.05vw;
            color: var(--ha-card-header-color);
            margin: 0 0 0 0;
          }
          /* colon */
          p > span > span {
            position: relative;
            top: -.09em;
          }
          /* text */
          p > font > b {
            font-family: SF Display;
            font-size: var(--markdown-sidebar-font-size);
            line-height: var(--markdown-sidebar-line-height);
            font-weight: 300;
            letter-spacing: 0.06vw;
            color: #6a7377;
            margin: 0 0 0 0;
          }
          
          b > p {
            font-family: SF Display;
            font-size: var(--markdown-sidebar-font-size);
            line-height: var(--markdown-sidebar-line-height);
            font-weight: 300;
            letter-spacing: 0.06vw;
            color: var(--ha-card-header-color);
          }

          /* phone */
          @media screen and (max-width: 800px) {
            p {
              font-size: calc(var(--markdown-sidebar-clock-font-size) * 2.6 );
              line-height: calc(var(--markdown-sidebar-clock-line-height) * 2.6 );
            }

            p > font > b {
              font-size: calc(var(--markdown-sidebar-font-size) * 2.6 );
              line-height: calc(var(--markdown-sidebar-line-height) * 2.6 );
              letter-spacing: 0.16vw;
            }

            b > p {
              font-size: calc(var(--markdown-sidebar-font-size) * 2.6 );
              line-height: calc(var(--markdown-sidebar-line-height) * 2.6 );
              letter-spacing: 0.16vw;
            }
          }

    #################################################
    #                                                                                             #
    #             Weather Card                                                         #
    #                                                                                            #
    ################################################

    "grid-layout$hui-element":
      $: |
        ha-card {
          display: flex !important;
          align-items: flex-end !important;
          justify-content: center !important;
        }

        /* phone */
        @media screen and (max-width: 800px) {
          ha-card {
            padding: -50% 0 0 0 !important;
          }
        }

But for some reason the weather card doesn’t respect the order and it gets placed at the top of the markdown card:

I think this has something to do with the flex container but I am not 100% sure.

Any ideas on what is happening here? Thanks all!

For those wanting an alarm tile, made one myself. It’s not as elegant as @Mattias_Persson could make, with all sorts of fancy animated svg icons and style, but it’s a start. Going to improve over time, but fits my needs for now. I do a popup to show me a full sized alarm panel card with all buttons etc. But it shows me the state, icon dynamically and added some color + animation to the tile when triggered etc.

Obviously, feel free to improve and share back~

@VPC @martheijnen @naijaping

      - type: "custom:button-card"
        entity: alarm_control_panel.alarmo
        aspect_ratio: 1/1
        show_entity_picture: true
        show_state: true
        show_name: false
        name: Alarm
        show_icon: true
        style:
          - padding: 0px
        styles:
          entity_picture:
            - width: 80%
            - height: 100%
            - padding-bottom: 0%
          card:
            - border-radius: 10%
            - background-color: 'rgba(115, 115, 115, 0.2)'    
        icon: mdi:shield-off-outline
        tap_action:
          !include ../popup/alarm.yaml
        state:
        - value: 'arming'
          icon: mdi:shield-outline
          styles:
            card:
              - animation: blink 3s ease infinite
              - background-color: '#FAA255'
        - value: 'armed_away'
          icon: mdi:shield-lock
          styles:
            card:
              - background-color: '#BA494B'
        - value: 'armed_home'
          icon: mdi:shield-account
          styles:
            card:
              - background-color: '#F0C438'
        - value: 'armed_night'
          icon: mdi:shield-home
          styles:
            card:
              - background-color: '#66C6F2'
        - value: 'armed_custom_bypass'
          icon: mdi:security
          styles:
            card:
              - background-color: '#7F7CE6'
        - value: 'pending'
          icon: mdi:shield-sync
          styles:
            card:
              - animation: blink 4s ease infinite
              - background-color: '#FAA255'
        - value: 'triggered'
          icon: mdi:bell-ring
          styles:
            card:
              - animation: blink 1s ease infinite
              - background-color: '#f70d1a'
        - value: 'unavailable'
          icon: mdi:shield-alert
          styles:
            card:
              - animation: blink 10s ease infinite
              - background-color: '#657c80'
        - value: 'unknown'
          icon: mdi:shield-alert
          styles:
            card:
              - animation: blink 10s ease infinite
              - background-color: '#6f8499'
3 Likes

I’ve also managed to make 2 garbage tile (left one showing what is being picked up today and right one showing what garbage container I should put that night, for garbage to be picked up the next day).

Screenshot 2021-06-13 at 22.23.32

code:

      - type: "custom:button-card"
        entity: sensor.garbage_today
        aspect_ratio: 1/1
        show_entity_picture: true
        show_name: true
        name: Vandaag
        show_icon: true
        style:
          - padding: 0px
        styles:
          entity_picture:
            - width: 80%
            - height: 100%
            - padding-bottom: 0%
          card:
            - border-radius: 10%
            - background-color: '#848484'         
        entity_picture: "/local/images/afval/afval_geen_large.png"
        state:
        - value: 'gft'
          entity_picture: "/local/images/afval/afval_gft_large.png"
          styles:
            card:
              - background-color: '#3B863D'
        - value: 'papier'
          entity_picture: "/local/images/afval/afval_papier_large.png"
          styles:
            card:
              - background-color: '#00B1EB'
        - value: 'plastic'
          entity_picture: "/local/images/afval/afval_pmd_large.png"
          styles:
            card:
              - background-color: '#F4A029'

      - type: "custom:button-card"
        entity: sensor.garbage_tomorrow
        aspect_ratio: 1/1
        show_entity_picture: true
        show_name: true
        name: Morgen
        show_icon: true
        style:
          - padding: 0px
        styles:
          entity_picture:
            - width: 80%
            - height: 100%
            - padding-bottom: 0%
          card:
            - border-radius: 10%
            - background-color: '#848484'         
        entity_picture: "/local/images/afval/afval_geen_large.png"
        state:
        - value: 'gft'
          entity_picture: "/local/images/afval/afval_gft_large.png"
          styles:
            card:
              - background-color: '#3B863D'
        - value: 'papier'
          entity_picture: "/local/images/afval/afval_papier_large.png"
          styles:
            card:
              - background-color: '#00B1EB'
        - value: 'plastic'
          entity_picture: "/local/images/afval/afval_pmd_large.png"
          styles:
            card:
              - background-color: '#F4A029'
4 Likes

Hi friend.
How did you make your photo appear.
I can’t make mine show. I create a person, I use it on the card and it tells me if I am or not. I thought changing the name of the image to mine but I don’t see it.
Thanks

Configuration > People > make a person with foto. And then add that to the card.

Or do what matt did:

hass-config/customize.yaml at efc4c4141cc219b7d11f89bb70dfea2d570c408b · matt8707/hass-config · GitHub

I was just wondering, as a theme newbie, if there is somewhere like an overview of more homemade custom icons and animations that match @Mattias_Persson’s design?
I already found an icon for Sonos here in the thread, but it’s a bit tedious and confusing to have to read through everything.

I’m building a new system for a wall mounted tablet and after seeing this there’s no question that this UI looks every bit as sleek and clean as a commercial product. Well done @Mattias_Persson

How do I install this? I have seen the various components on GitHub? Is this a fully manual process; e.g. create the structure in custom_components, edit configuration.yaml, ui-lovelace.yaml etc?

1 Like

How Mattias added the people in configuration I thought it was like this. If you add the people in configuration you cannot add it. But so I could. Thank you

1 Like

Do you want to show me your yaml for sensor.garbage_tomorrow ?

@Schocker

I’m just cramming in cards over the markdown card, I think it’ll be easier if you replace that grid area with a vertical stack and place your cards in that instead.

Excellent idea! Thanks @Mattias_Persson

Sure, integration through HACS: GitHub - bruxy70/Garbage-Collection: 🗑 Custom Home Assistant sensor for scheduling garbage collection (or other regularly re-occurring events - weekly on given days, semi-weekly or monthly)

And this is my garbage.yaml file:

sensor:
  - platform: template
    sensors:
      garbage_today:
          friendly_name: Garbage Today
          value_template: >-
            {% if states.sensor.bio_afval.attributes.days == 0 %} gft
            {% elif states.sensor.plastic_afval.attributes.days == 0 %} plastic
            {% elif states.sensor.papier_afval.attributes.days == 0 %} papier
            {% else %} geen
            {% endif %}
  
  - platform: template
    sensors:
      garbage_tomorrow:
          friendly_name: Garbage Tomorrow
          value_template: >-
            {% if states.sensor.bio_afval.attributes.days == 1 %} gft
            {% elif states.sensor.plastic_afval.attributes.days == 1 %} plastic
            {% elif states.sensor.papier_afval.attributes.days == 1 %} papier
            {% else %} geen
            {% endif %}
            
  - platform: template
    sensors:
      bio_afval_date:
          friendly_name: GFT
          value_template: "{{ as_timestamp(states.sensor.bio_afval.attributes.next_date) | timestamp_custom('%d %b') }}"

  - platform: template
    sensors:
      plastic_afval_date:
          friendly_name: Plastic
          value_template: "{{ as_timestamp(states.sensor.plastic_afval.attributes.next_date) | timestamp_custom('%d %b') }}"

  - platform: template
    sensors:
      papier_afval_date:
          friendly_name: Papier
          value_template: "{{ as_timestamp(states.sensor.papier_afval.attributes.next_date) | timestamp_custom('%d %b') }}"
1 Like

@Schocker hope you can share once you’ve managed xD

1 Like

Thank you. At the moment I am using a “normal” calendar which contains the collection days as a whole day event.

Dont want to change to a extra component. Thought you are maybe using it the same way.

Just need a sensor which is on on the day before.