fix(nav,footer): drop orphan _hidden section header, show footer on Activate
Two follow-ups to the prior sidebar/footer cleanup: - The "_hidden" section header was still visible in the sidebar because Streamlit renders ``stNavSectionHeader`` as a sibling of ``stNavSection``, not a child — so the ``:has()`` rule on the section was hiding the items list but leaving the header (and its collapse/drilldown marker) behind. Move Activate + Close into the unlabeled section (key ``""``) alongside Home so there is no header to leak in the first place, then hide just the two links via ``stSidebarNavLinkContainer:has(...)`` (with a defensive ``a[href$=...]`` fallback for browsers without ``:has()`` support). - The sticky footer was missing on ``pages/_Activate.py`` because the page never called ``render_sticky_footer`` — added the call so the Help / Close bar persists when the user follows the popover's Activate / Manage link. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -109,13 +109,16 @@ def _build_navigation() -> dict[str, list]:
|
||||
url_path="close",
|
||||
)
|
||||
|
||||
# Activate + Close are placed in the unlabeled section alongside
|
||||
# Home (key ``""`` — Streamlit renders no header for it). The CSS
|
||||
# in ``hide_streamlit_chrome`` then hides just their two links by
|
||||
# ``href``, leaving Home visible and no orphan section header /
|
||||
# drilldown marker in the sidebar.
|
||||
return {
|
||||
"": [home],
|
||||
"": [home, activate, close],
|
||||
section_label("cleaners"): by_section["cleaners"],
|
||||
section_label("transformations"): by_section["transformations"],
|
||||
section_label("automations"): by_section["automations"],
|
||||
# Hidden section — see comment above + CSS in hide_streamlit_chrome.
|
||||
"_hidden": [activate, close],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,29 +60,29 @@ header[data-testid="stHeader"] {
|
||||
footer {
|
||||
display: none !important;
|
||||
}
|
||||
/* Hide the Activate + Close entries from the sidebar nav — both
|
||||
/* Hide the Activate + Close entries from the sidebar nav. Both
|
||||
pages stay registered (so /activate and /close remain
|
||||
URL-routable) but are reached from the sticky-footer Help
|
||||
popover instead of the sidebar. */
|
||||
popover instead of the sidebar. They are grouped under the
|
||||
unlabeled section alongside Home in ``app.py`` so hiding the
|
||||
two links here leaves no orphan section header behind. We
|
||||
target the LinkContainer (Streamlit's per-entry wrapper) so the
|
||||
list item collapses, not just the inner anchor — otherwise the
|
||||
container's spacing would still occupy a row. */
|
||||
[data-testid="stSidebarNav"] [data-testid="stSidebarNavLinkContainer"]:has(a[href$="/activate"]),
|
||||
[data-testid="stSidebarNav"] [data-testid="stSidebarNavLinkContainer"]:has(a[href$="/activate/"]),
|
||||
[data-testid="stSidebarNav"] [data-testid="stSidebarNavLinkContainer"]:has(a[href$="/close"]),
|
||||
[data-testid="stSidebarNav"] [data-testid="stSidebarNavLinkContainer"]:has(a[href$="/close/"]) {
|
||||
display: none !important;
|
||||
}
|
||||
/* Defensive fallback for browsers without :has() support — at
|
||||
least hide the anchor itself so the entry isn't clickable. */
|
||||
[data-testid="stSidebarNav"] a[href$="/activate"],
|
||||
[data-testid="stSidebarNav"] a[href$="/activate/"],
|
||||
[data-testid="stSidebarNav"] a[href$="/close"],
|
||||
[data-testid="stSidebarNav"] a[href$="/close/"] {
|
||||
display: none !important;
|
||||
}
|
||||
/* Hide the section header that wraps those entries so no orphan
|
||||
label is left above the hidden links. Streamlit tags each nav
|
||||
section with ``data-testid="stNavSection"``; the :has() selector
|
||||
picks only the one(s) containing those links. Modern browsers
|
||||
(Chrome 105+, Safari 15.4+, Firefox 121+) all support :has();
|
||||
older browsers fall back to showing the section header, which
|
||||
is visually harmless. */
|
||||
[data-testid="stSidebarNav"] [data-testid="stNavSection"]:has(a[href$="/activate"]),
|
||||
[data-testid="stSidebarNav"] [data-testid="stNavSection"]:has(a[href$="/activate/"]),
|
||||
[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 —
|
||||
Streamlit's default leaves several rems below the last widget. */
|
||||
.stAppViewBlockContainer,
|
||||
|
||||
@@ -19,7 +19,11 @@ _project_root = Path(__file__).resolve().parent.parent.parent.parent
|
||||
if str(_project_root) not in sys.path:
|
||||
sys.path.insert(0, str(_project_root))
|
||||
|
||||
from src.gui.components import hide_streamlit_chrome, render_activation_form
|
||||
from src.gui.components import (
|
||||
hide_streamlit_chrome,
|
||||
render_activation_form,
|
||||
render_sticky_footer,
|
||||
)
|
||||
from src.i18n import t
|
||||
|
||||
st.set_page_config(
|
||||
@@ -31,4 +35,5 @@ st.set_page_config(
|
||||
# ``gate_license=False`` keeps the chrome from re-rendering the
|
||||
# activation form on top of the form we're about to render below.
|
||||
hide_streamlit_chrome(gate_license=False)
|
||||
render_sticky_footer()
|
||||
render_activation_form(key_prefix="page")
|
||||
|
||||
Reference in New Issue
Block a user