A different take on designing a Lovelace UI

For those that are interested, I managed to get it working except for the TILT part. Please let me know if you want to use it also, I can share my code. Hoping someone is able to help me getting the TILT work on this card also… :smiley:
ezgif.com-gif-maker(1)

9 Likes

I’m interested in !!

Yes please! :smiley:

here is the relevant part. Please note that I changes the input select part so the conditions are wrong, but the styling should work.

@klidberg @Tarlak

          - type: custom:swipe-card
            parameters:
              speed: 550
              spaceBetween: 40
              threshold: 5
            cards:
              - type: horizontal-stack
                  #####################################
                  #          MEDIA VAN MART           #
                  #####################################
                cards:

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media_mart
                        state_not: Spotify Mart
                    card:
                      type: custom:spotify-card
                      account: mart
                      spotify_entity: media_player.spotify_mart
                      playlist_type: discover-weekly
                      grid_covers_per_row: '2'
                      limit: 4
                      country_code: NL
                      display_style: grid
                      default_device: Living room and Kitchen

                      card_mod:
                        style: |
                          ha-card {
                            border-radius: calc(var(--custom-button-card-border-radius) / 2) !important;  /* card - rounded corners */
                            aspect-ratio: 2/2 !important;  /* card - square */
                            margin: 0px !important;  /* remove card margins to line up with rest of dashboard */
                            padding: 0% !important;
                          }
                          .grid{
                            object-fit: cover !important;  /* fill the whole card */
                            aspect-ratio: 1/1;  /* needed for object-fit */
                            border-radius: calc(var(--custom-button-card-border-radius) / 2) !important;  /* card - rounded corners */
                            margin: 0px !important;  /* remove card margins to line up with rest of dashboard */
                            gap: 5% !important;
                          }
                          .btn {
                            top: 50% !important;  /* center buttons */
                          }
                          .grid-item{
                            border-radius: var(--button-card-border-radius) !important;
                            object-fit: cover !important;  /* fill the whole card */
                            aspect-ratio: unset;  /* undo image aspect-ratio when clicked */
                            box-shadow:none !important;
                            color: transparent !important;
                          }
                          .grid-item-album-image img{
                            border-radius: var(--button-card-border-radius) !important;
                            object-fit: cover !important;  /* fill the whole card */
                            aspect-ratio: unset;  /* undo image aspect-ratio when clicked */
                            margin: 0px !important;  /* remove card margins to line up with rest of dashboard */
                          }
                          .grid-item:hover{
                            box-shadow:none !important;
                            color: transparent !important;
                          }
                          .grid-item-album-image.playing{
                            border-radius: var(--button-card-border-radius) !important;
                          }
                          #header{
                            display:none !important;
                          }
                          #footer{
                            display:none !important;
                          }
                          .playback-controls{
                            display:none !important;
                          }
                          #header-track{
                            display:none;
                          }
                          #content{
                            border: 0px !important;
                            background-color: transparent !important;
                          }

                  - type: conditional
                    conditions:
                      - entity: media_player.spotify_mart
                        state_not: idle
                      - entity: media_player.spotify_mart
                        state_not: 'off'
                      - entity: media_player.spotify_mart
                        state_not: unknown
                      - entity: media_player.spotify_mart
                        state_not: unavailable
                    card:
                      type: custom:button-card
                      entity: media_player.spotify_mart
                      template:
                        - conditional_media
                        - icon_spotify
8 Likes

Thanks !! :star_struck:

Hello all,
I’m trying to modify the update button logic from watchtower to home assistant update service.

I created a test button in a temporary dashboard and it works, here’s the code:

type: custom:button-card
entity: sensor.current_version
name: Aggiorna Home Assistant
variables:
  latest: sensor.home_assistant_versions
  latest_beta: sensor.home_assistant_versions_beta
tap_action:
  action: call-service
  service: update.install
  service_data:
    entity_id: update.home_assistant_core_update

i then tried to port this code inside the update yaml but it loks like it is not working:

          - type: custom:button-card
            entity: sensor.current_version
            name: Aggiorna Home Assistant
            variables:
              latest: sensor.home_assistant_versions
              latest_beta: sensor.home_assistant_versions_beta
            tap_action:
              action: call-service
              service: update.install
              service_data:
                entity_id: update.home_assistant_core_update
            template: updates_hass_icon_name

Does anyone has an idea why it is not working?

Thanks for your help!
Davide

I did some digging and thought I’d give an update.

I’m not clever enough to find and solve the actual issue. But disabling tilt from all devices solved my issues.

