fix(nav): restore real Streamlit Back-to-Home button — preserves state
Reported: after the sticky-footer href fix (be7191a) the back-to-home
click worked but the home-page upload list disappeared. Full-page
navigation via ``<a href>`` doesn't preserve ``st.session_state`` on
the user's Streamlit build.
Trade-off forced: pick visible-from-anywhere sticky footer OR state
preservation. Can't have both because ``st.switch_page`` (soft nav,
preserves state) needs a real Streamlit button widget, and Streamlit
widgets can't be reliably CSS-positioned to the viewport bottom —
Streamlit owns the widget DOM and remounts it on every rerun.
State preservation wins. Going back to the pre-sticky design:
- ``render_sticky_footer()`` becomes a no-op shim. Kept as a callable
so the call sites in every tool page don't have to be touched in
this commit; the original implementation is preserved as
``_render_sticky_footer_DISABLED`` if we ever decide to revisit.
- Every Ready/Coming-Soon tool page (1-9) gets ``back_to_home_link()``
reinstated near the top of the page (visible at scroll-top) AND
``back_to_home_link(key="_back_to_home_link_bottom")`` reinstated
near the bottom of the page (visible at scroll-bottom). Both
instances call ``st.switch_page`` via the existing helper — soft
nav, no full reload, ``st.session_state["home_uploads"]`` and
every other session-state key survive.
User trades the "always-visible while scrolling" sticky behavior for
the upload-list-survives-navigation behavior. The two-button pattern
(top + bottom) was what we had before the sticky-footer experiment;
on short pages both are visible at once, on long pages the user has
one in reach at either end.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -521,6 +521,32 @@ html_download_button = local_download_button
|
||||
|
||||
|
||||
def render_sticky_footer() -> None:
|
||||
"""No-op shim.
|
||||
|
||||
The previous implementation injected a CSS-positioned ``<a href>``
|
||||
footer into the page body. It looked nice (always-visible bar at
|
||||
the viewport bottom) but the click was a FULL-page navigation,
|
||||
which on the user's Streamlit build doesn't preserve
|
||||
``st.session_state`` — uploads disappeared after every Back to
|
||||
Home click. Soft navigation via ``st.switch_page`` requires a
|
||||
real Streamlit button widget, which we can't reliably
|
||||
CSS-position to the viewport bottom because Streamlit owns the
|
||||
widget's DOM container and remounts it on every rerun.
|
||||
|
||||
So the sticky footer is retired. Each tool page renders the
|
||||
real Streamlit-button version of ``back_to_home_link`` near the
|
||||
top AND near the bottom (the two-instance pattern from before
|
||||
the sticky-footer attempt), so the button is visible at both
|
||||
ends of the page without ever risking state loss.
|
||||
|
||||
Kept as a callable so existing tool-page imports + call sites
|
||||
don't have to be touched in this commit — they all resolve to
|
||||
this no-op.
|
||||
"""
|
||||
return
|
||||
|
||||
|
||||
def _render_sticky_footer_DISABLED() -> None:
|
||||
"""Slim fixed-position footer at the bottom of the viewport.
|
||||
|
||||
Contains a "Back to Home" link that's always visible regardless of
|
||||
|
||||
@@ -33,6 +33,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("1_Deduplicator")
|
||||
require_feature_or_render_upgrade(FeatureFlag.DEDUPLICATOR)
|
||||
@@ -405,6 +406,8 @@ else:
|
||||
# Footer
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption(
|
||||
"Runs locally. Your data never leaves this computer. "
|
||||
|
||||
@@ -35,6 +35,7 @@ from src.core.text_clean import (
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("2_Text_Cleaner")
|
||||
require_feature_or_render_upgrade(FeatureFlag.TEXT_CLEANER)
|
||||
@@ -382,6 +383,8 @@ with dl_c:
|
||||
mime="application/json",
|
||||
)
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("3_Format_Standardizer")
|
||||
require_feature_or_render_upgrade(FeatureFlag.FORMAT_STANDARDIZER)
|
||||
@@ -652,6 +653,8 @@ with dl_c:
|
||||
mime="application/json",
|
||||
)
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("4_Missing_Values")
|
||||
require_feature_or_render_upgrade(FeatureFlag.MISSING_HANDLER)
|
||||
@@ -415,6 +416,8 @@ with dl_c:
|
||||
mime="application/json",
|
||||
)
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("5_Column_Mapper")
|
||||
require_feature_or_render_upgrade(FeatureFlag.COLUMN_MAPPER)
|
||||
@@ -459,6 +460,8 @@ with dl_c:
|
||||
mime="application/json",
|
||||
)
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("6_Outlier_Detector")
|
||||
require_feature_or_render_upgrade(FeatureFlag.OUTLIER_DETECTOR)
|
||||
@@ -100,6 +101,8 @@ st.button("Detect Outliers", type="primary", use_container_width=True, disabled=
|
||||
# Footer
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption(
|
||||
"Runs locally. Your data never leaves this computer. "
|
||||
|
||||
@@ -22,6 +22,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("7_Multi_File_Merger")
|
||||
require_feature_or_render_upgrade(FeatureFlag.MULTI_FILE_MERGER)
|
||||
@@ -98,6 +99,8 @@ st.button("Merge Files", type="primary", use_container_width=True, disabled=True
|
||||
# Footer
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption(
|
||||
"Runs locally. Your data never leaves this computer. "
|
||||
|
||||
@@ -22,6 +22,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("8_Validator_Reporter")
|
||||
require_feature_or_render_upgrade(FeatureFlag.VALIDATOR_REPORTER)
|
||||
@@ -105,6 +106,8 @@ st.button("Validate & Generate Report", type="primary", use_container_width=True
|
||||
# Footer
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption(
|
||||
"Runs locally. Your data never leaves this computer. "
|
||||
|
||||
@@ -36,6 +36,7 @@ from src.license import FeatureFlag
|
||||
|
||||
hide_streamlit_chrome()
|
||||
render_sticky_footer()
|
||||
back_to_home_link()
|
||||
from src.audit import log_page_open
|
||||
log_page_open("9_Pipeline_Runner")
|
||||
require_feature_or_render_upgrade(FeatureFlag.PIPELINE_RUNNER)
|
||||
@@ -417,6 +418,8 @@ with dl_c:
|
||||
mime="application/json",
|
||||
)
|
||||
|
||||
back_to_home_link(key="_back_to_home_link_bottom")
|
||||
|
||||
st.divider()
|
||||
st.caption("Runs locally. Your data never leaves this computer. | DataTools v3.0")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user