A different take on designing a Lovelace UI

No. Sorry didn’t have enough time ;-(

Has someone added a progressbar for the duration of a actually playing movie in the Media card?

Can anyone tell me why I can’t go further to the left? Or what I have to change so that I can get further to the left?

- type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: Kueche
                    card:
                      type: custom:button-card
                      template:
                        - conditional_media
                        - icon_apple_tv
                      entity: media_player.kueche
                      custom_fields:
                        progress:
                          card:
                            type: custom:bar-card
                            height: 0.4em
                            entities:
                              - entity: sensor.appletv_kueche_progress
                            positions:
                              icon: 'off'
                              indicator: 'off'
                              name: 'off'
                              value: 'off'
                            color: >
                              [[[ return 'var(--primary-color)'; ]]]
                            max: '100'
                            min: '0'
                            target: '0'
                            decimal: '2'
                            unit_of_measurement: ' '
                            severity:
                              - hide: true
                               
                      styles:
                       custom_fields:
                          progress:
                            - position: absolute
                            - width: 100%
                            - height: 100%
                            - margin: 70% 10% 0 0
                            - display: initial
                            - opacity: 1
                            - justify-self: end          
                      ```
1 Like

I’ve been trying to figure out the PS5 integration! Would you mind sharing your code?

Add sensor.ps5_activity as if it was a media player in packages/tv_media.yaml

To get the other info you’ll need to add some checks in button_card_templates/media.yaml for entity.attributes.title_image and entity.attributes.title_name.

I edited my file pretty heavily so I just applied the edits to the original one. It should work, but let me know if it doesn’t.

button_card_templates/media.yaml

#################################################
#                                               #
#                  BASE MEDIA                   #
#                                               #
#################################################

base_media:
  variables:
    media_on: >
      [[[ return !entity || ['playing', 'paused'].indexOf(entity.state) !== -1; ]]]
    media_off: >
      [[[ return !entity || ['off', 'idle', 'standby', 'unknown', 'unavailable', 'none'].indexOf(entity.state) !== -1; ]]]
  tap_action:
    action: >
      [[[
        return variables.media_on
            ? 'call-service'
            : 'none';
      ]]]
    service: media_player.media_play_pause
    service_data:
      entity_id: >
        [[[
          return variables.entity_id;
        ]]]
  double_tap_action:
    action: more-info
  styles:
    card:
      - color: >
          [[[
            let game_image = entity.attributes.title_image;
            if (variables.is_youtube) {
                return `#efefef`;
            } else {
                return entity && game_image !== undefined
                  ? '#efefef'
                  : variables.media_on && variables.entity_picture === undefined
                      ? 'rgba(0, 0, 0, 0.6)'
                      : variables.media_off
                          ? '#97989c'
                          : '#efefef';
            }
          ]]]
      - text-shadow: >
          [[[
            let game_image = entity.attributes.title_image;
            if (variables.is_youtube) {
                return `1px 1px 5px rgba(18, 22, 23, 0.9)`;
            } else {
                return entity && game_image !== undefined
                  ? '1px 1px 5px rgba(18, 22, 23, 0.9)'
                  : variables.media_off || variables.entity_picture === undefined
                      ? 'none'
                      : '1px 1px 5px rgba(18, 22, 23, 0.9)';
            }
          ]]]

#################################################
#                                               #
#                     MEDIA                     #
#                                               #
#################################################

