⚪ Bubble Card - A minimalist card collection for Home Assistant with a nice pop-up touch

@hazio Thank you!

Hi, I now had the time to test the new version of Bubble-card. In the header of two pop-ups I do have sub-button-icons which change under certain conditions. this used to work without a problem. Now with the new version, these pop-ups do not work anymore (they don‘t pop up) as long as I leave the following code in the styling section:

${subButtonIcon[0].setAttribute("icon", hass.states['cover.sonnenrollo'].state === 'open' ? 'mdi:window-shutter-open' : 'mdi:window-shutter')}

When I remove the code everything works again…

Is this a bug for the header of the popups… or do I have to change something else in the code?

Thanks for helping!

Looks really nice! Great job!

Would you mind sharing your yaml?

Hi,

Will Need help for my Dashboard project.
I am using a floorplan Dashboard using picture elements and condicional for light efects in every division of the house.
In order to not have so many icons on the dash wanted to add an horizontal stack buttons with pop-up style.
The problem is when trying to add the buble pop up Card inside picture elements i cannot get the pop up to work.
Any idea How to add pop up style inside picture elements?

I have tried to using hui-elements, but the image stays blurred during the pop-up.

Hello, THANK YOU for this card collection!
I have been using it quite extensively to craft a mobile dashboard for me. I do have one issue I would like to ask (to see if someone spots any errors I made, or is there a minor bug somewhere).

I have a popup showing all my blind devices. I am using a combination of bubble and mushroom in order to get the behaviour I need. (my blinds are switchbot blind tilts so I need to use the tilt_position to control the blinds, I could not for the life of me get this working with bubble slider). The end result is otherwise perfect for what I need, but my template for sub-button background color is not working for some reason. If the blinds are closed, it works as expected (other button in different color) but when the blinds are open, the template no longer works and both buttons have the same background color. See picture attached.

EDIT: and to clarify, I tested the bubble-card button without layout card, still the same. And developer tools shows ‘open’ or ‘closed’ for the blinds state.

The YAML:

