test(home): broader diagnostic — outline anything near viewport bottom
Previous diagnostic only outlined fixed/sticky elements; user confirmed the offending white bar isn't one of those. Cast a much wider net: - Outline every element whose visible rect intersects the bottom 200px of the viewport, regardless of position. - Border style encodes position: solid=fixed, dashed=sticky, dotted=absolute, thin=static/relative. - Render a readable list in a top-right panel showing each element's tag/id/testid/class, position, z-index, height, and background. - Skip fully transparent + un-positioned elements (those can't actually overlay anything). With this, scroll to the bottom and the panel + colored outlines will identify exactly which element is the white bar — fixed or not. The user can paste the panel list (or just name the colored box) so we know what to remove. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
129
src/gui/_home.py
129
src/gui/_home.py
@@ -310,11 +310,34 @@ def _home_page() -> None:
|
||||
"""
|
||||
<script>
|
||||
(function () {
|
||||
function outlineFixed() {
|
||||
// Cast a wide net: outline EVERY element whose visible rect lives
|
||||
// in the bottom 200px of the viewport, regardless of position type.
|
||||
// Different border styles for different position values so the user
|
||||
// can tell at a glance what kind of element each box is.
|
||||
// Also dump a readable list onto the page (top-right panel) so the
|
||||
// user can read the labels without needing devtools.
|
||||
function styleFor(pos, idx) {
|
||||
var palette = ['#e6194b', '#3cb44b', '#4363d8', '#f58231', '#911eb4',
|
||||
'#46f0f0', '#f032e6', '#bcf60c', '#fabebe', '#008080'];
|
||||
var color = palette[idx % palette.length];
|
||||
var width = '3px';
|
||||
var style = 'solid';
|
||||
if (pos === 'sticky') style = 'dashed';
|
||||
else if (pos === 'absolute') style = 'dotted';
|
||||
else if (pos === 'static' || pos === 'relative') {
|
||||
style = 'solid';
|
||||
width = '1px';
|
||||
}
|
||||
return { color: color, css: width + ' ' + style + ' ' + color };
|
||||
}
|
||||
function inspect() {
|
||||
var doc = window.parent.document;
|
||||
if (!doc) return;
|
||||
// Clear previous outlines + labels so reruns don't stack.
|
||||
doc.querySelectorAll('[data-claude-outline-label]').forEach(function (n) {
|
||||
var winp = window.parent;
|
||||
var vh = winp.innerHeight;
|
||||
var vw = winp.innerWidth;
|
||||
// Clear previous outlines + labels.
|
||||
doc.querySelectorAll('[data-claude-label]').forEach(function (n) {
|
||||
n.remove();
|
||||
});
|
||||
doc.querySelectorAll('[data-claude-outlined]').forEach(function (el) {
|
||||
@@ -322,51 +345,91 @@ def _home_page() -> None:
|
||||
el.style.outlineOffset = '';
|
||||
el.removeAttribute('data-claude-outlined');
|
||||
});
|
||||
var palette = ['#e6194b', '#3cb44b', '#4363d8', '#f58231', '#911eb4',
|
||||
'#46f0f0', '#f032e6', '#bcf60c', '#fabebe', '#008080'];
|
||||
var panel = doc.getElementById('claude-diag-panel');
|
||||
if (panel) panel.remove();
|
||||
panel = doc.createElement('div');
|
||||
panel.id = 'claude-diag-panel';
|
||||
panel.style.cssText =
|
||||
'position:fixed;top:8px;right:8px;width:420px;max-height:60vh;'
|
||||
+ 'overflow:auto;background:rgba(0,0,0,0.88);color:#fff;'
|
||||
+ 'font:11px/1.35 ui-monospace,monospace;padding:8px 10px;'
|
||||
+ 'border-radius:6px;z-index:2147483647;'
|
||||
+ 'box-shadow:0 4px 16px rgba(0,0,0,0.4);';
|
||||
panel.innerHTML =
|
||||
'<div style="font-weight:700;margin-bottom:4px;">'
|
||||
+ 'CLAUDE DIAG — elements in bottom ' + 200 + 'px of viewport '
|
||||
+ '(vh=' + vh + ')</div>'
|
||||
+ '<div style="font-size:10px;opacity:.7;margin-bottom:6px;">'
|
||||
+ 'Border styles: solid=fixed, dashed=sticky, dotted=absolute, '
|
||||
+ 'thin=static/relative</div>';
|
||||
var rows = [];
|
||||
var idx = 0;
|
||||
doc.querySelectorAll('*').forEach(function (el) {
|
||||
var cs = window.parent.getComputedStyle(el);
|
||||
if (cs.position !== 'fixed' && cs.position !== 'sticky') return;
|
||||
var seen = new Set();
|
||||
doc.querySelectorAll('body *').forEach(function (el) {
|
||||
if (seen.has(el)) return;
|
||||
var rect = el.getBoundingClientRect();
|
||||
// Skip zero-size and off-screen-only items.
|
||||
// Must intersect the bottom 200px of the viewport.
|
||||
if (rect.bottom < vh - 200 || rect.top > vh) return;
|
||||
if (rect.width < 2 || rect.height < 2) return;
|
||||
var color = palette[idx % palette.length];
|
||||
if (rect.width > vw + 50 || rect.height > vh + 50) return;
|
||||
var cs = winp.getComputedStyle(el);
|
||||
// Skip transparent backgrounds — we want to find OPAQUE
|
||||
// overlays. But keep fixed/sticky regardless, since those can
|
||||
// still cause overlay even without bg color (children paint).
|
||||
var hasOpaqueBg =
|
||||
cs.backgroundColor !== 'rgba(0, 0, 0, 0)'
|
||||
&& cs.backgroundColor !== 'transparent';
|
||||
var positioned = cs.position === 'fixed'
|
||||
|| cs.position === 'sticky' || cs.position === 'absolute';
|
||||
if (!hasOpaqueBg && !positioned) return;
|
||||
seen.add(el);
|
||||
var st = styleFor(cs.position, idx);
|
||||
idx += 1;
|
||||
el.style.outline = '3px solid ' + color;
|
||||
el.style.outline = st.css;
|
||||
el.style.outlineOffset = '-3px';
|
||||
el.setAttribute('data-claude-outlined', '1');
|
||||
// Label pinned to the element's top-left.
|
||||
var label = doc.createElement('div');
|
||||
label.setAttribute('data-claude-outline-label', '1');
|
||||
var testid = el.getAttribute('data-testid');
|
||||
var name = el.tagName.toLowerCase()
|
||||
+ (el.id ? '#' + el.id : '')
|
||||
+ (el.getAttribute('data-testid')
|
||||
? '[' + el.getAttribute('data-testid') + ']' : '')
|
||||
+ ' pos=' + cs.position
|
||||
+ (testid ? '[' + testid + ']' : '')
|
||||
+ (el.className && typeof el.className === 'string'
|
||||
? '.' + el.className.split(/\\s+/).slice(0, 2).join('.') : '');
|
||||
var summary =
|
||||
'pos=' + cs.position
|
||||
+ ' z=' + cs.zIndex
|
||||
+ ' top=' + Math.round(rect.top)
|
||||
+ ' h=' + Math.round(rect.height) + 'px'
|
||||
+ ' bg=' + cs.backgroundColor;
|
||||
label.textContent = name;
|
||||
label.style.cssText =
|
||||
rows.push(
|
||||
'<div style="margin:2px 0;padding:3px 5px;'
|
||||
+ 'border-left:4px solid ' + st.color + ';background:#111;">'
|
||||
+ '<div style="color:' + st.color + ';font-weight:700;">'
|
||||
+ name + '</div>'
|
||||
+ '<div style="opacity:.85;">' + summary + '</div></div>'
|
||||
);
|
||||
// Floating label on the element itself.
|
||||
var lbl = doc.createElement('div');
|
||||
lbl.setAttribute('data-claude-label', '1');
|
||||
lbl.textContent = name;
|
||||
lbl.style.cssText =
|
||||
'position:fixed;left:' + Math.max(0, rect.left) + 'px;'
|
||||
+ 'top:' + Math.max(0, rect.top - 18) + 'px;'
|
||||
+ 'background:' + color + ';color:#fff;'
|
||||
+ 'font:11px/1.2 ui-monospace,monospace;'
|
||||
+ 'padding:2px 5px;border-radius:3px;'
|
||||
+ 'z-index:2147483647;pointer-events:none;'
|
||||
+ 'white-space:nowrap;max-width:90vw;overflow:hidden;'
|
||||
+ 'top:' + Math.max(0, rect.top - 16) + 'px;'
|
||||
+ 'background:' + st.color + ';color:#fff;'
|
||||
+ 'font:10px/1.2 ui-monospace,monospace;'
|
||||
+ 'padding:1px 4px;border-radius:3px;'
|
||||
+ 'z-index:2147483646;pointer-events:none;'
|
||||
+ 'white-space:nowrap;max-width:60vw;overflow:hidden;'
|
||||
+ 'text-overflow:ellipsis;';
|
||||
doc.body.appendChild(label);
|
||||
doc.body.appendChild(lbl);
|
||||
});
|
||||
panel.innerHTML += rows.join('') || '<i>(nothing found)</i>';
|
||||
doc.body.appendChild(panel);
|
||||
}
|
||||
// Run after initial paint and again after Streamlit's component
|
||||
// iframes settle.
|
||||
setTimeout(outlineFixed, 400);
|
||||
setTimeout(outlineFixed, 1500);
|
||||
setTimeout(outlineFixed, 3500);
|
||||
// Re-run on scroll so labels track the current viewport state.
|
||||
setTimeout(inspect, 400);
|
||||
setTimeout(inspect, 1500);
|
||||
setTimeout(inspect, 3500);
|
||||
window.parent.addEventListener('scroll', function () {
|
||||
setTimeout(outlineFixed, 50);
|
||||
setTimeout(inspect, 80);
|
||||
}, true);
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user