A different take on designing a Lovelace UI

Hello There
I have a problem with the footer and I have no idea what it can be. The size of the buttons does not adjust automatically. If I change the with from “fit-content” to 100px in footer.yaml, the buttons scale.

#button_card_templates: !include button_card_templates.yaml
button_card_templates:
  !include_dir_merge_named button_card_templates

views:
  - type: custom:grid-layout
    path: 0
    layout:
      #default
      margin: 0
      grid-gap: var(--custom-layout-card-padding)
      grid-template-columns: repeat(4, 1fr) 0
      grid-template-rows: 0 repeat(2, fit-content(100%)) 0fr
      grid-template-areas: |
        "sidebar  .           .       .             ."
        "sidebar  wohnzimmer  flur    schlafzimmer  ."
        "sidebar  media       sonos   home          ."
        "sidebar  footer      footer  footer        ."
      mediaquery:
        #phone
        "(max-width: 800px)":
          grid-gap: calc(var(--custom-layout-card-padding) * 1.7)
          grid-template-columns: 0 repeat(2, 1fr) 0
          grid-template-rows: 0 repeat(5, fit-content(100%)) 0fr
          grid-template-areas: |
            ".  .           .             ."
            ".  sidebar     sidebar       ."
            ".  wohnzimmer  schlafzimmer  ."
            ".  flur        home          ."
            ".  media       sonos         ."
            ".  footer      footer        ."
            ".  .           .             ."
        #portrait
        "(max-width: 1200px)":
          grid-gap: var(--custom-layout-card-padding)
          grid-template-columns: repeat(3, 1fr) 0
          grid-template-rows: 0 repeat(3, fit-content(100%)) 0fr
          grid-template-areas: |
            "sidebar  .           .             ."
            "sidebar  wohnzimmer  schlafzimmer  ."
            "sidebar  flur        home          ."
            "sidebar  media       sonos         ."
            "sidebar  footer      footer        ."
    cards:

      - type: custom:button-card #extra_styles fix
        styles: {card: [display: none]}

      #################################################
      #                                               #
      #                    SIDEBAR                    #
      #                                               #
      #################################################

      - type: vertical-stack
        view_layout:
          grid-area: sidebar
        cards:
          - type: custom:button-card
            entity: sensor.template_sidebar
            template: sidebar

      #################################################
      #                                               #
      #                  Wohnzimmer                   #
      #                                               #
      #################################################

      - type: grid
        title: Wohnzimmer
        view_layout:
          grid-area: wohnzimmer
        columns: 2
        cards:

          - type: custom:button-card
            entity: light.new_york
            name: New York
            template:
              - light
              - icon_hue

          - type: custom:button-card
            entity: light.schnapstrue
            name: Schnapstruhe
            template:
              - light
              - icon_hue

          - type: custom:button-card
            entity: sensor.weather_station_temperature
            name: Temperatur
            tap_action:
              action: more-info
            custom_fields:
              graph:
                card:
                  entities: 
                    - sensor.weather_station_temperature
            template:
              - temperature
              - icon_temp
            variables:
              popup_name: Temperatur


          - type: custom:button-card
            entity: light.salzstein
            name: Salzstein
            template:
              - light
              - icon_hue

      #################################################
      #                                               #
      #                    Schlafzimmer               #
      #                                               #
      #################################################

      - type: grid
        title: Schlafzimmmer
        view_layout:
          grid-area: schlafzimmer
        columns: 2
        cards:

          - type: custom:button-card
            entity: light.schlafzimmer
            name: Ständerlampe
            template:
              - light
              - icon_lamp

          - type: custom:button-card
            entity: fan.luftibert 
            name: "Lüftibert"
            hold_action:
              !include popup/schlafzimmer_fan.yaml
            tap_action:
              action: more-info
            template:
              - base
              - icon_fan



          - type: custom:button-card
            entity: media_player.hauptschlafzimmer
            name: Sonos
            hold_action:
              !include popup/sonos.yaml
            template:
              - base
              - icon_sonos
              - loader

          - type: custom:button-card
            entity: sensor.luftibert_temperature
            name: Temperatur
            tap_action:
              action: more-info
            custom_fields:
              graph:
                card:
                  entities: 
                    - sensor.luftibert_temperature
            template:
              - temperature
              - icon_temp
            variables:
              popup_name: Temperatur



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

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

          - type: custom:swipe-card
            start_card: 1
            parameters:
              roundLengths: true
              effect: coverflow
              speed: 650
              spaceBetween: 20
              threshold: 7
              coverflowEffect:
                rotate: 80
                depth: 300
            cards:

              - type: custom:spotify-card
                account: default
                spotify_entity: media_player.spotify_jan_stager
                playlist_type: discover-weekly
                grid_covers_per_row: '2'
                limit: 4
                country_code: DE
                default_device: Küche
                display_style: grid
                known_connect_devices:
                  - id: d4757ab523224358f9c9052ee4de85ba324c41fa
                    name: Küche
                    entity_id: media_player.kuche

              - type: custom:mini-media-player
                entity: media_player.kuche
                hide:
                  power: true
                  volume: true
                  controls: true
                  source: true
                speaker_group:
                  platform: sonos
                  show_group_count: true
                  entities:
                    - entity_id: media_player.kuche
                      name: Sonos Küche
                    - entity_id: media_player.badezimmer
                      name: Sonos Badezimmer
                    - entity_id: media_player.buro
                      name: Sonos Büro
                    - entity_id: media_player.hauptschlafzimmer
                      name: Sonos Schlafzimmer
                    - entity_id: media_player.balkon
                      name: Sonos Balkon
                entities:
                  - type: custom:mini-media-player
                    entity: media_player.multiroom_player
                    group: true
                    source: icon
                    artwork: cover
                    info: scroll
                    hide:
                      volume: true
                      power_state: true
                  - type: custom:mini-media-player
                    entity: media_player.kuche
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.badezimmer
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.buro
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.hauptschlafzimmer
                    group: true
                    hide:
                      controls: true
                  - type: custom:mini-media-player
                    entity: media_player.balkon
                    group: true
                    hide:
                      controls: true
                

      #################################################
      #                                               #
      #                    Sonos                      #
      #                                               #
      #################################################
      - type: grid
        title: Sonos
        view_layout:
          grid-area: sonos
        columns: 1
        cards:

          - type: entities
            entities:
              - type: custom:mini-media-player
                entity: media_player.kuche
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.buro
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.badezimmer
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.hauptschlafzimmer
                name: Schlafzimmer
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true
              - type: custom:mini-media-player
                entity: media_player.balkon
                name: Balkon
                group: true
                hide:
                  controls: true
                  power: true
                  icon: true
                  info: true
                  source: true
                  progress: true

      #################################################
      #                                               #
      #                    Flur                       #
      #                                               #
      #################################################

      - type: grid
        title: Flur
        view_layout:
          grid-area: flur
        columns: 2
        cards:


          - type: custom:button-card
            entity: light.group_hall
            name: Hall
            template:
              - light
              - icon_spot

      #################################################
      #                                               #
      #                     Home                      #
      #                                               #
      #################################################

      - type: grid
        title: Home
        view_layout:
          grid-area: home
        columns: 2
        cards:

          - type: custom:button-card
            entity: script.home_leave
            name: Good Bye
            hold_action:
              action: none
            template:
              - base
              - icon_away

          - type: custom:button-card
            entity: script.home_arrive
            name: Welcome
            hold_action:
              action: none
            template:
              - base
              - icon_home

          - type: custom:button-card
            entity: script.good_night
            name: Good Night
            hold_action:
              action: none
            template:
              - base
              - icon_good_night

          - type: custom:button-card
            entity: script.music
            name: Music
            hold_action:
              action: none
            template:
              - base
              - icon_music


      #################################################
      #                                               #
      #                    FOOTER                     #
      #                                               #
      #################################################
      
      - type: horizontal-stack
        view_layout:
          grid-area: footer
        cards:

          - type: custom:button-card
            name: >
              <ha-icon icon="mdi:nas"></ha-icon> NAS
            tap_action:
              !include popup/footer_nas.yaml
            triggers_update:
              - binary_sensor.jan_home_update_available
              - sensor.jan_home_status
              - binary_sensor.jan_home_security_status
              - sensor.disk_use_percent
            variables:
              notify: >
                [[[
                  let id = this._config.triggers_update;
                  if (id.every(e => states[e]))
                      return states[id[0]].state === 'on'
                          ? 1
                          : states[id[1]].state === 'background_scrubbing' ||
                            states[id[2]].state === 'on' ||
                            parseFloat(states[id[3]].state) >= 85;
                ]]]
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="mdi:arrow-up-bold-circle-outline"></ha-icon> Updates
            tap_action:
              !include popup/footer_updates.yaml
            triggers_update:
              - sensor.hacs
              - sensor.docker_hub_beta
              - sensor.docker_hub
            variables:
              notify: >
                [[[
                  let id = this._config.triggers_update;
                  if (id.every(e => states[e])) {
                      let hacs = parseInt(states[id[0]].state),
                          installed = hass.config.version,
                          latest = installed.includes('b')
                              ? states[id[1]].state
                              : states[id[2]].state;

                      if (latest.includes('.') && Number.isInteger(hacs))
                          return hacs + (installed !== latest ? 1 : 0);
                  }
                  return 0;
                ]]]
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="custom:roborock-vacuum"></ha-icon> Buddy
            tap_action:
              !include popup/footer_vacuum.yaml
            triggers_update:
              - sensor.date
            variables:
              notify: >
                [[[
                  let id = states['sensor.morty_last_clean_end'];
                  if (id) return (Date.now() - Date.parse(id.state)) > 6048e5;
                ]]]
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="mdi:chart-line-variant"></ha-icon> Statistik
            tap_action:
              !include popup/footer_history.yaml
            template: footer

          - type: custom:button-card
            name: >
              <ha-icon icon="custom:cupra"></ha-icon> Cupra
            tap_action:
              !include popup/footer_cupra.yaml
            template: footer     