Not a big loss for me, as I wasn’t getting the the floating card element that I’ve seen in animated examples here, so it felt rather flat still.

Hello everyone,

I need some help if anyone is so kind. I’m trying to make menu title dynamic as shown in this video. Any ideas how to do it?

Video

Hi
Does anyone know how to delete the scroll bars ?
Thanks

action: fire-dom-event
browser_mod:
  service: browser_mod.popup
  data:
    title: NAS
    style: >
      --popup-max-width: calc(385px + 385px);
      --ha-card-border-radius: 0;
    card_mod:
      style:
        layout-card:
          $grid-layout$:
            # card divider border
            .: |
              #root {
                  margin: -24px 0 !important;
              }
            hui-entities-card:
              $: |
                .card-content {
                  padding: var(--tablet-popup-content-padding);
                  padding-bottom: 0.8em;
                }
                ha-card {
                  border-right: 1.5px solid rgba(0, 0, 0, 0.2);
                  border-radius: 0;
                  transition: none;
                }
                /* portrait */
                @media screen and (max-width: 1200px) {
                  ha-card {
                    border-right: none;
                    border-bottom: 1.5px solid rgba(0, 0, 0, 0.2);
                  }
                }
              $hui-horizontal-stack-card:
                # horizontal bottom buttons
                $: |
                  #root {
                    justify-content: space-evenly;
                    margin-top: 1.7em;
                    max-width: 82vw; /* iphonex */
                  }
    content:
      type: custom:layout-card
      layout_type: custom:grid-layout
      layout:
        margin: 0
        grid-template-columns: 385px 385px
        grid-template-rows: 1fr
        grid-template-areas: |
          "hass nas"
        mediaquery:
          #portrait
          "(max-width: 1200px)":
            grid-template-columns: 1fr
            grid-template-rows: repeat(2, 1fr)
            grid-template-areas: |
              "hass"
              "nas"
      cards:

        ### HOME ASSISTANT

        - type: entities
          view_layout:
            grid-area: hass
          title: Home Assistant
          show_header_toggle: false
          card_mod:
            class: header
          entities:
            - entity: sensor.current_version
              name: Version actuelle
              icon: mdi:home-assistant

            - entity: sensor.template_hass_next_release

            - entity: sensor.db_size
              icon: mdi:database

            - entity: sensor.home_assistant_log_size
              name: Log
              icon: mdi:file-document

            - entity: sensor.uptime
              name: Dernier redémarrage
              icon: mdi:update

        ### Unraid

        - type: entities
          view_layout:
            grid-area: nas
          title: Unraid
          show_header_toggle: false
          card_mod:
            class: header
            # no border on last card
            style: |
              ha-card {
                border: none !important;
              }
          entities:
            - type: custom:bar-card
              width: 55%
              height: 2em
              decimal: 0
              unit_of_measurement: '%'
              positions: &bar_card_positions
                icon: outside
                indicator: 'off'
                name: outside
              severity: &bar_card_severity
                - color: '#6d2525'
                  from: 85
                  to: 999
              entity_row: true
              entities:

                - entity: sensor.glances_cpu_used
                  name: Processor
                  tap_action:
                    action: call-service
                    service: homeassistant.update_entity
                    service_data:
                      entity_id: sensor.glances_cpu_used

                - entity: sensor.glances_ram_used_percent
                  name: RAM - 16GB
                  tap_action:
                    action: call-service
                    service: homeassistant.update_entity
                    service_data:
                      entity_id: sensor.glances_ram_used_percent

                - entity: sensor.glances_mnt_disk1_used_percent
                  name: Stockage 4TB
                  tap_action:
                    action: call-service
                    service: homeassistant.update_entity
                    service_data:
                      entity_id: sensor.glances_mnt_disk1_used_percent

                - entity: sensor.glances_mnt_cache_used_percent
                  name: Cache 1TB
                  tap_action:
                    action: call-service
                    service: homeassistant.update_entity
                    service_data:
                      entity_id: sensor.glances_mnt_cache_used_percent

            - type: custom:hui-horizontal-stack-card
              cards:
                - type: custom:button-card
                  name: Adguard
                  icon: mdi:shield
                  entity: switch.adguard_protection
                  template:
                    - icon_name
                    - icon_adguard
          
          footer:
            type: custom:mini-graph-card
            show:
              name: false
              icon: false
              state: false
              legend: true
            entities:
              - entity: sensor.deluge_down_speed
                name: Download
              - entity: sensor.deluge_up_speed       
                name: Upload
