Rewrite tx list with innerHTML, fix scrollbar overlay and overflow
Some checks failed
check / check (push) Has been cancelled

- Rebuilt tx list rendering using innerHTML instead of createElement
- scrollbar-gutter: stable on body to prevent content shift
- max-width:42ch instead of width:42ch to prevent horizontal overflow
- overflow-x:hidden on body and #app
This commit is contained in:
2026-02-26 03:12:33 +07:00
parent 197f40bde5
commit 75ec67617b
5 changed files with 24 additions and 49 deletions

View File

@@ -99,57 +99,30 @@ function renderTransactions(txs) {
'<div class="text-muted text-xs py-1">No transactions found.</div>';
return;
}
list.innerHTML = "";
txs.forEach((tx, i) => {
let html = "";
let i = 0;
for (const tx of txs) {
const counterparty = tx.direction === "sent" ? tx.to : tx.from;
const dirLabel = tx.direction === "sent" ? "Sent" : "Received";
const errorStyle = tx.isError ? " opacity:0.5" : "";
const row = document.createElement("div");
row.style.cssText =
"padding:0.5rem 0;border-bottom:1px solid #ccc;font-size:12px;cursor:pointer;overflow:hidden;" +
errorStyle;
const line1 = document.createElement("div");
line1.style.cssText =
"display:flex;justify-content:space-between;overflow:hidden;";
const age = document.createElement("span");
age.style.cssText =
"color:#666;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;";
age.textContent = timeAgo(tx.timestamp);
age.title = isoDate(tx.timestamp);
const dir = document.createElement("span");
dir.style.cssText =
"flex-shrink:0;padding-left:0.5rem;white-space:nowrap;" +
(tx.isError ? "color:#666;" : "");
dir.textContent = dirLabel + (tx.isError ? " (failed)" : "");
line1.appendChild(age);
line1.appendChild(dir);
const amountStr = tx.value + " " + tx.symbol;
const line2 = document.createElement("div");
line2.style.cssText =
"display:flex;justify-content:space-between;overflow:hidden;";
const addr = document.createElement("span");
addr.style.cssText =
"overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;";
const amountStr = escapeHtml(tx.value + " " + tx.symbol);
const maxAddr = Math.max(10, 38 - Math.max(0, amountStr.length - 10));
addr.textContent = truncateMiddle(counterparty, maxAddr);
addr.title = counterparty;
const amount = document.createElement("span");
amount.style.cssText =
"flex-shrink:0;padding-left:0.5rem;white-space:nowrap;";
amount.textContent = amountStr;
line2.appendChild(addr);
line2.appendChild(amount);
row.appendChild(line1);
row.appendChild(line2);
const addrStr = escapeHtml(truncateMiddle(counterparty, maxAddr));
const err = tx.isError ? " (failed)" : "";
const opacity = tx.isError ? " opacity:0.5;" : "";
const ago = escapeHtml(timeAgo(tx.timestamp));
const iso = escapeHtml(isoDate(tx.timestamp));
html += `<div class="tx-row py-2 border-b border-border-light text-xs cursor-pointer hover:bg-hover" data-tx="${i}" style="${opacity}">`;
html += `<div class="flex justify-between"><span class="text-muted" title="${iso}">${ago}</span><span>${dirLabel}${err}</span></div>`;
html += `<div class="flex justify-between"><span>${addrStr}</span><span>${amountStr}</span></div>`;
html += `</div>`;
i++;
}
list.innerHTML = html;
list.querySelectorAll(".tx-row").forEach((row) => {
row.addEventListener("click", () => {
state.selectedTx = i;
showTxDetail(tx);
const idx = parseInt(row.dataset.tx, 10);
showTxDetail(loadedTxs[idx]);
});
list.appendChild(row);
});
}