I am grateful for every hint

Hi @Mattias_Persson , first thank you for your setup and help. I did everything as listed in Github Installation Instructions. First I got error:
secret Youtube_token not defined
but I fixed it by commenting it in media.yaml.
But now I get the error:
Secret apexcharts_tibber not defined
I dont know how to fix and I already searched this post but didnt find any solution. I already installed the apexcharts repo via hacs.
Can you please give me a solution?
Thank you!

That’s outdated instructions, there’s no secrets anymore. You’ll have to copy the files from my repo again https://github.com/matt8707/hass-config/blob/00de2dd3ce0f3145e20ae0de5adda518b37b0194/INSTALL.md

Try this #00de2dd

Okay thank you so much I will try it!

Hi so I´m sure this was asked a lot, but can somebody please tell me which files I need to look at for changing text, language, adding my own entities?
Thanks

Thank you :slight_smile:

but where can I do like the living room etc? Because in Lovelace ui it messes up everything when I change?

Mattias,
Or really anyone with the knowledge.
I have the Unifi UDM-Pro but I’m really struggling trying to get the footer to populate. Everything pops-up as should but shows “unknown” for values.
I’ve made the appropriate changes in !secrets and looked over "router_unifi.yaml to see where i may need some changes.
This instance of Unifi controller is not hosted anywhere other than on the UDM-pro.
I’ve tried doing the ssh into UDM without success.
Does something need to be enabled that I’m missing?
I do have the Unifi addon working, and have tried the same user and pass as that and still no go.