type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    hash: '#verhot'
    button_type: name
    name: Verhot
    icon: mdi:blinds-horizontal
    sub_button:
      - name: Avaa
        show_name: true
        icon: mdi:blinds-horizontal
        entity: script.open_all_blinds
        tap_action:
          action: call-service
          service: script.turn_on
          target:
            entity_id: script.open_all_blinds
      - name: Sulje
        show_name: true
        icon: mdi:blinds-horizontal-closed
        entity: script.close_all_blinds_script
        tap_action:
          action: call-service
          service: script.turn_on
          target:
            entity_id: script.close_all_blinds_script
    styles: |-
      .bubble-sub-button-1 {
        opacity: 1 !important;
        background-color: ${hass.states['cover.olohuoneen_verhot'].state === 'closed' ? 'var(--accent-color)' : 'none'} !important;
      }
      .bubble-sub-button-2 {
        opacity: 1 !important;
        background-color: ${hass.states['cover.olohuoneen_verhot'].state === 'open' ? 'var(--accent-color)' : 'none'} !important;
      }
  - type: custom:layout-card
    layout_type: custom:grid-layout
    layout:
      grid-template-columns: 2fr 1fr
      grid-template-rows: auto
      grid-template-areas: |
        "left right"
    cards:
      - type: custom:bubble-card
        card_type: button
        button_type: state
        entity: cover.blind_tilt_bedroom
        name: Makuuhuone
        double_tap_action:
          action: none
        hold_action:
          action: none
        show_state: true
        show_attribute: true
        attribute: current_tilt_position
        card_layout: large
        show_name: true
        show_icon: false
        sub_button:
          - entity: cover.blind_tilt_bedroom
            icon: mdi:blinds-horizontal
            name: Avaa
            show_name: true
            tap_action:
              action: call-service
              service: script.turn_on
              target:
                entity_id: script.open_bedroom_blinds
          - entity: cover.blind_tilt_bedroom
            name: Sulje
            icon: mdi:blinds-horizontal-closed
            show_state: false
            show_name: true
            tap_action:
              action: call-service
              service: script.turn_on
              target:
                entity_id: script.close_bedroom_blinds_script
        styles: |-
          .bubble-sub-button-1 {
            opacity: 1 !important;
            background-color: ${hass.states['cover.blind_tilt_bedroom'].state === 'closed' ? 'var(--accent-color)' : 'none'} !important;
          }
          .bubble-sub-button-2 {
            opacity: 1 !important;
            background-color: ${hass.states['cover.blind_tilt_bedroom'].state === 'open' ? 'var(--accent-color)' : 'none'} !important;
          }
      - type: custom:mushroom-cover-card
        entity: cover.blind_tilt_bedroom
        name: Makuuhuone
        icon: phu:blind-tilt-open
        show_tilt_position_control: true
        show_position_control: false
        show_buttons_control: false
        layout: horizontal
        icon_type: none
        primary_info: none
        secondary_info: none
        card_mod:
          style:
            mushroom-cover-tilt-position-control$:
              mushroom-slider$: |
                .slider {
                  --main-color: var(--accent-color) !important;
                  --bg-color: var(--accent-color-2) !important;
                  --gradient: none;
                }
            .: |
              mushroom-cover-tilt-position-control {
                --control-height: 48px !important;
                --control-border-radius: var(--ha-card-border-radius, 24px);
              }
              ha-card {
                border-radius: 34px!important;
                height: 64px!important;                
                padding: 8px !important;
              }
  - type: custom:layout-card
    layout_type: custom:grid-layout
    layout:
      grid-template-columns: 2fr 1fr
      grid-template-rows: auto
      grid-template-areas: |
        "left right"
    cards:
      - type: custom:bubble-card
        card_type: button
        button_type: state
        entity: cover.blind_tilt_kids_room
        name: Alvinin huone
        double_tap_action:
          action: none
        hold_action:
          action: none
        show_state: true
        show_attribute: true
        attribute: current_tilt_position
        card_layout: large
        show_name: true
        show_icon: false
        sub_button:
          - entity: cover.blind_tilt_kids_room
            icon: mdi:blinds-horizontal
            name: Avaa
            show_name: true
            tap_action:
              action: call-service
              service: script.turn_on
              target:
                entity_id: script.open_kidsroom_blinds
          - entity: cover.blind_tilt_kids_room
            name: Sulje
            icon: mdi:blinds-horizontal-closed
            show_state: false
            show_name: true
            tap_action:
              action: call-service
              service: script.turn_on
              target:
                entity_id: script.close_kidsroom_blinds_script
        styles: |-
          .bubble-sub-button-1 {
            opacity: 1 !important;
            background-color: ${hass.states['cover.blind_tilt_kids_room'].state === 'closed' ? 'var(--accent-color)' : 'none'} !important;
          }
          .bubble-sub-button-2 {
            opacity: 1 !important;
            background-color: ${hass.states['cover.blind_tilt_kids_room'].state === 'open' ? 'var(--accent-color)' : 'none'} !important;
          }
      - type: custom:mushroom-cover-card
        entity: cover.blind_tilt_kids_room
        name: Makuuhuone
        icon: phu:blind-tilt-open
        show_tilt_position_control: true
        show_position_control: false
        show_buttons_control: false
        layout: horizontal
        icon_type: none
        primary_info: none
        secondary_info: none
        card_mod:
          style:
            mushroom-cover-tilt-position-control$:
              mushroom-slider$: |
                .slider {
                  --main-color: var(--accent-color) !important;
                  --bg-color: var(--accent-color-2) !important;
                  --gradient: none;
                }
            .: |
              mushroom-cover-tilt-position-control {
                --control-height: 48px !important;
                --control-border-radius: var(--ha-card-border-radius, 24px);
              }
              ha-card {
                border-radius: 34px!important;
                height: 64px!important;                
                padding: 8px !important;
              }
  - type: custom:layout-card
    layout_type: custom:grid-layout
    layout:
      grid-template-columns: 2fr 1fr
      grid-template-rows: auto
      grid-template-areas: |
        "left right"
    cards:
      - type: custom:bubble-card
        card_type: button
        button_type: state
        entity: cover.olohuoneen_verhot
        name: Olohuone
        double_tap_action:
          action: none
        hold_action:
          action: none
        show_state: true
        show_attribute: true
        attribute: current_tilt_position
        card_layout: large
        show_name: true
        show_icon: false
        sub_button:
          - entity: cover.olohuoneen_verhot
            icon: mdi:blinds-horizontal
            name: Avaa
            show_name: true
            tap_action:
              action: call-service
              service: cover.set_cover_tilt_position
              target:
                entity_id: cover.olohuoneen_verhot
              data:
                tilt_position: 40
          - entity: cover.olohuoneen_verhot
            name: Sulje
            icon: mdi:blinds-horizontal-closed
            show_state: false
            show_name: true
            tap_action:
              action: call-service
              service: cover.set_cover_tilt_position
              target:
                entity_id: cover.olohuoneen_verhot
              data:
                tilt_position: 100
        styles: |-
          .bubble-sub-button-1 {
            opacity: 1 !important;
            background-color: ${hass.states['cover.olohuoneen_verhot'].state === 'closed' ? 'var(--accent-color)' : 'none'} !important;
          }
          .bubble-sub-button-2 {
            opacity: 1 !important;
            background-color: ${hass.states['cover.olohuoneen_verhot'].state === 'open' ? 'var(--accent-color)' : 'none'} !important;
          }
      - type: custom:mushroom-cover-card
        entity: cover.olohuoneen_verhot
        name: Olohuone
        icon: phu:blind-tilt-open
        show_tilt_position_control: true
        show_position_control: false
        show_buttons_control: false
        layout: horizontal
        icon_type: none
        primary_info: none
        secondary_info: none
        card_mod:
          style:
            mushroom-cover-tilt-position-control$:
              mushroom-slider$: |
                .slider {
                  --main-color: var(--accent-color) !important;
                  --bg-color: var(--accent-color-2) !important;
                  --gradient: none;
                }
            .: |
              mushroom-cover-tilt-position-control {
                --control-height: 48px !important;
                --control-border-radius: var(--ha-card-border-radius, 24px);
              }
              ha-card {
                border-radius: 34px!important;
                height: 64px!important;                
                padding: 8px !important;
              }

