A different take on designing a Lovelace UI

Haha. sorry for confusing you. i wanted to keep the aspect-ratio but at a smaller size.
i Thought i good adjust the custom layout grid to fit the cards style. So setting three rows at a specific height and the card would fit itself inside each row and not auto exspand grid so i get the scroller.
Does it give meaning what i am trying to explain? basically i want to make the layout fixed within the resolution size of the screen.

I guess so, you’re talking about grid-template-columns and grid-template-rows?
Use this https://grid-v1.layoutit.com/, I’d use fr/% but if you really need it fixed use px

2 Likes

Did you used the icons as png oder svg?
If png, can you show me your code how you implemented png as icons?

I use the png

state:
  - value: 'on'
    entity_picture: \local\img\icons8-scoop-beleuchtung-48.png
    color: rgba(255,255,255,0.9)
  - value: 'off'
    entity_picture: \local\img\icons8-scoop-beleuchtung-48.png
    color: rgba(65,65,63,0.8)
    styles:
      card:
        - filter: opacity(50%)
      icon:
        - filter: grayscale(100%)

Can sombody explain why this does not work? I wont show the entity_picture.
image

          - type: custom:button-card
            entity: cover.garage_tor
            name: Garage
            tap_action:
              action: toggle
            hold_action:
              action: more-info
            show_entity_picture: true
            entity_picture: \local\img\icons8-closed-window-48.png
            template:
              - base

button_card_template

base:
  variables:
    state: >
      [[[ return entity === undefined || entity.state; ]]]
    timeout: >
      [[[ return entity === undefined || Date.now() - Date.parse(entity.last_changed); ]]]
    light_color: >
      [[[ return entity === undefined ? 'var(--state-icon-color)' : 'var(--button-card-light-color-no-temperature)'; ]]]
    consider_on: >
      [[[
        var state = entity === undefined || entity.state;
        return (
          state == 'on' ||
          state == 'home' ||
          state == 'cool' ||
          state == 'fan_only' ||
          state == 'playing'
        );
      ]]]
  aspect_ratio: 1/1
  show_state: true
  show_icon: false
  state_display: >
    [[[ if (variables.state === true) return 'Unbekannt'; ]]]
  tap_action:
    ui_sound_tablet: |
      [[[
        const screensaver = states['switch.dashboard_screensaver'] === undefined || 
            states['switch.dashboard_screensaver'].state;

        if (variables.state === 'off' && screensaver === 'off') {
          hass.callService('media_player', 'play_media', {
            entity_id: 'media_player.browsermod_dashboard_fullykiosk',
            media_content_id: '/local/sound/on.m4a',
            media_content_type: 'music'
          });
        }
        if (variables.state === 'on' && screensaver === 'off') {
          hass.callService('media_player', 'play_media', {
            entity_id: 'media_player.browsermod_dashboard_fullykiosk',
            media_content_id: '/local/sound/off.m4a',
            media_content_type: 'music'
          });
        }
      ]]]
    animation_card: |
      [[[
        const animation_speed_ms = 900;
        const animation = `card_bounce ${animation_speed_ms}ms cubic-bezier(0.22, 1, 0.36, 1)`;
        this.shadowRoot.getElementById("card").style.animation = animation;
        window.setTimeout(() => {
          this.shadowRoot.getElementById("card").style.animation = "none";
        }, animation_speed_ms)
      ]]]
    action: toggle
    haptic: medium
  styles:
    grid:
      - grid-template-areas: |
          "icon  circle"
          "n     n"
          "s     s"
      - grid-template-columns: repeat(2, 1fr)
      - grid-template-rows: auto repeat(2, min-content)
      - gap: 2%
      - align-items: start
    name:
      - justify-self: start
      - line-height: 115%
    state:
      - justify-self: start
      - line-height: 115%
    card:
      - font-family: Sf Display
      - border-radius: var(--custom-button-card-border-radius)
      - -webkit-tap-highlight-color: rgba(0,0,0,0)
      - transition: none
      - padding: 10%
      - --mdc-ripple-color: >
          [[[
            return (variables.state === 'on' || variables.state === 'home' || variables.state === 'open') ?
              'rgb(0, 0, 0)' :
              'rgba(255, 255, 255, 0.3)';
          ]]]
      - color: >
          [[[
            return (variables.state === 'on' || variables.state === 'home' || variables.state === 'open') ?
              'rgba(0, 0, 0, 0.6)' :
              'rgba(255, 255, 255, 0.3)';
          ]]]
      - background-color: >
          [[[
            return (variables.state === 'on' || variables.state === 'home' || variables.state === 'open') ?
              'rgba(255, 255, 255, 0.8)' :
              'rgba(115, 115, 115, 0.2)';
          ]]]
  extra_styles: |
    [[[
      if (entity) {
        let hs = entity.attributes.hs_color == undefined;
        let h = hs || entity.attributes.hs_color[0];
        let s = hs || entity.attributes.hs_color[1];
        let l_min = 28;
        let l_max = 48;
        let l_calc =
          ((entity.attributes.brightness / 2.54) * (l_max - l_min)) / 100 + l_min;
        var light_color =
          entity.attributes.color_mode === 'color_temp'
            ? `hsl(204, 58%, ${l_calc}%);`
            : `hsl(${h}, ${s}%, ${l_calc}%);`;
      }
      return `
        svg {
          --light-color:
          ${ variables.state === 'on' && entity.attributes.brightness != undefined
              ? light_color
              : variables.state === 'on' && entity.attributes.brightness == undefined
              ? 'var(--state-icon-active-color);'
              : 'var(--state-icon-color);'
          }
        }
        #name, #state {
          font-size: 1.34vw;
          letter-spacing: 0.05vw;
        }
        /* portrait */
        @media screen and (max-width: 1200px) {
          #name, #state {
            font-size: 2vw;
            letter-spacing: 0.05vw;
          }
        }
        /* phone */
        @media screen and (max-width: 800px) {
          #name, #state {
            font-size: 3.1vw;
            letter-spacing: 0.12vw;
          }
        }
        @keyframes card_bounce {
          0% {
            transform: scale(1);
          }
          15% {
            transform: scale(0.9);
          }
          25% {
            transform: scale(1);
          }
          30% {
            transform: scale(0.98);
          }
          100% {
            transform: scale(1);
          }
        }
      `
    ]]]

