A different take on designing a Lovelace UI

Hello, i have problem with click sound:

When I click on the button. kiosk browser gives me a sound playback error

“Failed to load sound: wrong URL or unsupported format?”

I transferred the sound files to www folder an edit settings for tablet

Hi! So first thanks @Mattias_Persson for this greet dashboard idea for everyone in this topic. So that everyone can give ther ideas to improve it even more… So Thats why i post this video of mine edited dashboard from you.
i hope you guys have any extra tips/tricks to improve the dashboards we make together
just a short link for 2 days (I wil get a full link)

Its a beta so things dont look like what they should look like

8 Likes

Which media / spotify popup is that? Could you share your code?

1 Like

@Emad131

If you’re using the code for the light that I’ve modified, then there is no close button.
You simply have to click or tap outside of the popup to close it.

If you want a close button you could add a title with a space - or the text you’d like, like this:

  light:
    template:
      - base
      - circle
      - loader
    variables:
      circle_input: >
        [[[
          if (entity) {
              // if light group get brightness from child to remove bounce
              let child = entity.attributes.entity_id,
                  brightness = child && states[child[0]].attributes.brightness
                      ? Math.round(states[child[0]].attributes.brightness / 2.54)
                      : Math.round(entity.attributes.brightness / 2.54);
              return brightness === 0 && entity.state !== 'off'
                  ? 1
                  : brightness
          }
        ]]]
      circle_input_unit: '%'
      light_entity: '[[[ return entity.entity_id ]]]'
    double_tap_action:
      action: fire-dom-event
      browser_mod:
        service: browser_mod.sequence
        data:
          sequence:
            #- service: browser_mod.close_popup
            - service: browser_mod.popup
              data:
                sequence:
                ## Title with close button 
                title: ' '
                style: >
                  --popup-background-color: transparent;
                content:
                  type: custom:more-info-card
                  entity: '[[[ return variables.light_entity; ]]]'
                card_mod:
                  style:
                    more-info-card:
                      $ha-card:
                        .: |
                          state-card-content {
                            display: none !important;
                          }
                        $: |
                          .card-header {
                            display: none !important;
                          }
                        more-info-light:
                          $: |
                            ha-attributes {
                              display: none !important;
                            }
                            .controls {
                              margin-bottom: 0 !important;
                            }

The following part of the code is the key here:

            - service: browser_mod.popup
              data:
                sequence:
                ## Title with close button 
                title: ' '
1 Like

KING!
Its working now <3