2 Likes

Thank you!

Hello. How did you make a playlist appear on the card?

@Mattias_Persson hi sorry if i tag you i’m trying to get the card update working but i succeeded in everything, but i miss understanding how you created the hass latest and latest beta entities. could you help me?

Hey guys,
can someone explain me how to change the date format in the media card?
Where should I put “| timestamp_custom(’%d-%m-%Y’)”?

Thanks !

Here is my code:

      #################################################
      #                                               #
      #                     Media                     #
      #                                               #
      #################################################
      - type: grid
        title: Media
        view_layout:
          grid-area: media
        columns: 1
        cards:
          - type: custom:button-card
            entity: sensor.trakt_upcoming_shows
            name: Serien / Filme
            tap_action:
              action: none
            template:
              - conditional_media



  #################################################
  #                                               #
  #               CONDITIONAL MEDIA               #
  #                                               #
  #################################################

  conditional_media:
    aspect_ratio: 1000/996
    template:
      - base
  #    - media_youtube
      - icon_play_pause
    variables:
      i: >
        [[[
          let data = entity.attributes.data;
          if (entity && data) {
            return Math.floor(Math.random() * (data.length - 1)) + 1;
          }
        ]]]
    state_display: >
      [[[
        if (entity) {
          let elt = this.shadowRoot,
            await = setTimeout(marquee,0),
            data = entity.attributes.data,
            artist = entity.attributes.media_artist,
            title = entity.attributes.media_title;

            if (data !== undefined) {
              var number = data[variables.i].number === undefined && data[variables.i].aired !== undefined
                ? `(${data[variables.i].aired.split("-")[0]})`
                : data[variables.i].number === undefined && data[variables.i].aired === undefined
                  ? ' '
                  : data[variables.i].number,
                output = `${data[variables.i].title} ${number} - ${data[variables.i].airdate}`;
            } else {
              var output = artist === undefined && title !== undefined
                ? title
                : title === undefined && artist !== undefined
                  ? artist
                  : title !== undefined && artist !== undefined
                    ? `${artist} - ${title}`
                    : variables.translate_idle;
            }

          function marquee() {
            let state = elt.getElementById("state"),
              container = elt.getElementById("container");

            if (state && container) {
              state.innerHTML = output;
              let ro = new ResizeObserver(entries => {
                let spacer = " ".repeat(3),
                  s = entries[0],
                  c = entries[1],
                  r = s && s.contentRect &&
                      c && c.contentRect &&
                      s.contentRect.width !== 0 &&
                      c.contentRect.width !== 0;

                if (r && s.contentRect.width < c.contentRect.width) {
                  state.classList.remove("marquee");
                }
                else if (r && s.contentRect.width >= c.contentRect.width) {
                  state.innerHTML = `${output} ${spacer} ${output} ${spacer}&nbsp;`;
                  state.classList.add("marquee");
                }
              });
              ro.observe(state);
              ro.observe(container);
            }
          }
          return output;
        }
        return variables.translate_unknown; 
      ]]]
    tap_action:
      action: call-service
      service: media_player.media_play_pause
      service_data:
        entity_id: >
          [[[ return variables.entity_id; ]]]
    styles:
      grid:
        - gap: 0.65%
      name:
        - padding: 0.2vw
        - margin: -0.2vw
        - width: 100%
      state:
        - padding-bottom: 5.25%
        - max-width: unset
        - overflow: visible
      card:
        - padding: 5.75% 5.25% 0 5.75%
        - border-radius: calc(var(--custom-button-card-border-radius) / 2)
        - background: rgba(115, 115, 115, 0.2) center center/cover no-repeat
        - background-image: &media_background_image >
            [[[
              return entity.attributes.data !== undefined
                ? `url("${entity.attributes.data[variables.i].fanart}"), url("${entity.attributes.data[variables.i].poster}")`
                : `url("${variables.entity_picture}")`;
            ]]]
        - color: >
            [[[
              return entity === undefined
                ? 'rgba(255, 255, 255, 0.3)'
                : '#efefef';
            ]]]
        - text-shadow: >
            [[[
              return entity === undefined
                ? 'none'
                : '1px 1px 5px rgba(18, 22, 23, 0.9)';
            ]]]
      custom_fields:
        icon:
          - width: 30%
          - fill: >
              [[[
                return entity && variables.media_on
                  ? 'rgba(255, 255, 255, 0.8)'
                  : '#9da0a2';
              ]]]
        blur_overlay:
          - display: block
          - position: absolute
          - width: 103.1%
          - height: 103.1%
          - filter: var(--blur-intensity)
          - clip-path: >
              inset(74.5% 1.45% 1.45% 1.45% round 0 0 calc(var(--custom-button-card-border-radius) / 2) calc(var(--custom-button-card-border-radius) / 2))
          - background: center center/cover no-repeat
          - background-image: *media_background_image
          - left: -1.5%
          - bottom: -1.6%
    custom_fields:
      blur_overlay: >
        [[[
          setTimeout(() => {
            let elt = this.shadowRoot,
              card = elt.getElementById('card'),
              container = elt.getElementById('container'),
              blur_overlay = elt.getElementById('blur_overlay');

            if (elt && card && container && blur_overlay) {
              card.insertBefore(blur_overlay, container);
            }
          }, 0);
          return ' ';
        ]]]