Hey buddy great work, would you mind sharing your Plex popup. Is this collected off of another computer or server (docker)?

I’m attempting to make an auto-populating card for switch groups, based of the code for the new light popup… however I am was scratching my head as to what format is needed for:

tap_action:
  action: toggle

I eventually figured it out.
Here is the button card template:

switch:
  template:
    - base
    #- circle
    - loader
  double_tap_action:
    action: fire-dom-event
    browser_mod:
      command: popup
      title: >
        [[[
          return !entity || entity.attributes.friendly_name;
        ]]]
      style:
        hui-entities-card:
          $: |
            #states {
              padding-top: 0.8em;
            }
      card:
        type: entities
        entities: >
          [[[
            if (entity) {
                let switches = [],
                    id = Boolean(entity.attributes.entity_id)
                        ? [entity.entity_id].concat(entity.attributes.entity_id)
                        : [entity.entity_id];

                for (let i = 0; i < id.length; i++) {
                    switches.push({
                        "type": "custom:mushroom-entity-card",
                        "entity": id[i],
                        "fill_container": false,
                        "primary_info": "name",
                        "secondary_info": "last-changed",
                        "icon_type": "icon",
                        "icon_color": "light-green",
                        "tap_action": { action: 'toggle' }
                    });
                }
                return switches;
            }
          ]]]

