From 16d7b9f942d05cd363dd3196ae6e543455375a4f Mon Sep 17 00:00:00 2001 From: Nathan Woodburn Date: Thu, 20 Nov 2025 23:53:43 +1100 Subject: [PATCH] feat: Add scroll when viewing a mempool tx --- templates/assets/css/index.css | 42 +++++++++++++++++++++++++++++++++- templates/index.html | 40 ++++++++++++++++++++++++++++---- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/templates/assets/css/index.css b/templates/assets/css/index.css index 45aa7a4..dfb0f4a 100644 --- a/templates/assets/css/index.css +++ b/templates/assets/css/index.css @@ -89,6 +89,10 @@ main { padding: 2rem 0; } +section { + scroll-margin-top: 140px; +} + /* Cards */ .card { background: var(--card-bg); @@ -255,12 +259,16 @@ main { border: 1px solid var(--card-border); border-radius: 8px; margin-bottom: 0.75rem; - transition: border-color 0.2s ease; + transition: all 0.2s ease; animation: staggerFade 0.4s ease forwards; + cursor: pointer; } .tx-item:hover { border-color: rgba(139, 92, 246, 0.3); + background: rgba(139, 92, 246, 0.05); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .tx-hash { @@ -708,6 +716,38 @@ a:hover { font-style: italic; } +/* Loading Spinner */ +.loading-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 3rem; + color: var(--text-secondary); + animation: fadeIn 0.3s ease; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid rgba(139, 92, 246, 0.1); + border-radius: 50%; + border-top-color: var(--accent-color); + animation: spin 1s cubic-bezier(0.4, 0, 0.2, 1) infinite; + margin-bottom: 1rem; +} + +.loading-text { + font-size: 0.9rem; + font-weight: 500; + letter-spacing: 0.05em; + animation: pulse 1.5s ease-in-out infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + /* New Animations */ @keyframes slideUp { from { diff --git a/templates/index.html b/templates/index.html index d738afa..341b7e2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -236,7 +236,6 @@ document.getElementById('tx-input').value = txId; document.querySelector('[data-tab="tx"]').click(); searchTx(); - document.querySelector('.search-section').scrollIntoView({ behavior: 'smooth' }); } // Format mempool data nicely @@ -254,9 +253,8 @@
${mempool.map(txId => ` -
+
${txId} -
`).join('')}
@@ -924,6 +922,18 @@ } } + // Show loading animation + function showLoading(elementId) { + const element = document.getElementById(elementId); + element.style.display = 'block'; + element.innerHTML = ` +
+
+
Searching Fire...
+
+ `; + } + // Load status on page load async function loadStatus() { const chainStatus = await apiCall('chain'); @@ -948,6 +958,8 @@ alert('Please enter a block height or hash'); return; } + + showLoading('block-result'); updateURL('block', blockId); const data = await apiCall(`block/${blockId}`); @@ -966,6 +978,8 @@ alert('Please enter a block height or hash'); return; } + + showLoading('block-result'); updateURL('header', blockId); const data = await apiCall(`header/${blockId}`); @@ -984,11 +998,17 @@ alert('Please enter a transaction ID'); return; } + + const resultElement = document.getElementById('tx-result'); + showLoading('tx-result'); + + // Scroll to the search section + document.querySelector('.search-section').scrollIntoView({ behavior: 'smooth', block: 'start' }); + updateURL('tx', txId); const data = await apiCall(`tx/${txId}`); // Use formatted display instead of raw JSON - const resultElement = document.getElementById('tx-result'); if (data.error) { resultElement.innerHTML = `
Error: ${data.error}
`; } else { @@ -1002,6 +1022,8 @@ alert('Please enter an address'); return; } + + showLoading('address-result'); updateURL('address', address); const data = await apiCall(`tx/address/${address}`); @@ -1020,6 +1042,8 @@ alert('Please enter an address'); return; } + + showLoading('address-result'); updateURL('address', address); const data = await apiCall(`coin/address/${address}`); @@ -1038,6 +1062,8 @@ alert('Please enter a name'); return; } + + showLoading('name-result'); const punyName = toPunycode(name); updateURL('name', punyName); const data = await apiCall(`name/${punyName}`); @@ -1057,6 +1083,8 @@ alert('Please enter a name'); return; } + + showLoading('name-result'); const punyName = toPunycode(name); const data = await apiCall(`nameresource/${punyName}`); @@ -1075,6 +1103,8 @@ alert('Please enter a name'); return; } + + showLoading('name-result'); const punyName = toPunycode(name); const data = await apiCall(`namesummary/${punyName}`); @@ -1093,6 +1123,8 @@ alert('Please enter a name hash'); return; } + + showLoading('name-result'); const data = await apiCall(`namehash/${nameHash}`); // Check if result is valid and redirect to name page