Because I do not make use of img_cell or i. In that grid area I use the custom_fields icon.

This is without altering the grid

custom_fields:
  icon: >
    <img src="/local/*.png" width="100%">

and like this if you really need entity_picture

show_entity_picture: true
entity_picture: /local/*.png
size: 100%
styles:
  grid:
    - grid-template-areas: |
        "i  circle"
        "n     n"
        "s     s"

Now it is working. Thought it would be something with the grid, but didnt get it.

Hello,
Can you please write a short manual on your github repo for neccessery steps for installation process? Thanks

1 Like

Also joined this awesome design, first of all thanks Mattias!. Looks really cool…
I have a lot of questions though :), especially considering the interchangeability of this design. Since it’s pretty awesome, I would love for this to become the default of Home Assistant in tablet format :). But going through the config, I’m just wondering if some things can’t become more ‘generic’ like defining your “lights” on multiple places, I would rather make this into a template and use that. Not even knowing if it’s possible… But I’m drifting…

My actual question is the following:
All the popup that I open are opened at a specific width, I would love for the popup to scale to the content (to some degree, the max of the screen ofcourse). I dont’ seem to be able to fix this.

could anyone assist me, for this case I would expect to also see the map. like:

I can get this to work by editing some styling through the developer tools… But next to editing a ‘main’ style like

ha-dialog {
    --mdc-dialog-min-width: 900px; 
}

I also am unable to do this (or don’t know how)

Is there a way to present different sidebar to tablet and phone?

There’s already /* phone */ @media screen to change the style (themes.yaml and button_card_templates.yaml). To change the content you could do something like this

  sidebar_template:
    ...
    name: |
      [[[
        if (window.navigator.userAgent.match(/iPhone/i)) {
          return 'iPhone content';
        }
        else if (entity) {
          let attributes = '';
          for (const [key, value] of Object.entries(entity.attributes)) {
            value != false ? attributes += `<p>${value}</p>` : null;
          }
          return attributes;
        }
      ]]]
2 Likes

I don’t know if it’s possible. I use the default width unless I need more. There’s also large config var here.

You’re missing a lot of styling there, also is the vacuum card set up properly with coordinates etc?

Hi Guys.

i finally converted from the old dashboard to the new setup with button-cards. It is super cool.

I have one problem with the background image is not loading, and i simply can’t figure out why.

have the following config in my theme:

  card-mod-theme: tablet

  card-mod-root: |
    ha-app-layout {
      background: url('/local/img/wallpanel/uibg.png');
      background-size: cover;
    }

  card-mod-view-yaml: |
    .: |
      hui-view {
        background: none !important;
        min-height: 100vh;
      }

But looking at the debugger it does not seem to load at all:

Anyone experienced the same? (the image url is accessible and i dont get any load errors, it just doesnt seem to be there at all.).

Did you call frontend.reload_themes?

screen

I actually do see the map. It’s only on the right. So I need to “scroll” to the right. Let me take a look again later today.

@Mattias_Persson yeah even rebooted the whole instance :smiley:

Weird, have you tried

      card-mod-theme: tablet

      card-mod-view-yaml: |
        .: |
          hui-view {
            background: url('/local/background.png') !important;
            background-size: cover !important;
            min-height: 100vh;
          }

Do you think there’s a way to change the columns number in ‘grid’ based on device?

I want to do something like that.
I know it’s not the correct syntax - what would be?

      - type: grid
        title: devices
        view_layout:
          grid-area: livingroom
        columns: 2
          mediaquery: 3

That worked, thank you very much for the hint.
Still weird that i had to put on another level in the CSS. :slight_smile:

Thank you Mattias, and thank you for the awesome work :rocket:

1 Like