I’m still yet two wrap my head around how to set up the circle info to display “x/y” (where x is number of switches in the on state and y is the total of switches), then all that’s left is to fill the circle line out as a percentage of that.

I got it working, it was a combination of issues,

I had port 433 not 443 in my secretes but when I tested the code I used 443
and my HA user role didn’t have access to UniFiOS.

Thanks for the help, would not have been as much of an issue if the errors was more understandable but that’s a HA issue.

Love your config for the second screen. Could you share the Yaml?

hi, I have circle info to display “x/y” (where x is number of people home and y is the total of people).

might be a good start for what you are trying to do

this is in 2 parts this will fill in the circle based on the % of people home

  variables:
    circle_input:  >
      [[[
        return entity === undefined || Math.round(states['zone.home'].state / 3 * 100 ) ;
      ]]]

and this puts the value in the circle,

I can see an issue when that 10/10 might be to big and you will need to play with the font size, or just display x not x/y when all are on but that will not work if you have a group with more than 10 switches.

 custom_fields:
    circle: >
      [[[
          let input = variables.circle_input,
            radius = 20.5,
            circumference = radius * 2 * Math.PI;
          let inner_text = states['zone.home'].state
          return `
            <svg viewBox="0 0 50 50">
              <style>
                circle {
                  transform: rotate(-90deg);
                  transform-origin: 50% 50%;
                  stroke-dasharray: ${circumference};
                  stroke-dashoffset: ${circumference - input / 100 * circumference};
                }
                tspan {
                  font-size: 10px;
                }
              </style>
              <circle cx="25" cy="25" r="${radius}" stroke="#b2b2b2" stroke-width="1.5" fill="none" />
              <text x="50%" y="54%" fill="#8d8e90" font-size="14" text-anchor="middle" alignment-baseline="middle" dominant-baseline="middle">${inner_text}/3</text>
            </svg>
          `;
      ]]]

you could also use this template to get the inner text for the circle input

{{ expand('group.office_monitors') | selectattr('state','eq','on')|map(attribute='name') | list | count }} / {{ expand('group.office_monitors') | count }}

Full Home Card

