Compare commits

..

1 Commits

Author SHA1 Message Date
user
e13af842df feat: reorganize transaction detail view layout
All checks were successful
check / check (push) Successful in 22s
- Move transaction hash (txid) to first position after title
- Group fields into logical sections with visual dividers:
  Identity (hash, type, status, time), Value (amount, native qty,
  token contract), Parties (from, to), Protocol (calldata/action),
  On-chain (block, nonce, fee, gas price, gas used), Raw data
- Add tx-detail-group CSS class for subtle border separators
- Show on-chain details group wrapper only when data is loaded
- Maintain all existing functionality and copy-to-clipboard behavior

closes #131
2026-03-01 07:23:46 -08:00
4 changed files with 90 additions and 113 deletions

View File

@@ -435,36 +435,25 @@ transitions.
#### TransactionDetail
- **When**: User tapped a transaction row from AddressDetail or AddressToken.
- **Elements** (grouped into logical blocks using light well containers,
matching the Settings view pattern):
- **Elements**:
- "Transaction" heading, "Back" button
- **Identity block**:
- Blockie identicon (48px, centered, derived from transaction hash)
- Transaction hash: full hash (tap to copy) + etherscan link
- Type: transaction classification — one of: Native ETH Transfer, ERC-20
Token Transfer, Swap, Token Approval, Contract Call, Contract Creation
- Status: "Success" or "Failed"
- **Timing block**:
- Time: ISO datetime + relative age in parentheses
- Block: block number (tap to copy) + etherscan block link
- **Value block**:
- Amount: value + symbol (bold)
- Native quantity: raw integer + unit (shown when available)
- Token contract: shown for ERC-20 transfers — color dot + full contract
address (tap to copy) + etherscan token link
- From: blockie + color dot + full address (tap to copy) + etherscan
link; ENS name if available
- To: blockie + color dot + full address (tap to copy) + etherscan link;
ENS name if available
- **Decoded details** (shown for contract calls):
- Action name, decoded parameters, token details, swap steps
- **Network details** (shown when on-chain data is available):
- Nonce: transaction nonce (tap to copy)
- Gas price: value in Gwei (tap to copy)
- Gas used: integer (tap to copy)
- Transaction fee: ETH amount (tap to copy)
- **Raw data** (shown when calldata is present):
- Full calldata in monospace dashed border
- Type: transaction classification — one of: Native ETH Transfer, ERC-20
Token Transfer, Swap, Token Approval, Contract Call, Contract Creation
- Token contract: shown for ERC-20 transfers — color dot + full contract
address (tap to copy) + etherscan token link
- Status: "Success" or "Failed"
- Time: ISO datetime + relative age in parentheses
- Amount: value + symbol (bold)
- From: blockie + color dot + full address (tap to copy) + etherscan link
- ENS name if available
- To: blockie + color dot + full address (tap to copy) + etherscan link
- ENS name if available
- Transaction hash: full hash (tap to copy) + etherscan link
- Block: block number (tap to copy) + etherscan block link
- Nonce: transaction nonce (tap to copy)
- Transaction fee: ETH amount (tap to copy)
- Gas price: value in Gwei (tap to copy)
- Gas used: integer (tap to copy)
- **Transitions**:
- "Back" → **AddressToken** (if `selectedToken` set) or **AddressDetail**

View File

