fix(footer): tighten block-container `padding-bottom` to close white gap
Diagnostics confirmed the "white bar" the user has been describing is not a separate element — it's ``[data-testid=stApp]``'s solid white background (``rgb(255,255,255)``, viewport-locked) showing through the gap between where page content ends and where the fixed Help/Close footer overlay begins. ``stApp`` stays put while content scrolls inside it, which is why the bar "doesn't change when scrolling". The gap exists because ``render_sticky_footer`` overrides the block container's ``padding-bottom`` to ``3rem`` (48px) to reserve clear room for the fixed footer. The footer is only ~32-33px tall (min- height 32px + 0.25rem top/bottom padding), so ~16px of that reserve was pure visible white space sitting above the buttons. Reduce ``padding-bottom`` to ``2rem`` (~32px) — just enough to prevent content from rendering under the footer overlay, no more. Eliminates the visible gap without exposing text to clipping. Also remove the diagnostic banner + click-to-inspect iframe from the home page now that the bar is identified. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
160
src/gui/_home.py
160
src/gui/_home.py
@@ -288,163 +288,3 @@ def _home_page() -> None:
|
||||
header=f"📄 {name}",
|
||||
key_namespace=name,
|
||||
)
|
||||
|
||||
# TEMP: end-of-content marker — confirmed at the true bottom of
|
||||
# the home page's main content. The user reports content scrolls
|
||||
# *behind* the offending white bar, so the bar is fixed-positioned.
|
||||
# Only ``#datatools-sticky-footer`` is fixed at the bottom per
|
||||
# our CSS, but the user already confirmed the sticky footer is
|
||||
# NOT the offending bar. So there's a fixed element we haven't
|
||||
# accounted for. The JS below outlines EVERY fixed/sticky element
|
||||
# in the parent document with a labelled colored border so we can
|
||||
# see exactly what's overlaying scrolled content.
|
||||
st.markdown(
|
||||
'<div style="background:#ffe0e0;border:2px dashed #b00020;'
|
||||
'color:#b00020;font-weight:700;font-size:13px;text-align:center;'
|
||||
'padding:8px 12px;margin:4px 0;font-family:system-ui,sans-serif;">'
|
||||
'◀ CLAUDE TEST #3 — END OF MAIN CONTENT ▶'
|
||||
'</div>',
|
||||
unsafe_allow_html=True,
|
||||
)
|
||||
st.iframe(
|
||||
"""
|
||||
<script>
|
||||
(function () {
|
||||
// CLICK-TO-INSPECT: a single button enters inspect mode. The next
|
||||
// click anywhere on the page reports the full element stack at
|
||||
// that point — including elements inside same-origin iframes
|
||||
// (which earlier diagnostics couldn't reach with a flat walker).
|
||||
// No clutter outside the button + the report panel; nothing
|
||||
// re-runs on scroll.
|
||||
function init() {
|
||||
var doc = window.parent.document;
|
||||
var winp = window.parent;
|
||||
if (!doc || !doc.body) { setTimeout(init, 300); return; }
|
||||
// Clear any earlier diagnostic chrome.
|
||||
['claude-diag-panel', 'claude-inspect-btn', 'claude-inspect-report']
|
||||
.forEach(function (id) {
|
||||
var prev = doc.getElementById(id);
|
||||
if (prev) prev.remove();
|
||||
});
|
||||
doc.querySelectorAll('[data-claude-label]').forEach(function (n) {
|
||||
n.remove();
|
||||
});
|
||||
doc.querySelectorAll('[data-claude-outlined]').forEach(function (el) {
|
||||
el.style.outline = '';
|
||||
el.style.outlineOffset = '';
|
||||
el.removeAttribute('data-claude-outlined');
|
||||
});
|
||||
|
||||
var btn = doc.createElement('button');
|
||||
btn.id = 'claude-inspect-btn';
|
||||
btn.type = 'button';
|
||||
btn.textContent = 'CLAUDE: click here, then click the white bar';
|
||||
btn.style.cssText =
|
||||
'position:fixed;top:8px;right:8px;z-index:2147483647;'
|
||||
+ 'background:#b00020;color:#fff;font:13px/1.2 system-ui,sans-serif;'
|
||||
+ 'font-weight:700;padding:8px 14px;border:none;border-radius:6px;'
|
||||
+ 'cursor:pointer;box-shadow:0 4px 14px rgba(0,0,0,0.35);';
|
||||
doc.body.appendChild(btn);
|
||||
|
||||
function describe(el) {
|
||||
if (!el || !el.tagName) return '?';
|
||||
var testid = el.getAttribute && el.getAttribute('data-testid');
|
||||
var cls = (el.className && typeof el.className === 'string')
|
||||
? el.className.split(/\\s+/).slice(0, 3).join('.') : '';
|
||||
var cs = (el.ownerDocument.defaultView || winp)
|
||||
.getComputedStyle(el);
|
||||
var rect = el.getBoundingClientRect();
|
||||
return el.tagName.toLowerCase()
|
||||
+ (el.id ? '#' + el.id : '')
|
||||
+ (testid ? '[testid=' + testid + ']' : '')
|
||||
+ (cls ? '.' + cls : '')
|
||||
+ ' { pos=' + cs.position
|
||||
+ ', z=' + cs.zIndex
|
||||
+ ', bg=' + cs.backgroundColor
|
||||
+ ', rect=(' + Math.round(rect.left) + ','
|
||||
+ Math.round(rect.top) + ' '
|
||||
+ Math.round(rect.width) + 'x'
|
||||
+ Math.round(rect.height) + ') }';
|
||||
}
|
||||
|
||||
function showReport(stack, x, y, frameLabel) {
|
||||
var prev = doc.getElementById('claude-inspect-report');
|
||||
if (prev) prev.remove();
|
||||
var panel = doc.createElement('div');
|
||||
panel.id = 'claude-inspect-report';
|
||||
panel.style.cssText =
|
||||
'position:fixed;top:8px;left:8px;right:8px;max-height:60vh;'
|
||||
+ 'overflow:auto;background:rgba(0,0,0,0.92);color:#fff;'
|
||||
+ 'font:12px/1.4 ui-monospace,monospace;padding:10px 12px;'
|
||||
+ 'border-radius:6px;z-index:2147483647;'
|
||||
+ 'box-shadow:0 4px 18px rgba(0,0,0,0.5);';
|
||||
var html =
|
||||
'<div style="font-weight:700;color:#ffb;margin-bottom:6px;">'
|
||||
+ 'CLICKED AT (' + x + ',' + y + ') — ' + frameLabel + '</div>';
|
||||
stack.forEach(function (el, i) {
|
||||
html += '<div style="margin:3px 0;padding:3px 6px;'
|
||||
+ 'background:' + (i === 0 ? '#3a0010' : '#111')
|
||||
+ ';border-left:3px solid '
|
||||
+ (i === 0 ? '#ff4060' : '#555') + ';">'
|
||||
+ (i === 0 ? '<b>TOP: </b>' : ('[' + i + '] '))
|
||||
+ describe(el) + '</div>';
|
||||
});
|
||||
html += '<button onclick="this.parentElement.remove()" '
|
||||
+ 'style="margin-top:8px;background:#444;color:#fff;'
|
||||
+ 'border:none;padding:4px 10px;border-radius:4px;'
|
||||
+ 'cursor:pointer;">close</button>';
|
||||
panel.innerHTML = html;
|
||||
doc.body.appendChild(panel);
|
||||
}
|
||||
|
||||
function pickFromPoint(targetDoc, x, y, label, depth) {
|
||||
depth = depth || 0;
|
||||
var stack = (targetDoc.elementsFromPoint
|
||||
? targetDoc.elementsFromPoint(x, y) : []);
|
||||
// Recurse into any same-origin iframe at the click point.
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var el = stack[i];
|
||||
if (el && el.tagName === 'IFRAME' && depth < 3) {
|
||||
try {
|
||||
var inner = el.contentDocument;
|
||||
if (inner) {
|
||||
var r = el.getBoundingClientRect();
|
||||
var innerStack = pickFromPoint(inner,
|
||||
x - r.left, y - r.top,
|
||||
label + ' > IFRAME(' + (el.src || 'srcdoc') + ')',
|
||||
depth + 1);
|
||||
if (innerStack && innerStack.length) {
|
||||
return innerStack.concat(stack);
|
||||
}
|
||||
}
|
||||
} catch (e) { /* cross-origin */ }
|
||||
}
|
||||
}
|
||||
// Tag the frame label onto the returned stack via showReport.
|
||||
showReport(stack, x, y, label);
|
||||
return stack;
|
||||
}
|
||||
|
||||
btn.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
btn.textContent = 'click the white bar now…';
|
||||
btn.style.background = '#0a8';
|
||||
function onPick(ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
doc.removeEventListener('click', onPick, true);
|
||||
btn.textContent = 'CLAUDE: click here, then click the white bar';
|
||||
btn.style.background = '#b00020';
|
||||
pickFromPoint(doc, ev.clientX, ev.clientY, 'parent doc', 0);
|
||||
}
|
||||
setTimeout(function () {
|
||||
doc.addEventListener('click', onPick, true);
|
||||
}, 50);
|
||||
});
|
||||
}
|
||||
init();
|
||||
})();
|
||||
</script>
|
||||
""",
|
||||
height=1,
|
||||
)
|
||||
|
||||
@@ -629,7 +629,12 @@ def render_sticky_footer() -> None:
|
||||
"""
|
||||
<style>
|
||||
[data-testid="stAppViewBlockContainer"] {
|
||||
padding-bottom: 3rem !important;
|
||||
/* Reserve just enough room for the fixed footer overlay (min-height
|
||||
32px + 0.25rem * 2 padding ≈ 2rem). Anything larger leaves a
|
||||
visible white gap above the footer that the user sees as a
|
||||
"white bar" between content and the Help/Close row — actually
|
||||
just ``.stApp``'s solid-white background showing through. */
|
||||
padding-bottom: 2rem !important;
|
||||
}
|
||||
#datatools-sticky-footer {
|
||||
position: fixed !important;
|
||||
|
||||
Reference in New Issue
Block a user