1 Like

Hello, i hope someone can help me. How can I make the border of a bubble card (Button/state) 1px large with a color. I have a standard theme, but the bubble card does not draw a blue border around it. See picture

Try adding this to the styling options - custom styles part:

.bubble-button-card-container {
  border: 1px solid;
  border-color: blue;
}

Your dashboard looks great. Especially your vacuum/room select button…could share your code?

I think that would be the Sankey Chart.

1 Like

This is the code for the mushroom button on the main page that opens up to the vacuum popup

type: custom:mushroom-template-card
primary: Blinds
secondary: ''
icon: mdi:blinds
icon_color: teal
layout: vertical
tap_action:
  action: navigate
  navigation_path: '#blinds'
hold_action:
  action: none
double_tap_action:
  action: none
fill_container: false
card_mod:
  style: |
    ha-card {
      background: var(--background-color-2);
      border-radius: 35px;
    }

This is a vertical stack, using the bubble popup. This opens when you press the vacuum button on the main page.

type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    hash: '#vacuum'
    show_header: true
    button_type: state
    entity: vacuum.alice
    show_last_changed: true
    tap_action:
      action: none
    double_tap_action:
      action: none
    hold_action:
      action: none
    button_action:
      tap_action:
        action: none
      double_tap_action:
        action: none
      hold_action:
        action: none
  - type: custom:bubble-card
    card_type: select
    entity: input_select.room_select
    show_state: true
    sub_button:
      - entity: input_button.go
        name: Go
        show_name: true
        tap_action:
          action: call-service
          service: script.turn_on
          target:
            entity_id: script.vacuum_room_select
  - type: custom:vacuum-card
    entity: vacuum.alice
    stats:
      default:
        - entity_id: sensor.alice_filter_lifespan
          unit: '%'
          subtitle: Filter
        - entity_id: sensor.alice_main_brush_lifespan
          unit: '%'
          subtitle: Main Brush
        - entity_id: sensor.alice_side_brushes_lifespan
          unit: '%'
          subtitle: Side Brush
      cleaning:
        - entity_id: sensor.alice_cleaning_duration
          unit: minutes
          subtitle: Cleaning Time
        - entity_id: sensor.alice_total_area_cleaned
          unit: m²
          subtitle: Area Cleaned

4 Likes

Yaml for the main layout card on the main page

