A different take on designing a Lovelace UI

sure no problem, im not a programmer all im doing with Mattias code is thrugh trial and error, just trying to read what he has done. i don´t know if that´s the best way to do it but i’ve created a template to use only with my water card and not changing other circles through the dashboard. then i just replaced the stroke color from stroke="#313638" to stroke="#03a9f4". see below my card code. also i’ve add graph to it.

  water:
    template:
      - base
    show_state: false
    custom_fields:
      circle: >
        [[[ {
        const reabastecimentos = Math.round(entity.state);
        const radius = 20.5;
        const circumference = radius * 2 * Math.PI;
        return `<svg viewBox="0 0 50 50"><style>circle { transform: rotate(-90deg); transform-origin: 50% 50%;stroke-dasharray: ${circumference};stroke-dashoffset: ${circumference - reabastecimentos / 100 * circumference};}
        tspan {font-size: 10px;}</style> <circle cx="25" cy="25" r="24.5" stroke="#03a9f4" stroke-width="1.5" fill="#FFFFFF08" style="
        transform: rotate(-90deg); transform-origin: 50% 50%;" />
        <text x="50%" y="54%" fill="#8d8e90" font-size="11" text-anchor="middle" alignment-baseline="middle" dominant-baseline="middle">${reabastecimentos}</text></svg>`; } ]]]
      graph:
        card:
          type: "custom:mini-graph-card"
          line_color: "#3182b7"
          line_width: 4
          font_size: 75
          upper_bound: ~100
          lower_bound: ~0
          show:
            name: false
            icon: false
            state: false
            legend: false
            labels: false
    styles:
      name: [top: 57%, left: 0%, width: 100%, position: absolute]
      custom_fields:
        graph: [bottom: 0%, left: 0%, width: 100%, position: absolute]
        circle:
          [
            top: 6.5%,
            left: 54.5%,
            width: 3.5vw,
            position: absolute,
            letter-spacing: 0.03vw,
          ]
        icon:
          - width: 67%
          - fill: "#9da0a2"
1 Like

yeah true,
but I still want to have the option to swipe once to get to my buttons for the bathroom while the washer is on and the picture-entities card is shown :slight_smile:

Now I happy I find this one nice work

I solved the problem with the state-switch. Works like a charm to who it whom.

type: custom:state-switch
entity: sensor.washer_status
states:
  'True':
    type: custom:swipe-card
    parameters:
      roundLengths: true
      effect: coverflow
      speed: 650
      spaceBetween: 20
      threshold: 7
      coverflowEffect:
        rotate: 80
        depth: 300
    cards:
      - type: picture-elements
        aspect_ratio: 100%
        image: /local/washer.png
        elements:
          - entity: sensor.power_washer
            style:
              color: black
              font-size: 1rem
              left: 15%
              top: 93%
            type: state-label
          - entity: sensor.consumption_22
            style:
              color: black
              font-size: 1rem
              left: 70%
              top: 93%
            type: state-label
          - entity: sensor.washer_status
            state_image:
              'True': /local/washer_on.gif
              'False': /local/washer.png
            style:
              clip-path: circle(30% at center)
              width: 100%
              left: 50%
              top: 50%
            tap_action:
              action: more-info
            type: image
      - type: grid
        columns: 2
        cards:
          - type: custom:button-card
            entity: light.badezimmer_spiegel
            name: Spiegel
            template:
              - light
            custom_fields:
              icon: >
                <ha-icon icon="phu:adore-mirror"
                style="color:var(--button-card-light-color);"></ha-icon>
          - type: custom:button-card
            entity: light.badezimmer_decke
            name: Decke
            template:
              - light
              - icon_spot
          - type: custom:button-card
            entity: sensor.xiaomi_bad_temperature
            name: Klima
            custom_fields:
              graph:
                card:
                  entities:
                    - sensor.xiaomi_bad_temperature
            tap_action:
              action: more-info
            template:
              - temperature
              - icon_temp
          - type: custom:button-card
            entity: binary_sensor.bewegungsmelder_bad
            name: Bewegung
            template:
              - base
              - icon_bathroom
  'False':
    type: grid
    columns: 2
    cards:
      - type: custom:button-card
        entity: light.badezimmer_spiegel
        name: Spiegel
        template:
          - light
        custom_fields:
          icon: >
            <ha-icon icon="phu:adore-mirror"
            style="color:var(--button-card-light-color);"></ha-icon>
      - type: custom:button-card
        entity: light.badezimmer_decke
        name: Decke
        template:
          - light
          - icon_spot
      - type: custom:button-card
        entity: sensor.xiaomi_bad_temperature
        name: Klima
        custom_fields:
          graph:
            card:
              entities:
                - sensor.xiaomi_bad_temperature
        tap_action:
          action: more-info
        template:
          - temperature
          - icon_temp
      - type: custom:button-card
        entity: binary_sensor.bewegungsmelder_bad
        name: Bewegung
        template:
          - base
          - icon_bathroom