Here is my template code (Still wanna get every popup in my popup folder, but still working on it)

  Media_player_living:
    variables:
      media_on: >
        [[[ return !entity || ['on', 'playing', 'paused', 'idle'].indexOf(entity.state) !== -1; ]]]
      media_off: >
        [[[ return !entity || ['off', 'standby', 'unknown', 'unavailable'].indexOf(entity.state) !== -1; ]]]
      volume_control: '[[[ return entity.entity_id; ]]]'
      player: '[[[ return entity.entity_id; ]]]'
    tap_action:
      action: fire-dom-event
      browser_mod:
        service: browser_mod.popup
        data:
          style: >
            --popup-background-color: transparent;
            --popup-max-width: 2000px;
          card_mod:
            style:
              .: |
                ha-header-bar {
                  display: none !important;
                }
                :host {
                  --mdc-theme-surface: rgba(0,0,0,0);
                }
                @media screen and (max-width: 2000px) {
                  ha-header-bar {
                    display: none !important;
                  }
                }

          content:
            type: custom:mod-card
            card_mod:
              style:
                layout-card:
                  $grid-layout$:
                    hui-vertical-stack-card:
                      $: |
                        ha-card {
                          animation: border 1s forwards;
                        }
                      $hui-horizontal-stack-card:
                        $: |
                          #root {
                            height: 0% !important;
                            justify-content: center !important;
                            margin-top: 2.2em !important;
                          }

            card:
              type: custom:layout-card
              layout_type: custom:grid-layout
              layout:
                grid-template-columns: 500px 500px
                grid-template-rows: 1fr
                grid-column-gap: 15px
                grid-template-areas: |
                  "media  none"
                  "Actions  boobs"
                mediaquery:
                  #phone
                  "(max-width: 1250px)":
                    grid-template-areas: |
                      "media"
                      "none"

              cards:
                - type: vertical-stack
                  view_layout:
                    grid-area: media
                  cards:
                    - type: conditional
                      conditions:
                        - entity: media_player.hk_citation_one_d20393
                          state_not: 'off'
                      card:
                        type: custom:mini-media-player
                        volume_stateless: true
                        tap_action:
                          action: none
                        info: scrol
                        name: Woonkamer
                        group: false
                        volume_step: '2'
                        entity: media_player.hk_citation_one_d20393
                        sound_mode: full
                        artwork: full-cover
                        toggle_power: false
                        source: icon
                        hide:
                          name: true
                          source: true
                          next: true
                          prev: true
                          play_pause: true
                          volume: true
                          power: true
                        style: |
                          .flex {
                            display: block;
                            {% if not is_state('media_player.hk_citation_one_d20393','off') %}
                            filter: drop-shadow(0px 2px 2px rgba(0,0,0,1));
                            {% else %}
                            {% endif %}

                          } 

                          ha-card.--has-artwork .cover{
                            opacity: 0.9;

                          }

                          .entity__info__media {
                            opacity: 1 !important;
                            padding-right: 16px;
                            overflow: hidden;
                            height: 4.4em;
                            height: 90%;

                          }

                          ha-card > div.mmp-player > div.mmp-player__core.flex >
                          div.entity__icon {
                            {% if not is_state('media_player.hk_citation_one_d20393','off') %}
                            display: none;
                            {% endif %}

                          } ha-card > div.mmp-player > div.mmp-player__core.flex { }

                          mmp-media-controls {
                            {% if not is_state('media_player.hk_citation_one_d20393','off') %}
                            filter: drop-shadow(0px 2px 2px rgba(0,0,0,1));
                            flex-wrap: wrap-reverse !important;

                            {% endif %}

                          } mmp-powerstrip  {

                          } ha-card > div.mmp-player {
                            padding: 25px !important;
                            {% if not is_state('media_player.hk_citation_one_d20393','off') %}
                            {% else %}
                            #display: none !important;
                            {% endif %}

                          } ha-card > div.mmp-player {

                            {% if is_state_attr('media_player.hk_citation_one_d20393','media_content_id', 'Bluetooth') %}
                            position: relative;
                            height: 20vh;
                            {% else %}
                            position: absolute;
                            align-self: flex-start;
                            height: 100%;
                            {% endif %}

                            background: radial-gradient(circle, rgba(255,255,255,0) 10%, rgba(0,0,0,0.6) 90%) !important;
                            font-size: 0.9em !important;
                          } ha-card > div.mmp-player > div.mmp-player__adds {
                            position: absolute;
                            bottom: 25px;
                            padding: 0px 16px 0px 0px;

                          } div.flex.mmp-media-controls__media {
                              margin-bottom: -5px !important;
                            }



                - type: vertical-stack
                  cards:
                  - type: custom:spotify-card
                    spotify_entity: media_player.spotify_jacobien_cristian
                    playlist_type: 
                    grid_covers_per_row: '4'
                    limit: 40
                    country_code: NL
                    display_style: grid
                    default_device: Speaker Woonkamer

                    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: 0,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: horizontal-stack
                    cards:
                      - type: custom:button-card
                        icon: >-
                          [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                          'custom:nvidia-m' : 'mdi:power'; ]]]
                        tap_action:
                          action: call-service
                          service: >-
                            [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                            'script.living_room_set_inputs_to_shield' :
                            'media_player.turn_off'; ]]]
                          service_data:
                            entity_id: >-
                              [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                              'none' : variables.player; ]]]
                        template: icon_button
                      - type: custom:button-card
                        icon: >-
                          [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                          'custom:nvidia-m' : 'mdi:skip-previous'; ]]]
                        tap_action:
                          action: call-service
                          service: >-
                            [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                            'script.living_room_set_inputs_to_shield' :
                            'media_player.media_previous_track'; ]]]
                          service_data:
                            entity_id: >-
                              [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                              'none' : variables.player; ]]]
                        template: icon_button
                      - type: custom:button-card
                        icon: >-
                          [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                          'bha:apple-tv' : 'mdi:play-pause'; ]]]
                        tap_action:
                          action: call-service
                          service: >-
                            [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                            'script.living_room_set_inputs_to_apple_tv' :
                            'media_player.media_play_pause'; ]]]
                          service_data:
                            entity_id: >-
                              [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                              'none' : variables.player; ]]]
                        double_tap_action:
                          action: call-service
                          service: >-
                            [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                            'script.living_room_set_inputs_to_apple_tv' :
                            'media_player.media_stop'; ]]]
                          service_data:
                            entity_id: >-
                              [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                              'none' : variables.player; ]]]
                        hold_action:
                          action: call-service
                          service: >-
                            [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                            'script.living_room_set_inputs_to_apple_tv' :
                            'media_player.media_stop'; ]]]
                          service_data:
                            entity_id: >-
                              [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                              'none' : variables.player; ]]]
                        template: icon_button
                      - type: custom:button-card
                        icon: >-
                          [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                          'custom:sonos' : 'mdi:skip-next'; ]]]
                        tap_action:
                          action: call-service
                          service: >-
                            [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                            'script.living_room_set_input_to_sonos' :
                            'media_player.media_next_track'; ]]]
                          service_data:
                            entity_id: >-
                              [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                              'none' : variables.player; ]]]
                        template: icon_button
                      - type: custom:button-card
                        icon: >-
                          [[[ return entity.entity_id === 'media_player.denon_receiver' ?
                          'custom:sonos' : 'mdi:volume-off'; ]]]
                        tap_action:
                          action: call-service
                          service: input_boolean.toggle
                          service_data:
                            entity_id: input_boolean.mute
                        template: icon_button
                  - type: horizontal-stack
                    cards:
                      - type: entities
                        entities:
                          - type: custom:slider-entity-row
                            entity: media_player.hk_citation_one_d20393
                            full_row: true
                            step: 5
                            grow: true
                            max: 100
                        style: |
                          ha-card {
                            margin-top: -40px;
                          }```

Very nice thanks! Do you also have the code for the icons? Will take some work to get it running for my setup

Would love to get peoples guidance on how to make a button “light up” while a script is running.

I have a sprinkler/irrigation system. Right now, I have to press one button to start the watering and a different button to stop it mid-cycle. Each button successfully calls a service. Right now, pressing the ‘Run’ button works fine, but it doesn’t stay lit-up while any zone is watering. I would like to fix that. Anyone have any suggestions on how? Once I get that figured out, I am going to combine the two buttons so a long-tap performs the stop. For reference, here is my ui-lovelace-tablet.yaml code for the two buttons, and they both currently work as expected.:


      - type: grid
        title: Sprinklers
        view_layout:
          grid-area: outside
        columns: 2
        cards:

          - type: custom:button-card
            name: Run
            tap_action:
              action: call-service
              service: bhyve.start_program
              service_data:
                entity_id: switch.outside_mysprinklers_main_program_program
              target: {}
            template:
              - base
              - icon_sprinkler

          - type: custom:button-card
            name: Stop
            tap_action:
              action: call-service
              service: script.turn_on
              service_data:
                entity_id: script.sprinkler_stop_scrpt
              target:
                entity_id: script.sprinkler_stop_scrpt
            template:
              - light
              - icon_sprinkler

Thank You!

I think that could be done by using an input boolean to trigger and stop your script instead. Probably you need to make an automation to trigger the script from the input boolean. I’m not too experienced with that, but maybe it gives you an idea :slight_smile:

Hello, I am using your code, but it seems different from yours and the color palette does not pop up a color selector. I am confused, how can I solve it?

@Adelina , have you updated HA?

1 Like

No, I haven’t updated it because the latest version of the physical status won’t be translated

hey i am following your theme and i have some problem with icon animation:

on the bottom left I have a menu button whose code looks like this:

          # MENU PARTER
          - type: conditional
            conditions:
              - entity: input_boolean.pietro
                state: "off"
            elements:
              - entity: input_boolean.menu_parter
                template: 
                  - podstawowy
                  - ikona_pietro
                style:
                  top: 84.5%
                  left: 9%
                type: custom:hui-element
                row_type: custom:button-card

the animation of the button itself works without a problem:

podstawowy:
  template:
    - ustawienia
    - tilt
    - extra_styles
  variables:
    state_on: >
      [[[ return ['on', 'home', 'cool', 'fan_only', 'playing', 'unlocked', 'cleaning'].indexOf(!entity || entity.state) !== -1; ]]]
    state_off: >
      [[[ return ['off', 'paused', 'docked'].indexOf(!entity || entity.state) !== -1; ]]]
  show_state: true
  show_icon: false
  tap_action:
    ui_sound_tablet: |
      [[[
        if (variables.state_off) {
            hass.callService('media_player', 'play_media', {
                entity_id: variables.entity_browser_mod,
                media_content_id: '/local/sound/on.m4a',
                media_content_type: 'music'
            });
        }
        if (variables.state_on) {
            hass.callService('media_player', 'play_media', {
                entity_id: variables.entity_browser_mod,
                media_content_id: '/local/sound/off.m4a',
                media_content_type: 'music'
            });
        }
      ]]]
    card_bounce: |
      [[[
        // add animation
        if (this.getElementsByTagName("style").length === 0) {

            // phone condition
            let mq = window.matchMedia('(max-width: 800px)').matches;

            let style = document.createElement('style');

            style.innerHTML = `
                @keyframes card_bounce {
                    0%   { transform: scale(1); }
                    10%  { transform: scale(${ mq ? '0.92' : '0.94' }); }
                    25%  { transform: scale(1); }
                    30%  { transform: scale(${ mq ? '0.96' : '0.98' }); }
                    100% { transform: scale(1); }
                }
            `;

            this.appendChild(style);
        }

        // duration
        let duration = 800;

        // animate
        this.style.animation = `card_bounce ${duration}ms cubic-bezier(0.22, 1, 0.36, 1)`;

        // reset
        window.setTimeout(() => { this.style.animation = "none"; }, duration + 100)
      ]]]
    action: toggle
  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: 1.3%
      - align-items: start
      - will-change: transform
    name:
      - justify-self: start
      - line-height: 121%
    state:
      - justify-self: start
      - line-height: 115%
    card:
      - height: 165px
      - width: 150px
      - border-radius: var(--button-card-border-radius)
      - border-width: 0
      - -webkit-tap-highlight-color: rgba(0,0,0,0)
      - transition: none
      - --mdc-ripple-color: >
          [[[
            return variables.state_on
                ? 'rgb(0, 0, 0)'
                : '#97989c';
          ]]]
      - color: >
          [[[
            return variables.state_on
                ? '#4b5254'
                : '#97989c';
          ]]]
      - background-color: >
          [[[
            return variables.state_on
                ? 'rgba(255, 255, 255, 0.85)'
                : 'rgba(0, 0, 0, 0.4)';
          ]]]

However, the animation of the icon does not want to work for me. Do you know why?

ikona_pietro:
  styles:
    custom_fields:
      icon:
        - width: 100%
        - margin-left: -14%
        - margin-top: 1%
  custom_fields:
    icon: >
      [[[
        let state = variables.state_on && variables.timeout < 2000 ? 'on' : null;
        return `
          <svg viewBox="0 0 128 128" width="64px" height="64px">
            <style>
              @keyframes on {
                0% {
                  transform: scale(0.85);
                }
                20% {
                  transform: scale(1.1);
                }
                40% {
                  transform: scale(300);
                }
                60% {
                  transform: scale(1.03);
                }
                80% {
                  transform: scale(0.97);
                }
                100% {
                  transform: scale(1);
                }
              }
              .on {
                animation: on 0.8s;
                transform-origin: center;
              }
            </style>
            <rect x="26.2" y="47.7" class="${state} light-color" width="42.8" height="52.3"/>
            <path fill="#9da0a2" d="M36.2,102.7h-10c-1.7,0-3-1.3-3-3v-72c0-1.7,1.3-3,3-3h43c1.7,0,3,1.3,3,3s-1.3,3-3,3h-40v66h7c1.7,0,3,1.3,3,3S37.9,102.7,36.2,102.7z"/>
            <path fill="#9da0a2" d="M103.2,102.7h-47c-1.7,0-3-1.3-3-3s1.3-3,3-3h44v-46h-31c-1.7,0-3-1.3-3-3s1.3-3,3-3h34c1.7,0,3,1.3,3,3v52C106.2,101.4,104.9,102.7,103.2,102.7z"/>
            <path fill="#9da0a2" d="M49.2,50.7h-23c-1.7,0-3-1.3-3-3s1.3-3,3-3h23c1.7,0,3,1.3,3,3S50.9,50.7,49.2,50.7z"/>
            <path fill="#9da0a2" d="M69.2,101.3c-1.7,0-3-1.3-3-3V64.8c0-1.7,1.3-3,3-3s3,1.3,3,3v33.5C72.2,99.9,70.9,101.3,69.2,101.3z"/>
          </svg>
        `;
      ]]]

transform: scale(300); - I use this value for the test to see the animation better, unfortunately nothing is animated

2 Likes

Hi Guys,
Does anybody know how i can achieve sound on button clicks like mattias has in the config?

I like your interface style. Can you share the complete code?

1 Like

Have you solved the translation problem? What should I do if I still haven’t been translated after adding language? Please help me, thank you

@Laffer @Mattias_Persson After upgrading to the new version, the physical state of the card will become English and cannot be translated into my native language. Do you know how to solve this problem? I have been stuck in the old version for this I’m confused

There’s an issue open for it on github: Entity State displays „raw“ Informations · Issue #685 · custom-cards/button-card · GitHub. It’s an issue with the button-card. Also see the latest comment on: 2023.1.0 broke entity state display in local language · Issue #646 · custom-cards/button-card · GitHub. Hopefully it will be fixed soon :slight_smile:

I put a remote finder button in the footer. The code for the button is

- type: custom:button-card
  entity: script.shield_remote_finder
  name: >
    <ha-icon icon="mdi:remote-tv"></ha-icon> Find Remote
  template:
    - footer
  tap_action:
    action: toggle
  lock:
    enabled: true
    duration: 10
    unlock: hold

But the lock is not covered on the whole button. It only covers the top half of the button. See the mouse icon in the two pictures below
image
image

Any idea how to solve this?

Thank you. I will continue to monitor the card updates until the issue is resolved and I am upgrading the system version.

1 Like

thanks, when I finish the whole project, I will share the whole code here on the forum :slight_smile:

3 Likes