fix(nav): switch_page resolves correctly + bottom-of-page back link
Two issues, same fix surface.
(1) Reported crash on Back-to-Home:
StreamlitAPIException: Could not find page: app.py.
``st.switch_page("app.py")`` doesn't work under ``st.navigation`` —
the entry script is the nav manager itself and is not a registered
page. The fix needs to pass an ``st.Page`` object whose script
identity matches one registered in the nav.
First-pass attempt (``from src.gui.app import _home_page``) hit a
worse failure: importing ``app.py`` from inside a tool-page render
re-executes the nav setup with the WRONG "main script" context, so
every ``st.Page("pages/N_foo.py", ...)`` call in ``_build_navigation``
fails with "file could not be found".
Extract the home renderer into its own module ``src/gui/_home.py``
which has no top-level Streamlit side effects. Both the nav manager
and the back-link helper import ``_home_page`` from there. The Page
object built at click time has the same callable identity as the one
registered, so ``st.switch_page`` resolves it.
(2) Reported UX: the back button scrolled out of view on long pages.
Add a second ``back_to_home_link(key="_back_to_home_link_bottom")``
call near the footer of every tool page (1-9). The unique key avoids
widget-id collision with the top instance. Coming-Soon stubs get it
unconditionally; Ready tools render it only after a result exists
because the page short-circuits with ``st.stop()`` before then —
when no result is on screen the page is short enough that the top
link is sufficient.
2220 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -410,22 +410,33 @@ html_download_button = local_download_button
|
||||
|
||||
|
||||
def back_to_home_link(*, key: str = "_back_to_home_link") -> None:
|
||||
"""Render a small "← Back to Home" affordance near the top of a tool page.
|
||||
"""Render a "← Back to Home" affordance on a tool page.
|
||||
|
||||
Tool pages reached from the home findings panel benefit from an
|
||||
explicit return-to-home control so a user working through findings
|
||||
on multiple uploaded files can hop between files without hunting
|
||||
through the sidebar.
|
||||
through the sidebar. Call this twice on each tool page — once
|
||||
near the top (default key) and once at the bottom with
|
||||
``key="_back_to_home_link_bottom"`` so the control stays reachable
|
||||
after the user scrolls through long results.
|
||||
|
||||
Implementation note: ``st.switch_page("app.py")`` routes back to the
|
||||
entry script which, under ``st.navigation``, lands on the default
|
||||
page (Home). Streamlit's button is used (rather than ``st.page_link``)
|
||||
because the entry script is a navigation manager, not a registered
|
||||
Page object, and ``page_link`` to ``app.py`` renders inconsistently
|
||||
across Streamlit minor versions.
|
||||
Implementation: ``st.switch_page`` under ``st.navigation`` requires
|
||||
either a file path to a page in ``pages/`` or a ``StreamlitPage``
|
||||
object whose script identity matches one registered in the nav.
|
||||
The entry script ``app.py`` is the nav manager itself — it cannot
|
||||
be switched-to by filename. So we import the home callable from
|
||||
``src.gui.app`` and rebuild the same ``st.Page`` registration here.
|
||||
Streamlit identifies pages by the underlying callable's qualified
|
||||
name, so a freshly-constructed Page resolves to the registered one.
|
||||
"""
|
||||
if st.button(_t("nav.back_to_home"), key=key, type="secondary"):
|
||||
st.switch_page("app.py")
|
||||
# Import from the renderer module (not from app.py — importing
|
||||
# app.py would re-execute its navigation setup with the wrong
|
||||
# "main script" context and blow up the pages/ path resolution).
|
||||
from src.gui._home import _home_page
|
||||
st.switch_page(
|
||||
st.Page(_home_page, title="Home", icon="🧹", url_path="home"),
|
||||
)
|
||||
|
||||
|
||||
def shutdown_app() -> None:
|
||||
|
||||
Reference in New Issue
Block a user