@@ -1066,13 +1066,8 @@
</h2>
<!-- ── Identity ── -->
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Identity</h3>
<div
id="tx-detail-blockie"
class="flex justify-center mt-1 mb-3"
></div>
<div class="mb-2">
<div class="tx-detail-group mb-1">
<div class="mb-3">
<div class="text-xs text-muted mb-1">
Transaction hash
</div>
@@ -1081,40 +1076,30 @@
class="text-xs break-all"
></div>
</div>
<div id="tx-detail-type-section" class="mb-2 hidden">
<div id="tx-detail-type-section" class="mb-3 hidden">
<div class="text-xs text-muted mb-1">Type</div>
<div
id="tx-detail-type"
class="text-xs font-bold"
></div>
</div>
<div class="mb-2">
<div class="mb-3">
<div class="text-xs text-muted mb-1">Status</div>
<div id="tx-detail-status" class="text-xs"></div>
</div>
</div>
<!-- ── Timing ── -->
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Timing</h3>
<div class="mb-2">
<div class="mb-1">
<div class="text-xs text-muted mb-1">Time</div>
<div id="tx-detail-time" class="text-xs"></div>
</div>
<div id="tx-detail-block-section" class="mb-2 hidden">
<div class="text-xs text-muted mb-1">Block</div>
<div id="tx-detail-block" class="text-xs"></div>
</div>
</div>
<!-- ── Value ── -->
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Value</h3>
<div class="mb-2">
<div class="tx-detail-group mb-1">
<div class="mb-3">
<div class="text-xs text-muted mb-1">Amount</div>
<div id="tx-detail-value" class="text-xs"></div>
</div>
<div class="mb-2 hidden">
<div class="mb-3 hidden">
<div class="text-xs text-muted mb-1">
Native quantity
</div>
@@ -1122,7 +1107,7 @@
</div>
<div
id="tx-detail-token-contract-section"
class="mb-2 hidden"
class="mb-1 hidden"
>
<div class="text-xs text-muted mb-1">
Token contract
@@ -1132,24 +1117,30 @@
class="text-xs break-all"
></div>
</div>
<div class="mb-2">
</div>
<!-- ── Parties ── -->
<div class="tx-detail-group mb-1">
<div class="mb-3">
<div class="text-xs text-muted mb-1">From</div>
<div
id="tx-detail-from"
class="text-xs break-all"
></div>
</div>
<div class="mb-2">
<div class="mb-1">
<div class="text-xs text-muted mb-1">To</div>
<div id="tx-detail-to" class="text-xs break-all"></div>
</div>
</div>
<!-- ── Decoded details ── -->
<div id="tx-detail-calldata-section" class="hidden">
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Decoded Details</h3>
<div id="tx-detail-calldata-well" class="mb-2">
<!-- ── Protocol ── -->
<div id="tx-detail-calldata-section" class="mb-1 hidden">
<div class="tx-detail-group mb-1">
<div
id="tx-detail-calldata-well"
class="border border-border border-dashed p-2"
>
<div class="text-xs text-muted mb-1">Action</div>
<div
id="tx-detail-calldata-action"
@@ -1163,45 +1154,43 @@
</div>
</div>
<!-- ── Network details ── -->
<div id="tx-detail-network-section" class="hidden">
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Network Details</h3>
<div id="tx-detail-nonce-section" class="mb-2 hidden">
<div class="text-xs text-muted mb-1">Nonce</div>
<div id="tx-detail-nonce" class="text-xs"></div>
</div>
<div
id="tx-detail-gasprice-section"
class="mb-2 hidden"
>
<div class="text-xs text-muted mb-1">Gas price</div>
<div id="tx-detail-gasprice" class="text-xs"></div>
</div>
<div id="tx-detail-gasused-section" class="mb-2 hidden">
<div class="text-xs text-muted mb-1">Gas used</div>
<div id="tx-detail-gasused" class="text-xs"></div>
</div>
<div id="tx-detail-fee-section" class="mb-2 hidden">
<div class="text-xs text-muted mb-1">
Transaction fee
</div>
<div id="tx-detail-fee" class="text-xs"></div>
<!-- ── On-chain details ── -->
<div
id="tx-detail-onchain-group"
class="tx-detail-group mb-1 hidden"
>
<div id="tx-detail-block-section" class="mb-3 hidden">
<div class="text-xs text-muted mb-1">Block</div>
<div id="tx-detail-block" class="text-xs"></div>
</div>
<div id="tx-detail-nonce-section" class="mb-3 hidden">
<div class="text-xs text-muted mb-1">Nonce</div>
<div id="tx-detail-nonce" class="text-xs"></div>
</div>
<div id="tx-detail-fee-section" class="mb-3 hidden">
<div class="text-xs text-muted mb-1">
Transaction fee
</div>
<div id="tx-detail-fee" class="text-xs"></div>
</div>
<div id="tx-detail-gasprice-section" class="mb-3 hidden">
<div class="text-xs text-muted mb-1">Gas price</div>
<div id="tx-detail-gasprice" class="text-xs"></div>
</div>
<div id="tx-detail-gasused-section" class="mb-1 hidden">
<div class="text-xs text-muted mb-1">Gas used</div>
<div id="tx-detail-gasused" class="text-xs"></div>
</div>
</div>
<!-- ── Raw data ── -->
<div id="tx-detail-rawdata-section" class="hidden">
<div class="bg-well p-3 mx-1 mb-3">
<h3 class="font-bold mb-1">Raw Data</h3>
<div class="mb-2">
<div class="text-xs text-muted mb-1">Raw data</div>
<div
id="tx-detail-rawdata"
class="text-xs break-all font-mono border border-border border-dashed p-2"
></div>
</div>
<div id="tx-detail-rawdata-section" class="mb-4 hidden">
<div class="tx-detail-group">
<div class="text-xs text-muted mb-1">Raw data</div>
<div
id="tx-detail-rawdata"
class="text-xs break-all font-mono border border-border border-dashed p-2"
></div>
</div>
</div>
</div>