1 Like

Hi! Have you managed to fix this issue? I have exactly the same symptoms as yours. For whatever reason I couldn’t find out, my tablet suddenly became extremely slow. I can’t even refresh it. I haven’t changed anything other than HA and HACS updates. it is only the tablet, my phone and computer works well. The way it is now, I’m considering to remove it from the wall. Thanks!

hello,

is that you mean

Date.now() - Date.parse(entity.last_changed) < 1000

something like that ?

and by the way i wanna ask what’s the meaning of entity === undefined? the return value of timeout, i dont understand the meaning of this code below.

      timeout: >
        [[[ return entity === undefined || Date.now() - Date.parse(entity.last_changed); ]]]

can you please explain this code? Thank you so much.

      timeout: >
        [[[ return entity === undefined || Date.now() - Date.parse(entity.last_changed); ]]]

thank you!!!

If you use Markdown for all the text and card-mod, then most likely that is your issue as well. Use button-card instead (which requires you to rebuild all your text elements). If you’re not using Markdown card, then I have no idea what your issue is.

Hi @Mattias_Persson Where the switch is declared.galaxy_tab_a_screensaver

1 Like

Hi @Mattias_Persson,

First of all I want to congratulate you for all your work for this dashboard that is amazing! I already followed your work in the other version, but this one is super! for beginners like me, it’s much easier.

I would like to ask, if this is possible, of course… In relation to the footer, where you use the Covid19 sensor, I would like to use a football sensor, which would pass the data from that sensor infinitivation. Is this possible?
Here’s the example of the sensor I have:

And the idea would be like this (image edited in photoshop):

Thanks!!

Thanks! Even removing the markdown, the slowness continues.
I believe my issue is related to the custom button card itself. I spent the weekend recreating a simpler version of my dashboard (removed the animation, custom icons, custom button formatting, etc). But even with this simpler version, when I include several buttons (20 buttons on the dashboard) it gets slow. If I insert a mini graph card, then it almost stops responding.
I have a FireHD 8 10th generation, I know it is not a very powerful tablet, but I hoped it would handle the dashboard

This looks great and more intuitive than than the standard Lovelace UI, I think. But i have no idea where to start. Can someone explain it a bit so i can give it a try or skip it because its to much hassel for me…

1 Like