type: custom:layout-card
layout_type: masonry
cards:
  - type: custom:decluttering-card
    template: header_main
  - show_current: false
    show_forecast: true
    type: weather-forecast
    entity: weather.openweathermap
    forecast_type: daily
    card_mod:
      style: |
        ha-card {
          background: var(--background-color-2);
          border-radius: 50px;
        }     
  - type: custom:bubble-card
    card_type: button
    button_type: state
    entity: person.hannah_holden
    show_attribute: false
    attribute: device_trackers
    show_last_changed: false
    show_name: true
    card_layout: large
    sub_button:
      - entity: sensor.hannah_holdens_iphone_geocoded_location
        show_icon: false
        show_state: true
        show_background: false
      - entity: sensor.hannah_holdens_iphone_battery_level
        show_state: true
        show_background: false
      - entity: sensor.hannah_holdens_iphone_activity
    styles: |-
      .bubble-button-background {
        background-color: ${state === 'home' ? 'var(--accent-color)':''} !important;
      }
      .bubble-sub-button-1 {
        font-size: 10px;
        line-height: 1.5;
        text-align: center;
      }
  - type: custom:bubble-card
    card_type: button
    button_type: state
    entity: person.christopher_hemmings
    show_attribute: false
    attribute: device_trackers
    show_last_changed: false
    show_name: true
    card_layout: large
    sub_button:
      - entity: sensor.iphone_13_pro_max_geocoded_location
        show_icon: false
        show_state: true
        show_background: false
      - entity: sensor.iphone_13_pro_max_battery_level
        show_state: true
        show_background: false
      - entity: sensor.iphone_13_pro_max_activity
    styles: |-
      .bubble-button-background {
        background-color: ${state === 'home' ? 'var(--accent-color)':''} !important;
      }
      .bubble-sub-button-1 {
        font-size: 10px;
      }
      .bubble-sub-button-1 {
        font-size: 10px;
        line-height: 1.5;
        text-align: center;
      }
    show_state: true
  - type: custom:bubble-card
    card_type: button
    button_type: state
    entity: alarm_control_panel.alarmo
    name: Status
    show_state: true
    card_layout: large-2-rows
    sub_button:
      - name: Home temperature
        icon: mdi:home-thermometer-outline
        entity: sensor.indoor_temperature
        show_state: true
        show_icon: true
        show_background: false
      - name: Outside temperature
        entity: sensor.outdoor_station_temperature
        show_state: true
        show_background: false
      - name: Doors
        entity: sensor.doors_open
        show_name: true
        show_state: true
        tap_action:
          action: navigate
          navigation_path: '#security'
        show_attribute: false
        attribute: temperature
        icon: mdi:door-open
      - name: Windows
        entity: sensor.windows_open
        show_name: true
        show_state: true
        show_background: true
        show_attribute: false
        attribute: temperature
        icon: mdi:window-open
        show_icon: true
        tap_action:
          action: navigate
          navigation_path: '#security'
    styles: >
      .bubble-icon {
        color: ${hass.states['alarm_control_panel.alarmo'].state === 'armed_home' ? 'red' : (hass.states['alarm_control_panel.alarmo'].state === 'arming' ? 'orange' : 'grey')} !important;
        animation: ${hass.states['alarm_control_panel.alarmo'].state === 'arming' ? 'fade-in-out 2s linear infinite' : ''};
      }


      @keyframes fade-in-out {
        0%, 100% { opacity: 1; }
        50% { opacity: 0; }
      }


      ${icon.setAttribute("icon",
      hass.states['alarm_control_panel.alarmo'].state === 'armed_home' ?
      'mdi:shield-home' : 'mdi:shield-off-outline')}
    show_last_changed: false
    show_attribute: false
  - type: horizontal-stack
    cards:
      - type: custom:mushroom-template-card
        primary: Lights
        secondary: ''
        icon: mdi:lightbulb-group
        icon_color: yellow
        layout: vertical
        tap_action:
          action: navigate
          navigation_path: '#lights'
        hold_action:
          action: none
        double_tap_action:
          action: none
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }         
      - type: custom:mushroom-template-card
        primary: Blinds
        secondary: ''
        icon: mdi:blinds
        icon_color: teal
        layout: vertical
        tap_action:
          action: navigate
          navigation_path: '#blinds'
        hold_action:
          action: none
        double_tap_action:
          action: none
        fill_container: false
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }
      - type: custom:mushroom-template-card
        primary: Climate
        secondary: ''
        icon: mdi:air-conditioner
        icon_color: blue
        layout: vertical
        tap_action:
          action: navigate
          navigation_path: '#climate'
        fill_container: false
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }      
      - type: custom:mushroom-template-card
        primary: Garage
        secondary: ''
        icon: mdi:garage
        icon_color: green
        layout: vertical
        hold_action:
          action: none
        double_tap_action:
          action: none
        tap_action:
          action: navigate
          navigation_path: '#garage'
        fill_container: false
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }    
  - type: horizontal-stack
    cards:
      - type: custom:mushroom-template-card
        primary: Irrigation
        secondary: ''
        icon: mdi:water
        layout: vertical
        icon_color: blue
        tap_action:
          action: navigate
          navigation_path: '#irrigation'
        fill_container: true
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }           
      - type: custom:mushroom-template-card
        primary: Vacuum
        secondary: ''
        icon: mdi:robot-vacuum
        icon_color: purple
        fill_container: true
        layout: vertical
        tap_action:
          action: navigate
          navigation_path: '#vacuum'
        hold_action:
          action: none
        double_tap_action:
          action: none
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }             
      - type: custom:mushroom-template-card
        primary: Energy
        secondary: ''
        icon: mdi:lightning-bolt
        icon_color: orange
        fill_container: true
        layout: vertical
        tap_action:
          action: navigate
          navigation_path: '#energy'
        hold_action:
          action: none
        double_tap_action:
          action: none
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }             
      - type: custom:mushroom-template-card
        primary: Cameras
        secondary: ''
        icon: mdi:cctv
        icon_color: red
        fill_container: true
        layout: vertical
        tap_action:
          action: navigate
          navigation_path: '#cameras'
        hold_action:
          action: none
        double_tap_action:
          action: none
        card_mod:
          style: |
            ha-card {
              background: var(--background-color-2);
              border-radius: 35px;
            }   

Yaml for the footer showing the buttons

type: custom:bubble-card
card_type: horizontal-buttons-stack
button_type: state
entity: weather.openweathermap
auto_order: false
1_name: ''
1_icon: mdi:sofa-outline
1_link: '#family'
2_link: '#kitchen'
2_name: ''
2_icon: mdi:pot-steam-outline
4_name: ''
4_icon: mdi:sofa-single-outline
4_link: '#lounge'
5_link: '#other'
5_name: ''
5_icon: mdi:home-variant-outline
6_link: '#outdoors'
6_name: ''
6_icon: mdi:outdoor-lamp
hide_gradient: false
highlight_current_view: true
margin: 7px
width_desktop: 1000px
3_name: ''
3_icon: mdi:bed-king-outline
3_link: '#bedroom'

Yaml for one of the popup pages

