fix(footer,nav): left-justify buttons, drop per-page caption bar, hide sidebar Close

Three small follow-ups to the sticky-footer rework:

- Left-justify the footer buttons (and reposition the Help popover
  to anchor at the left edge so it lines up with its trigger).
- Remove the per-page ``st.divider() + st.caption("Runs locally…")``
  trailing block from all 9 tool pages. The new sticky footer
  covers that text, so it was rendering as an empty white bar at
  the bottom of each tool page.
- Hide the Close entry from the sidebar nav via CSS. The page stays
  registered with st.navigation so /close is still routable for the
  sticky-footer Close button — only the sidebar link + its section
  header are hidden (via :has() on stNavSection).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-18 15:04:12 +00:00
parent d1b9f642e2
commit 143c775cdf
11 changed files with 25 additions and 61 deletions

View File

@@ -94,6 +94,11 @@ def _build_navigation() -> dict[str, list]:
icon="🔑", icon="🔑",
url_path="activate", url_path="activate",
) )
# Close is registered so it remains URL-routable (/close) for the
# sticky-footer Close button. It is hidden from the sidebar via CSS
# in ``hide_streamlit_chrome`` rather than being unregistered —
# ``st.navigation`` requires every routable page to be listed; pages
# not in the dict 404 even by direct URL hit.
close = st.Page( close = st.Page(
"pages/99_Close.py", "pages/99_Close.py",
title=_t("nav.close_title") or "Close", title=_t("nav.close_title") or "Close",
@@ -103,9 +108,6 @@ def _build_navigation() -> dict[str, list]:
account_header = _t("nav.section_account") or "Account" account_header = _t("nav.section_account") or "Account"
close_header = _t("nav.section_close") or "Close" close_header = _t("nav.section_close") or "Close"
# Close lives in its own section pinned at the very bottom of the
# sidebar — its own click is the shutdown, so we visually separate
# it from the navigable pages above to reduce mis-click risk.
return { return {
"": [home], "": [home],
section_label("cleaners"): by_section["cleaners"], section_label("cleaners"): by_section["cleaners"],

View File

@@ -60,6 +60,24 @@ header[data-testid="stHeader"] {
footer { footer {
display: none !important; display: none !important;
} }
/* Hide the "Close" entry from the sidebar nav — the page is kept
registered so the sticky-footer Close link can still route to
/close, but the sidebar entry is redundant and risks mis-clicks. */
[data-testid="stSidebarNav"] a[href$="/close"],
[data-testid="stSidebarNav"] a[href$="/close/"] {
display: none !important;
}
/* Hide the entire "Close" section so its header label doesn't
orphan above the hidden link. Streamlit tags each nav section
with ``data-testid="stNavSection"``; the :has() selector picks
only the one containing the close link. Modern browsers (Chrome
105+, Safari 15.4+, Firefox 121+) all support it; older
browsers fall back to showing the empty header, which is
visually harmless. */
[data-testid="stSidebarNav"] [data-testid="stNavSection"]:has(a[href$="/close"]),
[data-testid="stSidebarNav"] [data-testid="stNavSection"]:has(a[href$="/close/"]) {
display: none !important;
}
/* Reclaim top padding lost from hidden header. Slim the bottom too — /* Reclaim top padding lost from hidden header. Slim the bottom too —
Streamlit's default leaves several rems below the last widget. */ Streamlit's default leaves several rems below the last widget. */
.stAppViewBlockContainer, .stAppViewBlockContainer,
@@ -572,7 +590,7 @@ def render_sticky_footer() -> None:
z-index: 2147483646 !important; z-index: 2147483646 !important;
display: flex !important; display: flex !important;
align-items: center !important; align-items: center !important;
justify-content: flex-end !important; justify-content: flex-start !important;
gap: 0.4rem !important; gap: 0.4rem !important;
font-family: system-ui, -apple-system, sans-serif !important; font-family: system-ui, -apple-system, sans-serif !important;
box-sizing: border-box !important; box-sizing: border-box !important;
@@ -605,7 +623,7 @@ def render_sticky_footer() -> None:
} }
#datatools-help-popover { #datatools-help-popover {
position: fixed !important; position: fixed !important;
right: 0.75rem !important; left: 0.75rem !important;
bottom: 44px !important; bottom: 44px !important;
background: white !important; background: white !important;
border: 1px solid rgba(49, 51, 63, 0.25) !important; border: 1px solid rgba(49, 51, 63, 0.25) !important;

View File

@@ -402,17 +402,6 @@ else:
st.info("Upload a file to get started.") st.info("Upload a file to get started.")
# ---------------------------------------------------------------------------
# Footer
# ---------------------------------------------------------------------------
st.divider()
st.caption(
"Runs locally. Your data never leaves this computer. "
"| DataTools v3.0"
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Post-run auto-scroll # Post-run auto-scroll
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -384,8 +384,6 @@ with dl_c:
) )
st.divider()
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Post-run auto-scroll # Post-run auto-scroll

View File

@@ -654,8 +654,6 @@ with dl_c:
) )
st.divider()
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Post-run auto-scroll # Post-run auto-scroll

View File

@@ -417,8 +417,6 @@ with dl_c:
) )
st.divider()
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Post-run auto-scroll # Post-run auto-scroll

View File

@@ -461,9 +461,6 @@ with dl_c:
) )
st.divider()
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Post-run auto-scroll # Post-run auto-scroll
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -97,14 +97,3 @@ st.selectbox("Action", ["Flag only (add column)", "Remove outlier rows", "Cap /
st.divider() st.divider()
st.button("Detect Outliers", type="primary", use_container_width=True, disabled=True) st.button("Detect Outliers", type="primary", use_container_width=True, disabled=True)
# ---------------------------------------------------------------------------
# Footer
# ---------------------------------------------------------------------------
st.divider()
st.caption(
"Runs locally. Your data never leaves this computer. "
"| DataTools v3.0"
)

View File

@@ -95,14 +95,3 @@ st.checkbox("Add source filename column", value=True, disabled=True)
st.divider() st.divider()
st.button("Merge Files", type="primary", use_container_width=True, disabled=True) st.button("Merge Files", type="primary", use_container_width=True, disabled=True)
# ---------------------------------------------------------------------------
# Footer
# ---------------------------------------------------------------------------
st.divider()
st.caption(
"Runs locally. Your data never leaves this computer. "
"| DataTools v3.0"
)

View File

@@ -102,14 +102,3 @@ st.selectbox("Output format", ["Excel (flagged rows)", "PDF summary", "Both"], d
st.divider() st.divider()
st.button("Validate & Generate Report", type="primary", use_container_width=True, disabled=True) st.button("Validate & Generate Report", type="primary", use_container_width=True, disabled=True)
# ---------------------------------------------------------------------------
# Footer
# ---------------------------------------------------------------------------
st.divider()
st.caption(
"Runs locally. Your data never leaves this computer. "
"| DataTools v3.0"
)

View File

@@ -419,9 +419,6 @@ with dl_c:
) )
st.divider()
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Post-run auto-scroll # Post-run auto-scroll
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------