- type: custom:button-card
  entity: input_select.state_home
  name: Home
  variables:
    circle_input:  >
      [[[
        return entity === undefined || Math.round(states['zone.home'].state / 3 * 100 ) ;
      ]]]
  hold_action:
    action: more-info
  tap_action:
    action: call-service
    service: input_select.select_next
    service_data:
      entity_id: input_select.state_home
  double_tap_action:
    action: call-service
    service: input_select.select_previous
    service_data:
      entity_id: input_select.state_home
  custom_fields:
    circle: >
      [[[
          let input = variables.circle_input,
            radius = 20.5,
            circumference = radius * 2 * Math.PI;
          let inner_text = states['zone.home'].state
          return `
            <svg viewBox="0 0 50 50">
              <style>
                circle {
                  transform: rotate(-90deg);
                  transform-origin: 50% 50%;
                  stroke-dasharray: ${circumference};
                  stroke-dashoffset: ${circumference - input / 100 * circumference};
                }
                tspan {
                  font-size: 10px;
                }
              </style>
              <circle cx="25" cy="25" r="${radius}" stroke="#b2b2b2" stroke-width="1.5" fill="none" />
              <text x="50%" y="54%" fill="#8d8e90" font-size="14" text-anchor="middle" alignment-baseline="middle" dominant-baseline="middle">${inner_text}/3</text>
            </svg>
          `;
      ]]]
  template:
    - base
    - icon_home
    - circle

if this is for light switches it might be better to look into switch as x Switch as X - Home Assistant

1 Like

Great work!

Is it possible to add this dashboard next to my current dashboard? If i follow the install instruction i loose all my current lovelace dashboards. I want to make this primary and but want to keep the other ones.

Thank you, this saves me a ton of head scratching!

It’s by far not perfect and I didn’t do it myself!

lovelace-ui:

type: custom:button-card
entity: weather.pirateweather
name: Berlin
template:
  - base
  - widget_weather
variables:
  temp_min: sensor.pirateweather_overnight_low_temperature_0d
  temp_max: sensor.pirateweather_daytime_high_temperature_0d
  precip: sensor.template_sensor_pirateweather_precip_probability_round

Button-card templates:

  widgets:
    aspect_ratio: 1
    variables: null
    show_icon: false
    show_state: true
    show_name: true
    tap_action:
      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)
        ]]]
    styles:
      card:
        - background-color: rgba(0,0,0,0.4)
        - font-color: rgb(255,255,255,0.9)
        - text-shadow: 0px 0px 1px black
        - letter-spacing: 0.05vw
      name:
        - color: rgb(255,255,255,0.6)
    extra_styles: |
      #name, #state {
        font-size: 1.1vw;
        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: 5.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);
        }
      }