type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    hash: '#family'
    button_type: name
    show_header: true
    name: Family Room
    icon: mdi:sofa-outline
    scrolling_effect: false
    show_icon: false
    show_name: false
    force_icon: false
    show_state: false
    show_attribute: false
    show_last_changed: false
    sub_button:
      - entity: sensor.indoor_temperature
        show_background: false
        show_icon: true
        show_state: true
        name: ''
        show_name: false
      - entity: sensor.indoor_humidity
        show_last_changed: false
        show_state: true
        show_background: false
    entity: light.family_lights
    card_layout: normal
    trigger_state: ''
    trigger_close: true
    bg_color: ''
    bg_opacity: '88'
    hide_backdrop: false
    styles: ''
    tap_action:
      action: none
    double_tap_action:
      action: none
    hold_action:
      action: none
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Lights
      - icon: mdi:lightbulb-group
  - type: custom:bubble-card
    card_type: button
    button_type: slider
    entity: light.family_lights
    name: Ambient Lights
    show_state: false
    tap_action:
      action: toggle
    double_tap_action:
      action: none
    hold_action:
      action: more-info
    sub_button: []
  - type: horizontal-stack
    cards:
      - type: custom:decluttering-card
        template: light_template
        variables:
          - entity: light.family_room_light
          - name: Light
      - type: custom:decluttering-card
        template: dimmer_template
        variables:
          - entity: light.family_room_lamp
          - name: Lamp
  - type: horizontal-stack
    cards:
      - type: custom:decluttering-card
        template: dimmer_template
        variables:
          - entity: light.family_room_led_strip
          - name: Led Strip
          - icon: mdi:led-strip
      - type: custom:decluttering-card
        template: dimmer_template
        variables:
          - entity: light.display_cabinet_lights
          - name: Cabinet lights
  - type: custom:decluttering-card
    template: light_template
    variables:
      - entity: light.fish_tank_light
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Switches
      - icon: mdi:power
  - type: horizontal-stack
    cards:
      - type: horizontal-stack
        cards:
          - type: custom:bubble-card
            card_type: button
            entity: button.heater_off
            icon: mdi:radiator-off
          - type: custom:bubble-card
            card_type: button
            entity: button.heater_on
            icon: mdi:radiator
  - type: custom:layout-card
    layout_type: custom:vertical
    cards:
      - type: custom:bubble-card
        card_type: button
        entity: switch.wallflower
        show_attribute: false
        icon: mdi:flower
        sub_button: []
        styles: ''
      - type: conditional
        conditions:
          - condition: state
            entity: timer.family_wallflower_timer
            state: active
        card:
          type: custom:decluttering-card
          template: timer_template
          variables:
            - icon: mdi:timer
            - entities:
                - timer.family_wallflower_timer
    layout:
      card_margin: '-3.5px -3.5px 3.5px -3.5px'
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Media
      - icon: mdi:play-pause
  - type: custom:bubble-card
    card_type: media-player
    name: Ceiling Speakers
    entity: media_player.ceiling_speakers
    show_state: true
    show_last_updated: true
    show_attribute: false
    attribute: volume_level
    card_layout: large
    scrolling_effect: true
    show_icon: true
    force_icon: false
    show_name: true
    show_last_changed: false
    columns: 2
    rows: 1
    tap_action:
      action: toggle
    hide:
      play_pause_button: false
      volume_button: false
      previous_button: false
      next_button: false
      power_button: true
    sub_button: []
  - type: custom:bubble-card
    card_type: media-player
    entity: media_player.family_room_tv
    hide:
      play_pause_button: true
      next_button: true
      power_button: true
      previous_button: true
      volume_button: true
    tap_action:
      action: more-info
      service: Button.press
      target:
        entity_id: button.power
    hold_action:
      action: more-info
    double_tap_action:
      action: more-info
    sub_button:
      - entity: media_player.family_room_tv
        icon: mdi:volume-minus
        tap_action:
          action: call-service
          service: button.press
          target:
            entity_id: button.volume_down
      - entity: media_player.family_room_tv
        icon: mdi:volume-plus
        tap_action:
          action: call-service
          service: button.press
          target:
            entity_id: button.volume_up
      - entity: media_player.family_room_tv
        icon: mdi:power
        tap_action:
          action: call-service
          service: button.press
          target:
            entity_id: button.power
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Blinds
      - icon: mdi:blinds-vertical
  - type: vertical-stack
    cards:
      - type: custom:decluttering-card
        template: cover_horizontal_template
        variables:
          - name: Left Blind
          - entity: cover.family_room_left_blind
          - sub1: sensor.family_room_left_blind_battery
      - type: custom:decluttering-card
        template: cover_horizontal_template
        variables:
          - name: Right Blind
          - entity: cover.family_room_right_blind
          - sub1: sensor.family_room_right_blind_battery

Yaml for the decluttering template cards. This goes in your raw config yaml for the dashboard, BEFORE the views. right at the beginning