View File

@@ -44,3 +44,11 @@ body {
background-color 225ms ease-out,
color 225ms ease-out;
}
/* Transaction detail view — visual grouping of related fields */
.tx-detail-group {
border-bottom: 1px solid var(--color-border-light);
padding-bottom: 0.5rem;
margin-bottom: 0.5rem;
padding-top: 0.25rem;
}

View File

@@ -130,19 +130,6 @@ function render() {
if (!tx) return;
$("tx-detail-hash").innerHTML = txHashHtml(tx.hash);
// Blockie identicon for the transaction hash
const blockieEl = $("tx-detail-blockie");
if (blockieEl) {
blockieEl.innerHTML = "";
const img = document.createElement("img");
img.src = makeBlockie(tx.hash);
img.width = 48;
img.height = 48;
img.style.imageRendering = "pixelated";
img.style.borderRadius = "50%";
blockieEl.appendChild(img);
}
const fromTitle = addressTitle(tx.from, state.wallets);
const toTitle = addressTitle(tx.to, state.wallets);
$("tx-detail-from").innerHTML = txAddressHtml(
@@ -203,14 +190,15 @@ function render() {
const rawDataSection = $("tx-detail-rawdata-section");
if (rawDataSection) rawDataSection.classList.add("hidden");
// Hide on-chain detail sections until populated
// Hide on-chain detail sections (and their group wrapper) until populated
const onchainGroup = $("tx-detail-onchain-group");
if (onchainGroup) onchainGroup.classList.add("hidden");
for (const id of [
"tx-detail-block-section",
"tx-detail-nonce-section",
"tx-detail-fee-section",
"tx-detail-gasprice-section",
"tx-detail-gasused-section",
"tx-detail-network-section",
]) {
const el = $(id);
if (el) el.classList.add("hidden");
@@ -299,10 +287,11 @@ function populateOnChainDetails(txData) {
);
}
// Show the network details wrapper if any child section is visible
const networkWrapper = $("tx-detail-network-section");
if (networkWrapper) {
// Show the on-chain details group if any child section is visible
const onchainGroup = $("tx-detail-onchain-group");
if (onchainGroup) {
const hasVisible = [
"tx-detail-block-section",
"tx-detail-nonce-section",
"tx-detail-fee-section",
"tx-detail-gasprice-section",
@@ -311,7 +300,9 @@ function populateOnChainDetails(txData) {
const el = $(id);
return el && !el.classList.contains("hidden");
});
if (hasVisible) networkWrapper.classList.remove("hidden");
if (hasVisible) {
onchainGroup.classList.remove("hidden");
}
}
// Bind copy handlers for newly added elements