fix(ui): bottom padding + close-screen button removed + sidebar collapse + quiet loguru
Four issues batched together since they all touch the GUI shell:
- ``stMainBlockContainer``'s ``padding-bottom`` bumped from 0.75rem
→ 4rem (~one button-height of free space above the fixed Help/Close
footer). The last line of content on a page that fills the viewport
was previously sitting flush against the footer's top border.
- Farewell overlay's "Close this window" button removed per UX
request. The auto-dismiss path is now the only flow: try
programmatic close (works in Chrome/Edge ``--app`` windows);
failing that, surface the hint and redirect the parent window to
``about:blank`` after a short timeout. Previously the user had to
click the button to get the same fallback. The
``quit.close_window_button`` i18n key is retained as a no-op for
now in case the button comes back; nothing references it.
- Sidebar collapse → expand was broken: clicking « collapsed the
sidebar but the » expand-back affordance was invisible. Two causes
pulled apart:
1. ``.dt-brand { flex: 1 }`` was eating the entire
``stSidebarHeader`` width, squeezing Streamlit's
``stSidebarCollapseButton`` off the right edge. Changed to
``margin: 0 auto 0 0`` so the brand keeps its natural width
and the chevron has room to live next to it.
2. The "hide Streamlit chrome" toolbar block was listing
``stToolbar`` and ``stToolbarActions`` for ``display: none``
— but the post-collapse re-open button
(``stExpandSidebarButton``) lives inside ``stToolbar``, so
hiding the container killed the button too. Dropped both
container testids from the hide list and kept the per-icon
rules for ``stMainMenu`` / ``stAppDeployButton`` /
``stStatusWidget`` / ``stDecoration``.
- Loguru's stderr sink quieted in GUI mode. ``src/gui/app.py`` now
runs ``logger.remove()`` + ``logger.add(sys.stderr, level="ERROR",
…)`` at the top so internal ``logger.debug`` / ``logger.warning``
breadcrumbs (e.g.
``standardize_dataframe: 7/31 cells were unparseable``) no longer
print to the terminal when the user runs ``python -m src.gui``.
CLI entry points already do the same configuration per-script.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,17 +43,17 @@ header[data-testid="stHeader"] {
|
||||
background: transparent !important;
|
||||
height: 0 !important;
|
||||
}
|
||||
/* Hide every Streamlit-shipped icon button in the header band:
|
||||
hamburger menu, deploy button, status / running indicator,
|
||||
toolbar action stacks. ``toolbarMode = "viewer"`` already suppresses
|
||||
most of these but newer Streamlit releases keep emitting them with
|
||||
tiny inline styles, so we belt-and-suspenders the visibility from
|
||||
CSS too. */
|
||||
/* Hide the noisy Streamlit-shipped icon buttons in the header band
|
||||
(hamburger menu, deploy button, status / running indicator). We
|
||||
deliberately do NOT hide ``stToolbar`` or ``stToolbarActions`` as
|
||||
containers — those wrap ``stExpandSidebarButton`` which is the
|
||||
ONLY path back to an expanded sidebar after the user collapses it.
|
||||
``toolbarMode = "viewer"`` already suppresses most of these icons;
|
||||
the CSS belt-and-suspenders the visibility for newer Streamlit
|
||||
releases that keep emitting them with inline styles. */
|
||||
#MainMenu,
|
||||
[data-testid="stMainMenu"],
|
||||
[data-testid="stAppDeployButton"],
|
||||
[data-testid="stToolbar"],
|
||||
[data-testid="stToolbarActions"],
|
||||
[data-testid="stStatusWidget"],
|
||||
[data-testid="stDecoration"] {
|
||||
display: none !important;
|
||||
@@ -104,7 +104,11 @@ footer {
|
||||
.stMainBlockContainer,
|
||||
[data-testid="stMainBlockContainer"] {
|
||||
padding-top: 0.5rem !important;
|
||||
padding-bottom: 0.75rem !important;
|
||||
/* +4rem buys a comfortable read of the last line of content on a
|
||||
page that fills the viewport: the fixed Help/Close footer is
|
||||
~36px (≈2.25rem) tall and we want at least a button-height of
|
||||
free space between the last widget and the footer's top edge. */
|
||||
padding-bottom: 4rem !important;
|
||||
}
|
||||
/* Scale content to fit app window */
|
||||
.stApp {
|
||||
@@ -192,14 +196,32 @@ body, .stApp {
|
||||
text. Injected into ``[data-testid="stSidebarHeader"]`` by the JS
|
||||
below; ``stLogoSpacer`` is hidden so the brand block takes its
|
||||
place flush against the left edge of the sidebar header. */
|
||||
/* The brand sits next to Streamlit's sidebar collapse button inside
|
||||
``stSidebarHeader``. ``flex: 1`` would steal all the horizontal
|
||||
space and squash the collapse chevron out of view — once collapsed
|
||||
the user would have no way to reopen the sidebar. Keep the brand
|
||||
at its natural width and let the header's flex layout leave room
|
||||
for the chevron on the right. */
|
||||
.dt-brand {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 0 0 0 4px;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
margin: 0 auto 0 0;
|
||||
}
|
||||
/* Belt-and-suspenders: keep the in-sidebar collapse button + the
|
||||
out-of-sidebar collapsed control reachable. The latter is what
|
||||
appears on the page edge once the sidebar slides shut. */
|
||||
[data-testid="stSidebarCollapseButton"],
|
||||
[data-testid="stSidebarCollapseButton"] button {
|
||||
display: inline-flex !important;
|
||||
visibility: visible !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
[data-testid="stSidebarCollapsedControl"] {
|
||||
display: flex !important;
|
||||
visibility: visible !important;
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
/* "Letter D (sans)" wordmark per Business/DataTools/app_icons.html
|
||||
§03: 28px ink-filled rounded square, cream "D" in Geist 700 with
|
||||
@@ -1274,12 +1296,7 @@ _FAREWELL_SCRIPT_TEMPLATE = """
|
||||
'border-radius:12px;background:#161922;max-width:480px;">' +
|
||||
'<h1 style="margin:0 0 8px 0;font-weight:600;letter-spacing:-0.01em;">' +
|
||||
'__TITLE__</h1>' +
|
||||
'<p style="opacity:0.7;margin:0 0 20px 0;">__SUBTITLE__</p>' +
|
||||
'<button id="datatools-close-btn" style="' +
|
||||
'background:#6ee7b7;color:#052e1a;font-weight:600;' +
|
||||
'padding:10px 20px;border-radius:8px;border:none;' +
|
||||
'font-size:15px;cursor:pointer;font-family:inherit;">' +
|
||||
'__CLOSE_BTN__</button>' +
|
||||
'<p style="opacity:0.7;margin:0;">__SUBTITLE__</p>' +
|
||||
'<p id="datatools-close-hint" style="' +
|
||||
'display:none;font-size:13px;opacity:0.6;margin:14px 0 0 0;">' +
|
||||
'__CLOSE_HINT__</p>' +
|
||||
@@ -1310,21 +1327,21 @@ _FAREWELL_SCRIPT_TEMPLATE = """
|
||||
// push to history.
|
||||
try { win.location.replace('about:blank'); } catch (e) {}
|
||||
}
|
||||
function wireClose(doc, win) {
|
||||
var btn = doc.getElementById('datatools-close-btn');
|
||||
if (!btn) return;
|
||||
btn.onclick = function () {
|
||||
var standalone = isStandalone(win);
|
||||
if (tryClose(win)) return;
|
||||
// Close failed (or definitely will fail in a regular tab).
|
||||
// Surface the hint immediately, then redirect to about:blank
|
||||
// after a short delay so the user has a moment to read why.
|
||||
var hint = doc.getElementById('datatools-close-hint');
|
||||
if (hint) hint.style.display = 'block';
|
||||
setTimeout(function () {
|
||||
if (!win.closed) fallbackToBlank(win);
|
||||
}, standalone ? 250 : 1500);
|
||||
};
|
||||
function autoDismiss(doc, win) {
|
||||
// Try the programmatic close first — succeeds in Chrome/Edge
|
||||
// --app windows. If it fails (regular browser tab), surface the
|
||||
// hint and auto-redirect to about:blank so the user lands on a
|
||||
// clean page instead of the frozen farewell overlay. The "Close
|
||||
// this window" button used to drive the same flow on click; we
|
||||
// dropped that affordance per UX request, so this auto-timer is
|
||||
// the only path on regular tabs.
|
||||
var standalone = isStandalone(win);
|
||||
if (tryClose(win)) return;
|
||||
var hint = doc.getElementById('datatools-close-hint');
|
||||
if (hint) hint.style.display = 'block';
|
||||
setTimeout(function () {
|
||||
if (!win.closed) fallbackToBlank(win);
|
||||
}, standalone ? 400 : 2500);
|
||||
}
|
||||
try {
|
||||
var doc = window.top.document;
|
||||
@@ -1332,17 +1349,12 @@ _FAREWELL_SCRIPT_TEMPLATE = """
|
||||
if (!doc.getElementById('datatools-farewell-overlay')) {
|
||||
doc.body.appendChild(buildOverlay(doc));
|
||||
}
|
||||
wireClose(doc, win);
|
||||
// Auto-close attempt on first paint — succeeds in Chrome --app
|
||||
// windows, fails silently on regular tabs (and we don't redirect
|
||||
// automatically here; the manual button drives that path so the
|
||||
// user is in control).
|
||||
tryClose(win);
|
||||
autoDismiss(doc, win);
|
||||
} catch (e) {
|
||||
// Cross-origin access denied (shouldn't happen given Streamlit's
|
||||
// sandbox flags, but fall back gracefully): cover this iframe.
|
||||
document.body.appendChild(buildOverlay(document));
|
||||
wireClose(document, window);
|
||||
autoDismiss(document, window);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user