decluttering_templates:
  timer_template:
    default:
      - icon: ''
      - name: ''
    card:
      type: custom:timer-bar-card
      name: '[[name]]'
      icon: '[[icon]]'
      entities: '[[entities]]'
      bar_height: 20px
      bar_background: var(--background-color)
      bar_foreground: var(--text-color)
      invert: true
      bar_radius: var(--ha-card-border-radius)
      layout: hide_name
      card_mod:
        style: |
          ha-card {
            position: relative;
            top: -47px;
            width: 60%; 
            margin-left: auto;
            margin-right: 5px;
            background: none;
            height: 0;
          }
          .card-content {
            padding: 0px !important;
          }
  header_main:
    card:
      type: custom:paper-buttons-row
      styles:
        justify-content: space-between
        background: none
        margin: 24px 20px 16px
        text-shadow: 0px 0px 20px var(--card-background-color);
      buttons:
        - layout: name_state
          name: >-
            {{ now().strftime('%A') }} {{ now().strftime('%d') }} {{
            now().strftime('%B') }}
          state: >-
            {{ now().strftime('%I') }}:{{ now().strftime('%M')}} {{
            now().strftime('%p')}}
          styles:
            name:
              font-weight: 400
              font-size: 16px
              margin-left: 0
              display: block
              text-align: left
              float: left
              width: 140px
            button:
              pointer-events: none
              align-items: left
              width: 140px
              line-height: 1.6em
            state:
              font-weight: 700
              font-size: 30px
              letter-spacing: '-1px'
              margin-left: 0
              display: block
              text-align: left
              float: left
              width: 140px
        - layout: icon|name_state
          name: ⌂ {{ states('sensor.indoor_temperature') }}°C
          state: '{{ states(''sensor.outdoor_station_temperature'') }}°C'
          image: |
            {% set mapper =
              { 'cloudy':'cloudy',
                'clear-night':'clear-night',
                'exceptional':'sunny-day',
                'fog':'fog',
                'lightning':'isolated-thunderstorms',
                'partlycloudy':'cloudy-day-3',              
                'rainy':'rainy-4',
                'sunny':'day',
                'windy':'wind',
                'windy-variant':'wind'} %}
            {% set state = states('weather.openweathermap') %}
            {% set weather = mapper[state] if state in mapper else 'weather' %}
            {% set path = '/local/icons/weather_icons/animated/' %}
            {% set ext = '.svg'%}
              {{[path,weather,ext]|join('')}}
          styles:
            name:
              font-weight: 400
              font-size: 16px
              margin-left: 0
              display: block
              text-align: right
              width: 140px
            button:
              pointer-events: none
              align-items: right
              width: 140px
              line-height: 1.6em
            state:
              font-weight: 600
              font-size: 30px
              letter-spacing: '-1px'
              margin-left: 0
              display: block
              text-align: right
              width: 140px
            icon:
              position: absolute
              left: 2px
              transform: scale(0.17)
              transform-origin: 0 19.5%
              top: '-48px;'
              padding: 0;
              height: 380px !important;
              width: 380px !important;
  seperator_template:
    default:
      - icon: ''
      - name: ''
    card:
      type: custom:bubble-card
      card_type: separator
      name: '[[name]]'
      card_layout: large
      styles: |
        .bubble-name {
          height: 25px;
          font-weight: 100;
          font-size: 25px;
        }
        .bubble-line {
          background-color: var(--background-color-2, var(--secondary-background-color));
          opacity: 0.4;
        }
  dimmer_template:
    default:
      - icon: ''
      - name: ''
    card:
      type: custom:bubble-card
      card_type: button
      button_type: slider
      entity: '[[entity]]'
      name: '[[name]]'
      icon: '[[icon]]'
      tap_action:
        action: toggle
      hold_action:
        action: more-info
  fan_template:
    default:
      - icon: ''
      - name: ''
    card:
      type: custom:bubble-card
      card_type: button
      button_type: slider
      entity: '[[entity]]'
      name: '[[name]]'
      icon: '[[icon]]'
      show_state: true
      tap_action:
        action: toggle
      hold_action:
        action: more-info
  light_template:
    default:
      - icon: ''
      - name: ''
    card:
      type: custom:bubble-card
      card_type: button
      button_type: switch
      entity: '[[entity]]'
      name: '[[name]]'
      icon: '[[icon]]'
      tap_action:
        action: more-info
  cover_template:
    default:
      - name: ''
    card:
      type: custom:bubble-card
      card_type: cover
      entity: '[[entity]]'
      name: '[[name]]'
      icon_open: mdi:blinds-vertical
      icon_close: mdi:blinds-vertical-closed
      show_state: true
      columns: 2
      card_layout: large
      sub_button:
        - name: My
          icon: mdi:star
          show_background: false
          tap_action:
            action: call-service
            service: cover.set_cover_position
            data:
              position: 50
            target:
              entity_id:
                - '[[entity]]'
      card_mod:
        style: |
          .bubble-cover-card-container {
            background-color:
              {% if state_attr(config.entity, 'current_position') == 100 %}
                var(--state-cover-active-color)
              {% elif state_attr(config.entity, 'current_position') > 0 %}
                var(--accent-color)
              {% else %}
                var(--background-color-2, var(--secondary-background-color))
              {% endif %}
            !important;
          }
          .large .bubble-buttons {
            gap: 8px;
          }
          .bubble-button {
            background: transparent;
            width: 40px;
            height: 40px;
          }
          .bubble-icon {
            justify-content: center;
            align-items: center;
          }
          .large .bubble-sub-button-container {
            margin-right: 8px;
          }
          .bubble-sub-button {
            background: transparent;
            width: 40px;
            height: 40px;
          }
          .bubble-state::after {
            content: " - {{ state_attr(config.entity, 'current_position') }}%";
            margin-left: 4px;
          }
          .bubble-icon-container {
            border-color: transparent;
            background-color: transparent;
          }
          .bubble-icon-container::after {
            content: "";
            background-color:
              {% if state_attr(config.entity, 'current_position') == 100 %}
                var(--state-cover-active-color)
              {% elif state_attr(config.entity, 'current_position') > 0 %}
                var(--accent-color)
              {% else %}
                var(--background-color-2, var(--secondary-background-color))
              {% endif %}
            !important;
            height: 25px;
            width: 25px;
            position: absolute;
            left: 50px;
            top: 25px;
            -webkit-mask-image: radial-gradient(circle at top right, transparent 0, transparent 25px, black 25.5px);
          }
  cover_horizontal_template:
    default:
      - name: ''
      - sub1: ''
    card:
      type: custom:bubble-card
      card_type: cover
      entity: '[[entity]]'
      name: '[[name]]'
      sub_button:
        - entity: '[[sub1]]'
          show_last_changed: false
          show_state: true
      icon_open: mdi:blinds-open
      icon_close: mdi:blinds
      show_state: true
      columns: 2
      card_layout: large
      card_mod:
        style: |
          .bubble-cover-card-container {
            background-color:
              {% if state_attr(config.entity, 'current_position') == 100 %}
                var(--state-cover-active-color)
              {% elif state_attr(config.entity, 'current_position') > 0 %}
                var(--accent-color)
              {% else %}
                var(--background-color-2, var(--secondary-background-color))
              {% endif %}
            !important;
          }
          .large .bubble-buttons {
            gap: 8px;
          }
          .bubble-button {
            background: transparent;
            width: 40px;
            height: 40px;
          }
          .bubble-icon {
            justify-content: center;
            align-items: center;
          }
          .large .bubble-sub-button-container {
            margin-right: 8px;
          }
          .bubble-sub-button {
            background: transparent;
            width: 40px;
            height: 40px;
          }
          .bubble-state::after {
            content: " - {{ state_attr(config.entity, 'current_position') }}%";
            margin-left: 4px;
          }
          .bubble-icon-container {
            border-color: transparent;
            background-color: transparent;
          }
          .bubble-icon-container::after {
            content: "";
            background-color:
              {% if state_attr(config.entity, 'current_position') == 100 %}
                var(--state-cover-active-color)
              {% elif state_attr(config.entity, 'current_position') > 0 %}
                var(--accent-color)
              {% else %}
                var(--background-color-2, var(--secondary-background-color))
              {% endif %}
            !important;
            height: 25px;
            width: 25px;
            position: absolute;
            left: 50px;
            top: 25px;
            -webkit-mask-image: radial-gradient(circle at top right, transparent 0, transparent 25px, black 25.5px);
          }          
