feat(gui): inline Help popover next to every tool's title

Adds a contextual Help button on each detail page, right of the title.
Clicking it opens a Streamlit popover with a one-shot how-to: when to
use, numbered steps, before→after examples, and an optional one-line
tip. Designed to be scannable — no paragraph prose.

Implementation:
- New ``render_tool_header(tool_id)`` helper in components replaces the
  bare ``st.title(...) + st.caption(...)`` block on each of the 11 tool
  pages. Title in the wide column, popover in a narrow right column;
  caption sits on its own line beneath.
- Help content is one markdown blob per tool stored in i18n under
  ``tools.<id>.help_md`` (en + es). Editors can tweak copy without
  touching Python.
- ``help.button_label`` and ``help.missing_body`` keys added to both
  packs for the popover trigger and the empty-tool fallback.

All 11 tool pages now use the same header pattern — including the
PDF Extractor and Reconciler which previously had hardcoded title/
caption pairs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-02 17:21:47 +00:00
parent 7203a81af7
commit 904356f4e8
15 changed files with 119 additions and 49 deletions

View File

@@ -48,6 +48,7 @@ __all__ = [
# Shared chrome / pickup
"back_to_home_link",
"render_sticky_footer",
"render_tool_header",
"hide_streamlit_chrome",
"html_download_button",
"local_download_button",

View File

@@ -2042,6 +2042,40 @@ a[data-testid="stPageLink-NavLink"][href*="close"] {
)
def render_tool_header(tool_id: str) -> None:
"""Title row with an inline Help popover anchored to the right.
Replaces the bare ``st.title(...)`` + ``st.caption(...)`` block on
each tool page. Help content is one markdown blob per tool in the
i18n pack (``tools.<id>.help_md``) so editors can tweak copy without
touching Python. The popover is anchored next to the title rather
than the caption so it reads as part of the page header.
Layout: ``[title | help button]`` over ``[caption]``. The help
column is narrow; the title gets the rest. Vertical alignment is
left to Streamlit's column default (top) — works on 1.35+ without
the ``vertical_alignment`` kwarg that landed later.
"""
col_title, col_help = st.columns([10, 1])
with col_title:
st.title(_t(f"tools.{tool_id}.page_title"))
with col_help:
# Spacer pushes the popover button down so it sits closer to
# the title's baseline than to its top — without the spacer the
# button floats above the big title text.
st.write("")
body = _t(f"tools.{tool_id}.help_md")
if body.startswith("tools."):
body = _t("help.missing_body")
with st.popover(
_t("help.button_label"),
icon=":material/help_outline:",
use_container_width=True,
):
st.markdown(body)
st.caption(_t(f"tools.{tool_id}.page_caption"))
def _render_sticky_footer_DISABLED() -> None:
"""Slim fixed-position footer at the bottom of the viewport.