Files

5.1 KiB

Bubble Card Pop-up Migration — v3.2.0 Standalone Format

Session: 2026-07-10. Part of the HA dashboard redesign. All 5 pop-ups in the "Haus" dashboard were migrated from legacy format to the new standalone format.

What Changed

Bubble Card v3.2.0 introduced standalone pop-ups. Legacy pop-ups (content cards as siblings in the view) must be migrated to standalone format (content cards nested inside the pop-up's cards: property).

Benefits of standalone format:

  • Faster rendering
  • More reliable display
  • No longer need to live inside a vertical-stack card
  • New editor based on HA section editor (drag-and-drop)
  • New features: centered mode, classic style, performance mode

⚠️ CRITICAL PITFALL: Pop-up Migration Broke Tab Rendering

Moving content cards INTO the pop-up's cards: property (as the v3.2.0 migration instructs) caused all views to render as empty/blank. The user reported "die tabs sind leer" (the tabs are empty). The pop-up acts as an overlay — its content is hidden until the pop-up is triggered (hash navigation). When using Bubble Card bottom-navigation for tab switching, the pop-up is redundant and its content cards become invisible.

Fix Applied

Removed all card_type: 'pop-up' cards from every view entirely. Content cards stay at view level as siblings of the bottom-navigation card. This works correctly — tabs show their content, bottom-navigation switches between views.

Lesson

The v3.2.0 "standalone pop-up" format is designed for pop-ups that open/close on demand (hash-triggered overlays). If you're using bottom-navigation for persistent tab navigation (not pop-up overlays), do NOT use pop-up cards at all — just put content cards directly in the view alongside the bottom-navigation card. The migration notice is misleading for this use case.

Final Working Structure

views:
  - title: Home
    path: home
    cards:
      # NO pop-up card — just content + navigation
      - type: custom:mushroom-template-card
        primary: "{{ states('weather.forecast_home') }}"
        ...
      - type: custom:power-flow-card-plus
        ...
      - type: custom:bubble-card
        card_type: bottom-navigation
        routes:
          - icon: mdi:home
            name: Home
            target: "#home"
          - icon: mdi:window-shutter
            name: Rollos
            target: "#rollos"
          # ...more routes

Migration Script (WebSocket) — FOR REFERENCE ONLY

This script moves cards into the pop-up. Do NOT use it if you're using bottom-navigation for tab switching — it will make your views blank. Only use if you genuinely need pop-up overlays (modal dialogs).

(async () => {
  const ha = document.querySelector("home-assistant");
  const conn = ha.hass.connection;

  const cfg = await conn.sendMessagePromise({type: 'lovelace/config', url_path: 'dashboard-haus'});

  for (const view of cfg.views) {
    const cards = view.cards || [];
    const popupIdx = cards.findIndex(c => c.card_type === 'pop-up');
    if (popupIdx === -1) continue;

    const popup = cards[popupIdx];
    const navIdx = cards.findIndex(c => c.card_type === 'bottom-navigation');

    // Content cards = everything EXCEPT pop-up and bottom-nav
    const contentCards = cards.filter((c, i) => i !== popupIdx && i !== navIdx);

    // Move content INTO the pop-up
    popup.cards = contentCards;

    // Rebuild: [pop-up (with content), bottom-nav]
    const newCards = [popup];
    if (navIdx !== -1) newCards.push(cards[navIdx]);

    view.cards = newCards;
  }

  await conn.sendMessagePromise({
    type: 'lovelace/config/save',
    url_path: 'dashboard-haus',
    config: cfg
  });
})();

Revert Script (Remove Pop-ups Entirely)

This is what actually fixed the blank-tab issue:

(async () => {
  const ha = document.querySelector("home-assistant");
  const conn = ha.hass.connection;

  const cfg = await conn.sendMessagePromise({type: 'lovelace/config', url_path: 'dashboard-haus'});

  // Remove all pop-up cards from all views
  for (const view of cfg.views) {
    view.cards = (view.cards || []).filter(c => c.card_type !== 'pop-up');
  }

  await conn.sendMessagePromise({
    type: 'lovelace/config/save',
    url_path: 'dashboard-haus',
    config: cfg
  });
})();

Verification

  • Check cfg.views[].cards structure — no card should have card_type: 'pop-up' with nested cards: if using bottom-navigation
  • Navigate to each view hash — content should be visible immediately
  • 0 render errors in browser console
  • Test on a real browser, not just headless — the headless browser may fail to render cards after homeassistant.reload_all + service worker clear, even when the config is correct

Headless Browser Rendering Issue

After homeassistant.reload_all + clearing service workers/caches, the headless browser failed to render ANY dashboard (including the old Übersicht with 43 cards). ha-card count was 0 across all dashboards. The config was verified correct via WebSocket (correct card structure, entity IDs, no errors). This appears to be a headless-browser caching issue, not a config issue. Testing on a real browser/mobile device is the reliable verification method.