6 Likes

Thanks for sharing, awesome!!

Thank you Chris :pray:

More and more of my cards are being replaced with bubble cards, love how easy they are to customize with card mod!

I have some identical CSS applied to multiple pop-up cards that I’d love to be able to pull out and put into the theme file like all other CSS. However, I have no idea how to apply the appropriate selectors on that side.

This is and example of what I have:

    type: vertical-stack
    cards:
      - type: custom:bubble-card
        card_type: pop-up
        hash: '#media'
        bg_opacity: '0'
        bg_blur: '0'
        icon: none
        show_header: false
        close_by_clicking_outside: false
        styles: |
          .bubble-header-container {
            display: none !important;
          }
          .bubble-pop-up-container {
            margin-top: var(--bubble-pull-up) !important;
            padding: 0 !important;
          }
          .bubble-pop-up {
            border-radius: 12px !important;
            margin: 0 !important;
            padding: 0 !important;
          }
          .bubble-backdrop {
            height: calc(100vh - 80px) !important;
          }

But in the theme file, I don’t get those styles by placing the directly underneath

   card-mod-card: |

I’ve been trying to figure this out from the inspector, but it seems some of these styles need to be applied to elements that are a couple of levels above the ha-card element, and even outside a shadow root that contains it.

Any ideas on this?

Hi chris,

Would you mind sharing your air con popup and garage, I want to beef up my graphs like yours and add my garage door like yours

How do I remove the blur at the top of the screen?

I’ve tried bg_blur: ‘0’ but it doesn’t do anything.

Have you tried to play with these parameters ?

1 Like

Thanks for making such a great card, is there a way that we can template style the bubble cards similar to the custom button card? Otherwise im finding i have to apply my additional styles to every single card of the same type and then have to change every single card manually if i decide to change something.

Thanks again for the great work with this

1 Like

Garage Card