media:
  template:
    - base
    - base_media
  styles:
    custom_fields:
      icon:
        - width: 70%
        - margin-left: 2%
        - fill: '#9da0a2'
        - display: >
            [[[
              let game_image = entity.attributes.title_image;
              if (variables.is_youtube) {
                  return `none`;
              }
              else {
                  return entity && game_image !== undefined
                    ? 'none'
                    : variables.media_off || variables.entity_picture === undefined
                        ? 'initial'
                        : 'none';
              }
            ]]]
    card:
      - background-color: none
      - background-size: cover
      - background-position: center
      - background-image: >
          [[[
            let game_image = entity.attributes.title_image;
            if (variables.is_youtube) {
                return `linear-gradient(0deg, rgba(0,0,0,.8) 0%, rgba(0,0,0,0) 100%), url(${states[this._config?.triggers_update].state})`;
            } else {
                return entity && game_image !== undefined
                  ? `linear-gradient(0deg, rgba(0,0,0,.8) 0%, rgba(0,0,0,0) 100%), url(${game_image})`
                  : variables.media_on && variables.entity_picture === undefined
                      ? 'linear-gradient(0deg, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0.8) 100%)'
                      : variables.media_off
                          ? 'linear-gradient(0deg, rgba(115, 115, 115, 0.2) 0%, rgba(115, 115, 115, 0.2) 100%)'
                          : `linear-gradient(0deg, rgba(0,0,0,.8) 0%, rgba(0,0,0,0) 100%), url(${variables.entity_picture})`;
            }
          ]]]

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

