From b9250dab2e366d6005ef366cd7c20497836cda60 Mon Sep 17 00:00:00 2001 From: sneak Date: Fri, 27 Feb 2026 16:05:49 +0700 Subject: [PATCH] Fix layout shift from async USD prices and token balances Reserve vertical space with min-height and   placeholders for all elements populated by async data: per-address USD totals, ETH price display, token balance containers, and total value sub-line. Prevents buttons and click targets from moving when price API responds. --- src/popup/index.html | 20 ++++++++++++++------ src/popup/views/addressDetail.js | 3 ++- src/popup/views/addressToken.js | 3 ++- src/popup/views/home.js | 14 ++++++++------ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/popup/index.html b/src/popup/index.html index 848ce08..445dc46 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -274,11 +274,15 @@
+ class="text-xs text-muted mb-3 text-right min-h-[1rem]" + > +   +
-
+
+   +
@@ -343,11 +347,15 @@
+ class="text-xs text-muted mb-3 text-right min-h-[1rem]" + > +   +
-
+
+   +
diff --git a/src/popup/views/addressDetail.js b/src/popup/views/addressDetail.js index 26ed95d..d2794e6 100644 --- a/src/popup/views/addressDetail.js +++ b/src/popup/views/addressDetail.js @@ -54,7 +54,8 @@ function show() { const addrLink = etherscanAddressLink(addr.address); $("address-etherscan-link").innerHTML = `${EXT_ICON}`; - $("address-usd-total").textContent = formatUsd(getAddressValueUsd(addr)); + const usdTotal = formatUsd(getAddressValueUsd(addr)); + $("address-usd-total").innerHTML = usdTotal || " "; const ensEl = $("address-ens"); if (addr.ensName) { ensEl.innerHTML = diff --git a/src/popup/views/addressToken.js b/src/popup/views/addressToken.js index 8b3d78f..3159b70 100644 --- a/src/popup/views/addressToken.js +++ b/src/popup/views/addressToken.js @@ -124,7 +124,8 @@ function show() { // USD total for this token only const usdVal = price ? amount * price : 0; - $("address-token-usd-total").textContent = formatUsd(usdVal); + const usdStr = formatUsd(usdVal); + $("address-token-usd-total").innerHTML = usdStr || " "; // Single token balance line (no tokenId — not clickable here) $("address-token-balance").innerHTML = balanceLine(symbol, amount, price); diff --git a/src/popup/views/home.js b/src/popup/views/home.js index d57690b..1ef0e7e 100644 --- a/src/popup/views/home.js +++ b/src/popup/views/home.js @@ -38,13 +38,15 @@ function renderTotalValue() { const ethPrice = getPrice("ETH"); if (priceEl) { - priceEl.textContent = ethPrice ? formatUsd(ethPrice) + " USD/ETH" : ""; + priceEl.innerHTML = ethPrice + ? formatUsd(ethPrice) + " USD/ETH" + : " "; } const addr = findActiveAddr(); if (!addr) { - el.textContent = ""; - if (subEl) subEl.textContent = ""; + el.innerHTML = " "; + if (subEl) subEl.innerHTML = " "; return; } const ethBal = parseFloat(addr.balance || "0"); @@ -54,8 +56,8 @@ function renderTotalValue() { if (subEl) { const totalUsd = getAddressValueUsd(addr); - subEl.textContent = - totalUsd !== null ? "Total: " + formatUsd(totalUsd) : ""; + subEl.innerHTML = + totalUsd !== null ? "Total: " + formatUsd(totalUsd) : " "; } } @@ -276,7 +278,7 @@ function render(ctx) { html += `${infoBtn}`; html += ``; const addrUsd = formatUsd(getAddressValueUsd(addr)); - html += `
${addrUsd}
`; + html += `
${addrUsd || " "}
`; html += balanceLinesForAddress( addr, state.trackedTokens,