type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    trigger_close: true
    hash: '#garage'
    entity: cover.garage_door
    show_last_changed: true
    show_state: true
    name: Garage
    button_type: name
    icon: mdi:garage-variant
    tap_action:
      action: none
    double_tap_action:
      action: none
    hold_action:
      action: none
    styles: ''
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Control
      - icon: mdi:garage-variant
  - type: custom:bubble-card
    card_type: cover
    entity: cover.garage_door
    show_icon: true
    force_icon: false
    show_name: true
    show_last_changed: true
    show_state: true
    show_attribute: false
    card_layout: large-2-rows
  - type: custom:frigate-card
    cameras:
      - camera_entity: camera.garage
    menu:
      style: none
  - type: custom:bubble-card
    card_type: button
    entity: lock.rear_entry_door
    sub_button:
      - show_attribute: false
        show_state: false
        name: Unlock
        show_background: false
        icon: mdi:lock-open
        tap_action:
          action: call-service
          service: lock.unlock
          target:
            entity_id: lock.rear_entry_door
        show_name: true
      - show_attribute: false
        show_state: false
        name: Lock
        show_background: false
        icon: mdi:lock
        tap_action:
          action: call-service
          service: lock.lock
          target:
            entity_id: lock.rear_entry_door
        show_name: true
    show_state: true
    styles: >+
      .bubble-sub-button-1 {
        display: ${hass.states['lock.rear_entry_door'].state === 'unlocked' ? 'none' : ''} !important
      }

      .bubble-sub-button-2 {
        display: ${hass.states['lock.rear_entry_door'].state === 'locked' ? 'none' : ''} !important
      }

      .bubble-state.state.display-state:after {
        content: "% battery"; /* Unicode for mdi:battery icon */
        margin-right: 5px;
      }

      @keyframes fade-in-out {
        0%, 100% { opacity: 1; }
        50% { opacity: 0; }
      }




      ${icon.setAttribute("icon", hass.states['lock.rear_entry_door'].state ===
      'unlocked' ? 'mdi:lock-open' : 'mdi:lock')}

    button_type: switch
    show_attribute: true
    show_last_changed: true
    attribute: battery
    double_tap_action:
      action: more-info
    hold_action:
      action: more-info
    button_action:
      tap_action:
        action: none
      double_tap_action:
        action: none
      hold_action:
        action: none
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Light
      - icon: mdi:lightbulb-group
  - type: custom:decluttering-card
    template: light_template
    variables:
      - entity: light.garage_light
      - name: Light

Aircon Card

type: vertical-stack
cards:
  - type: custom:bubble-card
    card_type: pop-up
    trigger_close: true
    hash: '#climate'
    name: Air Conditioner
    icon: mdi:home-thermometer
    tap_action:
      action: none
    double_tap_action:
      action: none
    hold_action:
      action: none
    button_type: name
    entity: switch.air_conditioner
    show_state: true
    show_last_changed: true
    show_icon: true
    show_name: true
  - type: custom:bubble-card
    card_type: button
    entity: switch.air_conditioner
    scrolling_effect: true
    force_icon: false
    show_state: true
    show_last_changed: true
  - type: custom:decluttering-card
    template: seperator_template
    variables:
      - name: Status
      - icon: mdi:thermometer-lines
  - type: horizontal-stack
    cards:
      - type: custom:mini-graph-card
        name: Inside Temp
        entities:
          - sensor.indoor_temperature
        align_icon: left
        align_state: center
        show:
          fill: true
        color_thresholds:
          - value: 10
            color: '#036ffc'
          - value: 20
            color: '#a503fc'
          - value: 30
            color: '#fc0345'
      - type: custom:mini-graph-card
        name: Inside Humidity
        entities:
          - sensor.indoor_humidity
        align_icon: left
        align_state: center
        show:
          fill: true
        color_thresholds:
          - value: 80
            color: '#fc0345'
          - value: 65
            color: '#a503fc'
          - value: 50
            color: '#036ffc'
  - type: horizontal-stack
    cards:
      - type: custom:mini-graph-card
        name: Outside Temp
        entities:
          - sensor.outdoor_station_temperature
        align_icon: left
        align_state: center
        show:
          fill: true
        color_thresholds:
          - value: 10
            color: '#036ffc'
          - value: 20
            color: '#a503fc'
          - value: 30
            color: '#fc0345'
      - type: custom:mini-graph-card
        name: Outside Humidity
        entities:
          - sensor.outdoor_station_humidity
        align_icon: left
        align_state: center
        show:
          fill: true
        color_thresholds:
          - value: 80
            color: '#fc0345'
          - value: 65
            color: '#a503fc'
          - value: 50
            color: '#036ffc'
  - type: horizontal-stack
    cards:
      - type: custom:mini-graph-card
        name: Co2
        entities:
          - sensor.indoor_carbon_dioxide
        icon: mdi:molecule-co2
        align_icon: left
        align_state: center
        show:
          fill: true
        color_thresholds:
          - value: 500
            color: '#036ffc'
          - value: 1000
            color: '#a503fc'
          - value: 1500
            color: '#fc0345'
      - type: custom:mini-graph-card
        name: Rain
        entities:
          - sensor.indoor_smart_rain_gauge_precipitation
        icon: mdi:water-alert
        align_icon: left
        align_state: center
        show:
          fill: true
        color_thresholds:
          - value: 30
            color: '#fc0345'
          - value: 15
            color: '#a503fc'
          - value: 0
            color: '#036ffc'

1 Like

If anything, this should be under

card_mod:

At all times