conditional_media:
  aspect_ratio: 1000/996
  template:
    - base
    - base_media
    - icon_play_pause
  variables:
    i: >
      [[[
        if (entity) {
            let data = entity.attributes.data;
            return data === undefined || Math.floor(Math.random() * (data.length - 1)) + 1;
        }
      ]]]
  state_display: >
    [[[
      let horizontalStack = this.getRootNode().host,
          swipeCard = horizontalStack.getRootNode().host,
          gridTitle = swipeCard.getRootNode().querySelector("h1");

      swipeCard.swiper.on("slideChange", () => {
          if (swipeCard.swiper.realIndex === 0) {
              gridTitle.textContent = "Media";
          }
          else if (swipeCard.swiper.realIndex === 1) {
              gridTitle.textContent = "Spelare";
          }
      });

      if (entity) {
          let elt = this.shadowRoot,
              await = setTimeout(marquee, 100),
              data = entity.attributes.data,
              artist = entity.attributes.media_artist,
              title = entity.attributes.media_title,
              game_title = entity.attributes.title_name;

            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}`;
            } else {
                var output = artist === undefined && title !== undefined
                    ? title
                    : game_title !== undefined
                      ? `${game_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
    state:
      - padding-bottom: 5.25%
      - max-width: unset
      - overflow: visible
    card:
      - padding: 5.75% 5.25% 0 5.75%
      - border-radius: calc(var(--button-card-border-radius) / 2)
      - background: rgba(115, 115, 115, 0.2) center center/cover no-repeat
      - background-image: &media_background_image >
          [[[
            if (entity) {
              if (variables.is_youtube) {
                  return `url(${states[this._config?.triggers_update].state})`;
              } else {
                let data = entity.attributes.data,
                game_image = entity.attributes.title_image;
                return game_image !== undefined
                  ? `url("${game_image}")`
                  : data && (data[variables.i].fanart || data[variables.i].poster)
                      ? `url("${data[variables.i].fanart}"), url("${data[variables.i].poster}")`
                      : `url("${variables.entity_picture}")`;
              }
            }
          ]]]
      - color: >
          [[[
            return entity === undefined
                ? '#97989c'
                : '#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(--button-card-border-radius) / 2) calc(var(--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 ' ';
      ]]]

Then you’ll also need to add sensor.ps5_activity as if it was a media player in ui-lovelace.yaml (this is the media section only and you only need to add the PlayStation bits)

      #################################################
      #                                               #
      #                     MEDIA                     #
      #                                               #
      #################################################

      - type: grid
        title: Media
        view_layout:
          grid-area: media
        columns: 1
        cards:

          - type: custom:swipe-card
            parameters:
              speed: 550
              spaceBetween: 40
              threshold: 5
            cards:

              - type: horizontal-stack
                cards:

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state_not: Shield TV

                      - entity: select.conditional_media
                        state_not: Master Bedroom TV

                      - entity: select.conditional_media
                        state_not: PS5 Activity

                      - entity: select.conditional_media
                        state_not: Garage TV

                      - entity: select.conditional_media
                        state_not: Upstairs TV

                    card:
                      type: custom:button-card
                      entity: sensor.plex_recently_added
                      name: Recently Added
                      tap_action:
                        action: none
                      template:
                        - conditional_media
                        - icon_plex

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: Shield TV
                    card:
                      type: custom:button-card
                      entity: media_player.shield_tv_plex
                      triggers_update: sensor.youtube_watching
                      template:
                        - conditional_media
                        - icon_shield_tv

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: Master Bedroom TV
                    card:
                      type: custom:button-card
                      entity: media_player.master_bedroom_tv_plex
                      triggers_update: sensor.youtube_watching
                      template:
                        - conditional_media
                        - icon_google_tv

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: Upstairs TV
                    card:
                      type: custom:button-card
                      entity: media_player.upstairs_tv_plex
                      triggers_update: sensor.youtube_watching
                      template:
                        - conditional_media
                        - icon_google_tv

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: PS5 Activity
                    card:
                      type: custom:button-card
                      entity: sensor.ps5_activity
                      template:
                        - conditional_media
                        - icon_playstation

                  - type: conditional
                    conditions:
                      - entity: select.conditional_media
                        state: Garage TV
                    card:
                      type: custom:button-card
                      entity: media_player.garage_tv_plex
                      template:
                        - conditional_media
                        - icon_google_tv

              - type: grid
                columns: 2
                cards:

                  - type: custom:button-card
                    entity: media_player.shield_tv_plex
                    triggers_update: sensor.youtube_watching
                    name: Shield TV
                    template:
                      - media
                      - icon_shield_tv

                  - type: custom:button-card
                    entity: media_player.master_bedroom_tv_plex
                    triggers_update: sensor.youtube_watching
                    name: Master Bedroom TV
                    template:
                      - media
                      - icon_google_tv

                  - type: custom:button-card
                    entity: sensor.ps5_activity
                    name: PS5 Activity
                    template:
                      - media
                      - icon_playstation

                  - type: custom:button-card
                    entity: media_player.garage_tv_plex
                    name: Garage TV
                    template:
                      - media
                      - icon_google_tv

              - type: grid
                columns: 2
                cards:

                  - type: custom:button-card
                    entity: media_player.upstairs_tv_plex
                    triggers_update: sensor.youtube_watching
                    name: Upstairs TV
                    template:
                      - media
                      - icon_google_tv

and I made a PlayStation icon to match the other media player icons.
button_card_templates/icons.yaml

icon_playstation:
  custom_fields:
    icon: >
      <svg viewBox="0 0 50 50">
        <path d="M49.5,11.8l-0.2-2.4c-0.5-2.7-2.1-4.9-4.2-6.6c-1.9-1.6-4.1-2.4-6.7-2.4L27.5,0.3L11,0.4c-0.5,0-0.9,0-1.4,0.1 C7.8,0.8,6.2,1.6,4.8,2.7C1.9,5,0.5,7.9,0.4,11.5v26.7c0.1,1.1,0.1,2,0.3,3C1.4,43.8,3,45.8,5,47.4c1.9,1.4,4.1,2.2,6.5,2.2 l13.7,0.1c0,0,13.3-0.1,13.4-0.2c0.7,0,1.3-0.1,1.9-0.2c2.8-0.6,5.1-2.2,6.8-4.4c1.3-1.7,2.1-3.7,2.2-5.9l0.1-6.7L49.5,11.8z M19.2,29.1l-6.2,2.2c-1.1,0.4-1.3,0.9-0.4,1.2c0.9,0.3,2.5,0.2,3.6-0.2l3-1.1v3.1c-0.2,0-0.4,0.1-0.6,0.1c-3,0.5-6.1,0.3-9.2-0.7 c-2.9-0.8-3.4-2.5-2.1-3.5c1.2-0.9,3.3-1.6,3.3-1.6l8.5-3V29.1z M26.3,15.9V38l-6-1.9V9.7c2.5,0.5,6.2,1.6,8.2,2.3 c5,1.7,6.8,3.9,6.8,8.8c0,4.7-2.9,6.5-6.6,4.7v-8.8c0-1-0.2-2-1.2-2.3C26.8,14.1,26.3,14.8,26.3,15.9z M43,31.3 c-0.7,0.9-2.5,1.5-2.5,1.5l-13,4.7v-3.5l9.6-3.4c1.1-0.4,1.3-0.9,0.4-1.2c-0.9-0.3-2.5-0.2-3.6,0.2l-6.4,2.3v-3.6l0.4-0.1 c0,0,1.8-0.7,4.4-0.9c2.6-0.3,5.8,0,8.3,1C43.4,29.1,43.7,30.4,43,31.3z"/>
      </svg>

It should look something like this
image

EDIT: edited base media variables to include ‘none’ in media_off

    media_off: >
      [[[ return !entity || ['off', 'idle', 'standby', 'unknown', 'unavailable', 'none'].indexOf(entity.state) !== -1; ]]]

EDIT2: line 95 media.yaml

            let game_image = entity.attributes.title_image;
7 Likes

okay i get it to work,

but when i use my mobile or tablet it the progress moves a little bit to the right and top. But i use % as margin values.

here on my phone

Unbenannt1

i updatet the grid

styles:
                        grid:
                          - grid-template-areas: |
                              "icon  circle"
                              "progress  progress"
                              "n     n"
                              "s     s"
                          - grid-template-columns: repeat(2, 1fr)
                          - grid-template-rows: auto repeat(3, min-content)
                          - gap: 1.3%
                          - align-items: start

and added the #progress to the extra_styles

extra_styles: >
      [[[
        if (entity) {
          let hs = entity.attributes.hs_color === undefined,
            h = hs || entity.attributes.hs_color[0],
            s = hs || entity.attributes.hs_color[1],
            l_min = 28,
            l_max = 48,
            l_calc = entity.attributes.brightness / 2.54 * (l_max - l_min) / 100 + l_min;
          var light_color = entity.attributes.color_mode === 'color_temp' || entity.attributes.color_mode === 'brightness'
            ? `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);'
            }
          }
          #container {
            text-align: left !important;
          }
          #name, #state {
            font-size: 1.32vw;
            letter-spacing: -0.02vw;
          }
          #state::first-letter {
            text-transform: uppercase;
          }
          /* portrait */
          @media screen and (max-width: 1200px) {
            #name, #state {
              font-size: 2vw;
            }
          }
          /* phone */
          @media screen and (max-width: 800px) {
            #name, #state {
              font-size: 3vw;
            }
          }

          /* tilt */
          #ripple, .js-tilt-glare {
            clip-path: inset(0 round var(--custom-button-card-border-radius));
            overflow: hidden;
          }
          .js-tilt-glare {
            z-index: 1;
          }
          .js-tilt-glare-inner {
            background-color: rgba(0,0,0,0.9);
          }
          #container {
            transform: translateZ(${variables.tilt_options.parallax});
          }
          #card {
            transform-style: preserve-3d;
            overflow: visible;
          }

          ${this._config.template.includes('conditional_media') ? `
            :host {
              --blur-intensity: blur(4.5px) brightness(0.8);
            }
            /* phone */
            @media screen and (max-width: 800px) {
              :host {
                --blur-intensity: blur(2.5px) brightness(0.8);
              }
            }
            #ripple, .js-tilt-glare {
              clip-path: inset(0 round calc(var(--custom-button-card-border-radius) / 2));
            }
            #container {
              overflow: hidden;
            }
            .marquee {
              animation: marquee 20s linear infinite;
            }
            @keyframes marquee {
              from {
                transform: translateX(0%);
              }
              to {
                transform: translateX(-50%);
              }
            }
          `:''}

          ${this._config.template.includes('footer') ? `
            :host {
              --name-font-size: 1.22vw;
              --name-icon-size: 1.5vw;
              --notify-font-size: 0.9vw;
              --notify-box-size: 1.8vw;
              --name-padding-v: 0.7vw;
              --name-padding-h: 1.1vw;
              --progress-padding-v: 0.7vw;
              --progress-padding-h: 1.1vw;
              --card-border-radius: 0.6vw;
            }
            #ripple, .js-tilt-glare {
              border-radius: calc(var(--card-border-radius) - 0.1vw);
              clip-path: inset(0 round calc( var(--custom-button-card-border-radius) - 0.1vw ));
            }
            #progress {
              padding: var(--progress-padding-v) var(--progress-padding-h);
            }
            #name {
              font-size: var(--name-font-size);
              padding: var(--name-padding-v) var(--name-padding-h);
              letter-spacing: 0.012vw;
            }
            ha-icon {
              width: var(--name-icon-size);
              vertical-align: 7%;
              padding-right: 0.1vw;
              opacity: 0.4;
            }
            #card {
              border-radius: var(--card-border-radius);
              background: rgba(115, 115, 115, 0.04);
            }
            #notify {
              font-size: var(--notify-font-size);
              width: var(--notify-box-size);
              height: var(--notify-box-size);
              line-height: var(--notify-box-size);
              padding-right: 0.5px;
              padding-top: 0.5px;
            }
            /* portrait */
            @media screen and (max-width: 1200px) {
              #name {
                font-size: calc(var(--name-font-size) * 1.4);
                padding: calc(var(--name-padding-v) * 1.4) calc(var(--name-padding-h) * 1.4);
              }
              #progress {
                padding: calc(var(--progress-padding-v) * 1.4) calc(var(--progress-padding-h) * 1.4);
              }
              ha-icon {
                width: calc(var(--name-icon-size) * 1.4);
              }
              #card {
                border-radius: calc(var(--card-border-radius) * 1.4);
                margin: 0 0.5vw;
              }
              #notify {
                font-size: calc(var(--notify-font-size) * 1.4);
                width: calc(var(--notify-box-size) * 1.4);
                height: calc(var(--notify-box-size) * 1.4);
                line-height: calc(var(--notify-box-size) * 1.4);
              }
            }
            /* phone */
            @media screen and (max-width: 800px) {
              #name {
                font-size: calc(var(--name-font-size) * 2.7);
                padding: calc(var(--name-padding-v) * 2.7) calc(var(--name-padding-h) * 2.7);
                letter-spacing: 0.12vw;
              }
              #progress {
                margin: calc(var(--progress-padding-v) * 2.7) calc(var(--progress-padding-h) * 2.7);
              }
              ha-icon {
                width: calc(var(--name-icon-size) * 2.7);
              }
              #card {
                border-radius: calc(var(--card-border-radius) * 2.7);
                background: rgba(115, 115, 115, 0.08);
                margin: 0 0.5vw;
              }
              #notify {
                font-size: calc(var(--notify-font-size) * 2.7);
                width: calc(var(--notify-box-size) * 2.7);
                height: calc(var(--notify-box-size) * 2.7);
                line-height: calc(var(--notify-box-size) * 2.7);
                padding: 0;
              }
            }
          `:''}
        `
      ]]]

