From d840230e48e8ddc09e256d734a5c1f221cb4d996 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 18 May 2026 15:39:14 +0000 Subject: [PATCH] fix(nav,footer): hide Activate from sidebar, surface it in Help popover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Collapse the Account section: Activate now lives in the same hidden sidebar section as Close (single ``_hidden`` group). Both pages stay registered with ``st.navigation`` so /activate and /close remain URL-routable for the Help-popover / Close-button links — only the sidebar entries + their section header are hidden via CSS. - Help popover always exposes a license-management link now: ``Activate now →`` when the license is inactive, ``Manage license →`` when it is active and valid. Both point at ``./activate``. - Extend the sidebar-hide CSS to also match ``a[href$="/activate"]`` and the section that contains it. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/gui/app.py | 19 ++++++++++--------- src/gui/components/_legacy.py | 28 ++++++++++++++++++---------- src/i18n/packs/en.json | 1 + src/i18n/packs/es.json | 1 + 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/gui/app.py b/src/gui/app.py index 157d59f..0270ddc 100644 --- a/src/gui/app.py +++ b/src/gui/app.py @@ -88,17 +88,20 @@ def _build_navigation() -> dict[str, list]: default=True, url_path="home", ) + # Activate + Close are both reached from the sticky-footer Help + # popover (Activate / Manage-license link and Close button). They + # are registered with ``st.navigation`` so ``/activate`` and + # ``/close`` remain URL-routable — pages not listed in the dict + # 404 even by direct hit — but their sidebar entries are hidden + # via CSS in ``hide_streamlit_chrome``. We group them under a + # single section header that is also hidden by that same CSS rule + # so no orphan "Account" / "Close" label is left in the sidebar. activate = st.Page( "pages/_Activate.py", title=_t("nav.activate_title") or "Activate", icon="🔑", 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( "pages/99_Close.py", title=_t("nav.close_title") or "Close", @@ -106,15 +109,13 @@ def _build_navigation() -> dict[str, list]: url_path="close", ) - account_header = _t("nav.section_account") or "Account" - close_header = _t("nav.section_close") or "Close" return { "": [home], section_label("cleaners"): by_section["cleaners"], section_label("transformations"): by_section["transformations"], section_label("automations"): by_section["automations"], - account_header: [activate], - close_header: [close], + # Hidden section — see comment above + CSS in hide_streamlit_chrome. + "_hidden": [activate, close], } diff --git a/src/gui/components/_legacy.py b/src/gui/components/_legacy.py index 218ba87..5e3214a 100644 --- a/src/gui/components/_legacy.py +++ b/src/gui/components/_legacy.py @@ -60,20 +60,25 @@ header[data-testid="stHeader"] { footer { 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. */ +/* 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. */ +[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 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. */ +/* 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; @@ -593,11 +598,14 @@ def render_sticky_footer() -> None: date=(state.expires_at or "")[:10], days=state.days_remaining, ) + manage_link = _html.escape(_t("footer.help_manage_link")) license_html = ( f'
' f'{license_label}: {_html.escape(active_line)}
' f'
' f'{_html.escape(expires_line)}
' + f'' ) else: inactive_line = _html.escape(_t("footer.help_license_inactive")) diff --git a/src/i18n/packs/en.json b/src/i18n/packs/en.json index b7afe81..3820b40 100644 --- a/src/i18n/packs/en.json +++ b/src/i18n/packs/en.json @@ -183,6 +183,7 @@ "help_license_active": "{name}", "help_license_expires": "Expires {date} ({days} days)", "help_activate_link": "Activate now →", + "help_manage_link": "Manage license →", "help_dismiss": "Close" } } diff --git a/src/i18n/packs/es.json b/src/i18n/packs/es.json index 6213739..551d435 100644 --- a/src/i18n/packs/es.json +++ b/src/i18n/packs/es.json @@ -183,6 +183,7 @@ "help_license_active": "{name}", "help_license_expires": "Caduca {date} ({days} días)", "help_activate_link": "Activar ahora →", + "help_manage_link": "Gestionar licencia →", "help_dismiss": "Cerrar" } }