and

  widget_weather:
    variables:
      temp_min: ''
      temp_max: ''
      precip: ''
    aspect_ratio: 1/1
    show_icon: false
    show_entity_picture: true
    show_name: true
    show_state: true
    show_label: true
    tap_action:
      action: more-info
    styles:
      grid:
        - grid-template-areas: |
            "n"        
            "temp"
            "i"
            "s"
            "l"
        - grid-template-columns: 1fr
        - grid-template-rows: min-content repeat(2, 1fr) repeat(2, min-content)
        - gap: 0%
      card:
        - color: rgba(255, 255, 255, 0.8)
        - background: |
            [[[
              if (states['sun.sun'].state == 'below_horizon'){
                return 'linear-gradient(to top, rgba(53,59,83,1) 0%, rgba(10,14,34,1) 100%)';
              } else
                return 'linear-gradient(to top, rgba(123,168,197,1) 0%, rgba(61,132,176,1) 100%)';
            ]]]                        
      name:
        - place-self: start
        - text-transform: uppercase
        - font-weight: 500
      img_cell:
        - justify-content: start
      icon:
        - width: 20%
      label:
        - place-self: start
        - margin-left: '-5px'
      custom_fields:
        temp:
          - place-self: start
    custom_fields:
      temp: |
        [[[ return entity.attributes.temperature + "°"; ]]]    
    label: |
      [[[
          if (window.navigator.userAgent.match(/iPhone/i)) {
            return         `<ha-icon
            icon="mdi:arrow-up-thin"
            style="width: 15px; height: 15px; margin-right: -6px;">
            </ha-icon><span> ${states[variables.temp_max].state}°</span>
                  <ha-icon
            icon="mdi:arrow-down-thin"
            style="width: 15px; height: 15px; margin-right: -6px;">
            </ha-icon><span> ${states[variables.temp_min].state}° </span>       
          `;
                }
          else {
                    return `<ha-icon
            icon="mdi:arrow-up-thin"
            style="width: 15px; height: 15px; margin-right: -5px;">
            </ha-icon><span> ${states[variables.temp_max].state}°</span>
                  <ha-icon
            icon="mdi:arrow-down-thin"
            style="width: 15px; height: 15px; margin-right: -5px; margin-left: -5px;">
            </ha-icon><span> ${states[variables.temp_min].state}° </span>       
                  <ha-icon
            icon="mdi:weather-pouring"
            style="width: 14px; height: 14px; margin-right: -2px; margin-left: -1px;">
            </ha-icon><span> ${states[variables.precip].state}%</span>
          `}
      ]]]
    entity_picture: |
      [[[
        return entity && entity.state
          ? `/local/animated-weather-icons/${entity.state}.svg`
          : '?';
      ]]]
    extra_styles: |
      [[[
        return `
          #name {
            font-size: 1vw;
          }
          #temp {
            font-size: 1.9vw;
          }
          #state {
            font-size: 0.60vw;
          }  
          #label {
            font-size: 0.60vw;
          }
          /* portrait */
          @media screen and (max-width: 1200px) {
            #name {
              font-size: 1.3vw;
            }
            #temp {
              font-size: 4.5vw;
            }
            #state {
              font-size: 1.1vw;
            }  
            #label {
              font-size: 1.1vw;
            }
          }
          /* phone */
          @media screen and (max-width: 800px) {
            #name {
              font-size: 3vw;
            }              
            #temp {
              font-size: 2.5vw;
            }    
            #state {
              font-size: 1.8vw;
            }
            #label {
              font-size: 2.25vw;
            }
                   
          }
          @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);
            }
          }
        `
      ]]]
1 Like

Very long time since I’ve been here.
I have updated to the build from a week or so back.
A lot of work getting everything to work together again, but did a lot of nice fixes for my own environment.
However this is the first time I have enabled “tilt”
And I am noticing with the tilt enabled the cards seem a lot more fuzzy/blurry, especially noticeable on text

image image

With tilt enabled (left) and disabled (right)
I don’t see this fuzziness for anyone else’s setup, is this something anyone has encountered before?

In the “inspect” view of the browser the following line seems to cause the fuzziness

Transform: perspective(800px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)

Which is a part of:

<ha-card id="card" class="button-card-main type-custom-button-card" style="border-radius: var(--button-card-border-radius); --mdc-ripple-color: #97989c; color: rgb(151, 152, 156); background-color: rgba(115, 115, 115, 0.25); --c-stroke-color-on: #b0b0b0; --c-stroke-color-off: #313638; --c-fill-color-on: none; --c-fill-color-off: rgba(255,255,255,0.04); --c-stroke-width-on: 2.3; --c-stroke-width-off: 1.5; --c-stroke-width-dragging: 4; --c-font-color: #97989c; --c-font-size: 14px; --c-unit-font-size: 10.5px; --c-font-weight: 700; --c-letter-spacing: -0.02rem; position: absolute; transform: perspective(800px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1); will-change: transform;">

And a second question, I am positive I have seen the question and answer somewhere in the thread, but I cannot find it anywhere, even after searching and going to the thread.
But, when swiping on a swiper card, I am not able to change a dimmer light level by clicking and holding on the percentage circle
It works outside of the swiper card, and as I said the solution is out there but I cannot seem to find it, if anyone knows, please let me know

Yeah, but barely noticeable on my end, not like yours… Probably how your browser renders 3d transform?

Try some parameters https://swiperjs.com/swiper-api

type: custom:swipe-card
parameters:
  touchStartPreventDefault: false