but still no change, any ideas perhaps`?

I updated browser-mod today now double tap isn’t working. Is that a known issue - I didn’t see anything in the docs?

Edit: required a cache clear to fix.

Thanks for sharing your code! I copied your code over to mine exactly, but now I am now seeing the below javascript error on all media button cards:

ButtonCardJSTemplateError: ReferenceError: game_image is not defined in ‘game_image = entity.attributes.title_image;
if (variables.is_youtube) {
return `linear-gra…’

I must be missing something. Also verified that the PS5 integration is active:

1 Like

My bad. media.yaml line 95 add let in front of game_image = entity.attributes.title_image;

...
      - background-image: >
          [[[
            let game_image = entity.attributes.title_image;
            if (variables.is_youtube) {
                return `linear-gradient(0deg, rgba(0,0,0,.8) 0%, rgba(0,0,0,0) 100%), url(${states[this._config?.triggers_update].state})`;
            }
...
2 Likes

how did you create this sensor?

hi, is it possible to have another dashboard beside this one? Because the tablet theme breaks the other dashboard… thanks

Yes try this.

Maybe this question is already asked, but couldn’t find the solution in this thread.

The person cards are working, howeve within the circle the display of the time home are not updating, only on refresh of the whole browser the information is updated.

I would expect that these times are updating automatically, but maybe my expectation is wrong.

- platform: template
    sensors:
      appletv_kueche_progress:
        friendly_name: "Apple TV Kueche Player Prozent"
        value_template: >
              {{ 100 / state_attr('media_player.kueche','media_duration') * (state_attr('media_player.kueche', 'media_position')) }}  

Thanks! That fixed the error. For some reason my conditional card is no longer changing though, and just stuck at “Recently Added.” Probably something off in my own code, but I’ll keep working through it.

Thanks again!

1 Like

Check out the select.conditional_media entity and see if that is reporting correctly. The options should match the media player friendly names that are listed as conditions in the ui-lovelace.yaml media section.

If it doesn’t, your problem is in packages/tv_media.yaml

1 Like

You rock! That was exactly what I needed, and found that my PS5 sensor was named incorrectly in tv_media.yaml. Quick fix. Thanks for pointing me in the right direction!

2 Likes

I cannot figure out how to change colors of svg icons. As it is right now the icons i have copied from this thread, where pictures show different colors from what i get… I can see that colors are often set via variables, but where should i find these values? Is it in themes.yaml, because i cannot find them there.

My icons:
image

Original according to this forum:
image

and icon.yaml includes this code

icon_pendant:
    styles:
      custom_fields:
        icon:
          - width: 100%
          - margin-left: -9%
          - margin-top: -9%
    custom_fields:
      icon: >
        [[[
          let state = variables.state_on && variables.timeout < 2000 ? 'on' : null;
          return `
            <svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
              <defs><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="178.015" id="Filter" width="15.7685" x="244.46" y="22.1442"><feDropShadow dx="0" dy="0" flood-color="#000" flood-opacity=".797297" in="SourceGraphic" result="Shadow" stdDeviation=".680957"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="74.3896" id="Filter_2" width="49.2588" x="228.474" y="164.53"><feDropShadow dx="0" dy="0" flood-color="#000" flood-opacity=".333" in="SourceGraphic" result="Shadow" stdDeviation=".775166"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="185.846" id="Filter_3" width="342.386" x="79.1407" y="201.683"><feDropShadow dx="0" dy="0" flood-color="#000" flood-opacity=".333" in="SourceGraphic" result="Shadow" stdDeviation=".387597"/></filter></defs><g  id="Layer-1" vectornator:layerName="Layer 1">
              <path class="${state}" d="M252.33 30.0149 252.357 192.288" fill="blue" fill-rule="evenodd" filter="url(#Filter)" stroke="#a0a0a0" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="13.0176" vectornator:shadowAngle="-.656674" vectornator:shadowColor="#000000" vectornator:shadowOffset="0" vectornator:shadowOpacity=".797297" vectornator:shadowRadius="1.36191"/>
              <path class="${state}" d="M238.28 166.081H267.926C272.486 166.081 276.182 169.886 276.182 174.581V228.869C276.182 233.564 272.486 237.369 267.926 237.369H238.28C233.72 237.369 230.024 233.564 230.024 228.869V174.581C230.024 169.886 233.72 166.081 238.28 166.081z" fill="var(--light-outside)" fill-rule="evenodd" filter="url(#Filter_2)" stroke="none" vectornator:shadowAngle="1.5708" vectornator:shadowColor="#000000" vectornator:shadowOffset="0" vectornator:shadowOpacity=".333" vectornator:shadowRadius="1.55033"/>
              <path class="${state}" d="M79.9394 336.998C78.8314 299.922 117.197 257.306 137.523 241.656 168.633 217.703 202.906 202.458 249.98 202.458 297.053 202.458 338.512 219.467 369.361 243.775 400.209 268.084 420.752 302.038 420.752 336.83 420.752 382.245 405.423 385.678 366.584 386.494 341.306 387.025 298.558 386.577 251.484 386.577 204.411 386.577 171.104 386.31 135.623 385.764 96.7806 385.167 81.331 383.565 79.9394 336.998z" fill="var(--light-outside)" fill-rule="evenodd" filter="url(#Filter_3)" stroke="none" vectornator:shadowAngle="1.5708" vectornator:shadowColor="#000000" vectornator:shadowOffset="0" vectornator:shadowOpacity=".333" vectornator:shadowRadius=".775194"/>
              <path class="${state}" fill="var(--light-color)" d="M210.899 409.227C212.783 397.014 216.042 397.813 226.03 397.757 235.634 397.704 245.046 397.781 256.452 397.685 267.382 397.594 270.76 397.868 281.548 398.215 290.703 398.51 295.585 397.897 297.041 408.195 298.497 418.493 295.761 440.415 282.097 449.059 268.434 457.704 234.111 456.602 222.094 445.669 210.076 434.737 209.367 419.164 210.899 409.227z" fill="#ffdc00" fill-rule="evenodd" opacity="1" stroke="none"/>
              </g>
              
              <style>
                @keyframes on {
                  0% {
                    color: #26abff
                    background-color: '#26abff';
                  }
                  23% {
                    transform: rotateZ(-10deg);
                    animation-timing-function: ease-in-out;
                  }
                 
                  56% {
                    transform: rotateZ(10deg);
                    animation-timing-function: ease-in-out;
                  }
                  70% {
                    transform: rotateZ(-2deg);
                    animation-timing-function: ease-in-out;
                  }
                  85% {
                    transform: rotateZ(2deg);
                    animation-timing-function: ease-in-out;
                  }
                  100% {
                    transform: rotateZ(0deg);
                  }
                }
                .on {
                  animation: on 1.7s;
                  transform-origin: top;
                  background-color: '#26abff';
                  animation-fill-mode: forwards;
                  animation-delay: -0.1s;
                }
                
              </style>
            </svg>
            
          `; 
        ]]]

And ui-lovelace.yaml

          - type: custom:button-card
            entity: light.yeelight_ceiling10_0x7654218
            name: Belysning
            template:
              - loader
              - base
              - icon_pendant
1 Like

I dont know where light-outside is set, it could be custom from @Quinnod34 or something that was removed by @Mattias_Persson between now and when that code was written. in short I just fixed it by setting the fill to the same value that I have set as the fill on other icons.

before fixing mine looked like yours after the fix it looks like so (this is an RGB light and set to orange)
Screen Shot 2023-01-11 at 9.30.12 pm

  icon_pendant:
    styles:
      custom_fields:
        icon:
          - width: 100%
          - margin-left: -9%
          - margin-top: -9%
    custom_fields:
      icon: >
        [[[
          let state = variables.state_on && variables.timeout < 2000 ? 'on' : null;
          return `
            <svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
              <defs><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="178.015" id="Filter" width="15.7685" x="244.46" y="22.1442"><feDropShadow dx="0" dy="0" flood-color="#000" flood-opacity=".797297" in="SourceGraphic" result="Shadow" stdDeviation=".680957"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="74.3896" id="Filter_2" width="49.2588" x="228.474" y="164.53"><feDropShadow dx="0" dy="0" flood-color="#000" flood-opacity=".333" in="SourceGraphic" result="Shadow" stdDeviation=".775166"/></filter><filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="185.846" id="Filter_3" width="342.386" x="79.1407" y="201.683"><feDropShadow dx="0" dy="0" flood-color="#000" flood-opacity=".333" in="SourceGraphic" result="Shadow" stdDeviation=".387597"/></filter></defs><g  id="Layer-1" vectornator:layerName="Layer 1">
              <path class="${state}" d="M252.33 30.0149 252.357 192.288" fill="blue" fill-rule="evenodd" filter="url(#Filter)" stroke="#a0a0a0" stroke-linecap="butt" stroke-linejoin="miter" stroke-width="13.0176" vectornator:shadowAngle="-.656674" vectornator:shadowColor="#000000" vectornator:shadowOffset="0" vectornator:shadowOpacity=".797297" vectornator:shadowRadius="1.36191"/>
              <path class="${state}" d="M238.28 166.081H267.926C272.486 166.081 276.182 169.886 276.182 174.581V228.869C276.182 233.564 272.486 237.369 267.926 237.369H238.28C233.72 237.369 230.024 233.564 230.024 228.869V174.581C230.024 169.886 233.72 166.081 238.28 166.081z" fill="#9da0a2" fill-rule="evenodd" filter="url(#Filter_2)" stroke="none" vectornator:shadowAngle="1.5708" vectornator:shadowColor="#000000" vectornator:shadowOffset="0" vectornator:shadowOpacity=".333" vectornator:shadowRadius="1.55033"/>
              <path class="${state}" d="M79.9394 336.998C78.8314 299.922 117.197 257.306 137.523 241.656 168.633 217.703 202.906 202.458 249.98 202.458 297.053 202.458 338.512 219.467 369.361 243.775 400.209 268.084 420.752 302.038 420.752 336.83 420.752 382.245 405.423 385.678 366.584 386.494 341.306 387.025 298.558 386.577 251.484 386.577 204.411 386.577 171.104 386.31 135.623 385.764 96.7806 385.167 81.331 383.565 79.9394 336.998z" fill="#9da0a2" fill-rule="evenodd" filter="url(#Filter_3)" stroke="none" vectornator:shadowAngle="1.5708" vectornator:shadowColor="#000000" vectornator:shadowOffset="0" vectornator:shadowOpacity=".333" vectornator:shadowRadius=".775194"/>
              <path class="${state}" fill="var(--light-color)" d="M210.899 409.227C212.783 397.014 216.042 397.813 226.03 397.757 235.634 397.704 245.046 397.781 256.452 397.685 267.382 397.594 270.76 397.868 281.548 398.215 290.703 398.51 295.585 397.897 297.041 408.195 298.497 418.493 295.761 440.415 282.097 449.059 268.434 457.704 234.111 456.602 222.094 445.669 210.076 434.737 209.367 419.164 210.899 409.227z" fill="#ffdc00" fill-rule="evenodd" opacity="1" stroke="none"/>
              </g>
              
              <style>
                @keyframes on {
                  0% {
                    color: #26abff
                    background-color: '#26abff';
                  }
                  23% {
                    transform: rotateZ(-10deg);
                    animation-timing-function: ease-in-out;
                  }
                  56% {
                    transform: rotateZ(10deg);
                    animation-timing-function: ease-in-out;
                  }
                  70% {
                    transform: rotateZ(-2deg);
                    animation-timing-function: ease-in-out;
                  }
                  85% {
                    transform: rotateZ(2deg);
                    animation-timing-function: ease-in-out;
                  }
                  100% {
                    transform: rotateZ(0deg);
                  }
                }
                .on {
                  animation: on 1.7s;
                  transform-origin: top;
                  background-color: '#26abff';
                  animation-fill-mode: forwards;
                  animation-delay: -0.1s;
                }
                
              </style>
            </svg>
            
          `; 
        ]]]

the variables for light-color is set in button_card_templates/extra_styles.yaml

gold star on the question lots of details and all the info that I needed to help

4 Likes