I have the same problem. the card as I insert the sensor.current_versio created ui goes in error.

ButtonCardJSTemplateError: TypeError: Cannot read properties of undefined (reading ‘state’) in ‘if (entity) { let links = new RegExp(’<a href="([^"]+)"’, “g”), installed = entity…’

I have and had already added those sensors … but unfortunately the error in the card remains. c

Try this

image
I’m hoping someone can help guide me on how to fix this issue with the graph custom_fields. Whenever I activate tilt all the graphs are shifted like the picture. I have tilt active only on windows so on my phone the graphs look perfectly fine. I’m wondering if anyone has a fix for this ! Thanks

Whatever you’re using for the template, you need to adjust the positioning and maybe height of the graph in the style section.

Here’s an example you can play around with:

temperature:
  template:
    - base2
    - extra_styles
  show_name: true # Hides Card Name
  show_state: true # Hides Card state
  state_display: >
    [[[ return '&nbsp;'; ]]]
  custom_fields:
    graph:
      card:
        type: "custom:mini-graph-card"
        height: 140
        hours_to_show: 24
        points_per_hour: 1
        line_width: 8
        font_size: 75
        decimals: 0
        show:
          name: false
          icon: false
          state: false
          legend: false
          labels: false
          labels_secondary: false
          points: false
        color_thresholds:
          - value: 65
            color: "#276696"
          - value: 77
            color: "#228C22"
          - value: 79
            color: "#d35400"
          - value: 80
            color: "#c0392b"
              
  styles:
    custom_fields:
      graph: [bottom: 0%, left: 0%, width: 130%, position: absolute, margin: 0% 0% -14% -15.2%]
      icon:
        - width: 67%
        - fill: "#9da0a2"

            
icon_temp:
  styles:
    custom_fields:
      icon:
        - margin-top: 2%
  custom_fields:
    icon: >
      <svg viewBox="10 5 50 50">
        <style>@keyframes animate{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);}}.animate{animation: animate 0.8s; transform-origin: center;}</style>
        <path fill="#9da0a2" d="M41.74 10.852v2h-7.75v-2zm-3.25 4.36h-4.5v2h4.5zm-4.5 6.36h7.75v-2h-7.75zm4.5 2.36h-4.5v2h4.5zm-4.5 6.36h7.75v-2h-7.75zM35.2 41.685A10.14 10.14 0 0 1 25.074 51.81a10.14 10.14 0 0 1-10.125-10.125c0-3.618 1.9-6.906 5-8.725V10.006c0-2.826 2.3-5.125 5.125-5.125s5.125 2.3 5.125 5.125V32.96c3.1 1.817 5 5.106 5 8.725zm-2 0c0-3.07-1.706-5.845-4.453-7.24l-.547-.278v-24.16a3.13 3.13 0 0 0-3.125-3.125 3.13 3.13 0 0 0-3.125 3.125v24.16l-.547.278a8.09 8.09 0 0 0-4.453 7.24c0 4.48 3.645 8.125 8.125 8.125s8.125-3.645 8.125-8.125zm-1.666 0a6.47 6.47 0 0 1-6.459 6.458 6.47 6.47 0 0 1-6.458-6.458 6.46 6.46 0 0 1 4.796-6.233l.37-.1v-22.23h2.583v22.23l.37.1a6.46 6.46 0 0 1 4.796 6.233zm-6.14-4.305c-.154-.684-.842-1.134-1.543-.974a5.31 5.31 0 0 0-4.158 5.207 1.29 1.29 0 0 0 2.58 0c0-1.277.902-2.41 2.147-2.7.692-.16 1.13-.85.974-1.543z"/>
      </svg>

using the spotify lovelace card (as I wrote in my message earlier)

1 Like