Mattias, this is almost working perfectly! The only issue now is the light icon color. I have updated the button template code to your latest which includes the fill=“var(–light-color)” however I am getting a blue colour instead of the actual light colour. These are Philips hue lights but some of the ones I have do not have ‘hs’ functionality, only color_temp, maybe this is the issue? I have included a picture and the code below. Thank you!

  #################################################
  #                                               #
  #                     BASE                      #
  #                                               #
  #################################################

  base:
    variables:
      state: >
        [[[ return entity === undefined || entity.state; ]]]
      timeout: >
        [[[ return entity === undefined || Date.now() - Date.parse(entity.last_changed); ]]]
      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 'Okänt'; ]]]
    tap_action:
      ui_sound_tablet: |
        [[[
          const screensaver = states['switch.galaxy_tab_a_screensaver'] === undefined || 
            states['switch.galaxy_tab_a_screensaver'].state;
          if (variables.state === 'off' && screensaver === 'off') {
            hass.callService('media_player', 'play_media', {
              entity_id: 'media_player.c2080cea_6627150a',
              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.c2080cea_6627150a',
              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.consider_on ?
                'rgb(0, 0, 0)' :
                'rgba(255, 255, 255, 0.3)';
            ]]]
        - color: >
            [[[
              return variables.consider_on ?
                'rgba(0, 0, 0, 0.6)' :
                'rgba(255, 255, 255, 0.3)';
            ]]]
        - background-color: >
            [[[
              return variables.consider_on ?
                '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);
            }
          }
        `
      ]]]
  icon_pendants_3:
    styles:
      custom_fields:
        icon:
          - width: 187%
          - margin-left: '-3%'
          - margin-top: 1%
    custom_fields:
      icon: >
        [[[
          if (entity.state == 'on') {
            return `
              <svg viewBox="0 0 50 50">
              <style>
              @keyframes on {
              0% {transform: scale(0.85);}
              20% {transform: scale(1.1);}
              40% {transform: scale(0.95);}
              60% {transform: scale(1.03);}
              80% {transform: scale(0.97);}
              100% {transform: scale(1);}}.on{animation: on 0.8s; transform-origin: center;}
              </style>
              <path fill="var(--light-color)" d="M12 17.8c-6.7 0-10.4-1.3-10.4-2 0-.5 2.2-1.4 6.3-1.8 1.7-.1 3.6-.1 5.5-.1 5.8.2 9 1.3 9 1.9 0 .7-3.7 2-10.4 2m0-2.6c-.2 0-2.1 0-2.1.8s1.9.8 2.1.8 2.2 0 2.2-.8-2-.8-2.2-.8z"/>              
              <g class="on"><path fill="#9da0a2" d="M12 8.8c-3.9 0-11.4.6-11.4 3V16c0 2 7.5 2.8 11.4 2.8s11.1-.6 11.4-2.8v-4.2c0-2.4-7.5-3-11.4-3zm0 9c-6.7 0-10.4-1.3-10.4-2 0-.5 2.2-1.4 6.3-1.8 1.7-.1 3.6-.1 5.5-.1 5.8.2 9 1.3 9 1.9 0 .7-3.7 2-10.4 2m0-2.6c-.2 0-2.1 0-2.1.8s1.9.8 2.1.8 2.2 0 2.2-.8-2-.8-2.2-.8zm-.6-8v1.6h1V7.2c1.2-.1 2.5-.4 2.5-1.3v-.4c0-1-1.6-1.3-3-1.3s-3 .3-3 1.3v.4c0 .8 1.3 1.2 2.5 1.3z"/>              
              </svg>
            `;
          }
          if (entity.state == 'off') {
            return `
              <svg viewBox="0 0 50 50">
                <path fill="#9da0a2" d="M12 8.8c-3.9 0-11.4.6-11.4 3V16c0 2 7.5 2.8 11.4 2.8s11.1-.6 11.4-2.8v-4.2c0-2.4-7.5-3-11.4-3zm0 9c-6.7 0-10.4-1.3-10.4-2 0-.5 2.2-1.4 6.3-1.8 1.7-.1 3.6-.1 5.5-.1 5.8.2 9 1.3 9 1.9 0 .7-3.7 2-10.4 2m0-2.6c-.2 0-2.1 0-2.1.8s1.9.8 2.1.8 2.2 0 2.2-.8-2-.8-2.2-.8zm-.6-8v1.6h1V7.2c1.2-.1 2.5-.4 2.5-1.3v-.4c0-1-1.6-1.3-3-1.3s-3 .3-3 1.3v.4c0 .8 1.3 1.2 2.5 1.3z"/>
              </svg>
            `;
          }
        ]]]
3 Likes

Hello, PlopDropper, I liked your strip icons, you can share the code. Thank you in advance!

1 Like

Its working now, but “sensor.template_hacs_version” says its unavailable.
And if I put

    - unique_id: hacs_version
      state: >
        {{ device_attr(device_id('sensor.hacs'), 'sw_version') }}

in the Dev-Tools, it gives me the error:

TemplateError: str: Must provide a device or entity ID

Sensor.hacs works fine.

Any Ideas, or did I forgot something? Thanks again!

Edit: Solved my Problem. It didnt work with the legacy hacs-installation.

It’s intended as it can be hard to see the icons if they’re white or yellow on a light gray background

color_temp = shades of blue
hs = changes to actual color

If you don’t like this behavior you can use --button-card-light-color :innocent:

3 Likes

if your light is philips hue white ambiance, then it will not have hs mode. then in the dashboard, it will be always blue (or accent color of the theme).

2 Likes

First make a template sensor attribute

template:
  sensor:
    - unique_id: football
      state: template
      attributes:
        football: >
          {{ markdown... }}

then change state_display in coronavirus to

state_display: >
  [[[
    return entity.attributes.football;
  ]]]

and add your entity

- type: custom:button-card
  view_layout:
    grid-area: footer
  entity: sensor.template_football
  template: coronavirus
3 Likes

It’s not, setup using ui :woozy_face: