feat(ui): Material icons in sidebar + stats overview on home
Two pieces of the mockup 2 layout that hadn't landed yet: 1. Sidebar nav icons — emoji glyphs (🧹 ✂️ 🔍 …) swapped for Streamlit's ``:material/<name>:`` syntax, picking the outline Material Symbol that best matches each mockup SVG: Home → :material/home: Fix Missing Values → :material/help_outline: Find Unusual Vals → :material/insights: Clean Text → :material/text_format: Standardize Fmts → :material/format_list_bulleted: Find Duplicates → :material/search: Quality Check → :material/check_circle: Map Columns → :material/view_column: Combine Files → :material/account_tree: Auto Workflows → :material/auto_awesome: Activate → :material/key: Close → :material/close: Streamlit injects the icon name as a literal ligature inside a first-child ``<span>`` of the nav anchor, expected to render through the Material Symbols font. theme.py's base rule was forcing Geist on every span under ``stSidebarNav``, turning the ligatures back into plain text labels — added a structural exception that targets ``[data-testid="stSidebarNavLink"] > span:first-child`` (and any descendant), restoring the Material font family, neutralizing the inherited ``ss01/cv01/cv11`` feature settings, and sizing to 18px. Also stripped the leading emojis from every page title in the en/es i18n packs (``home.title``, ``close_page.title``, ``activation.title``, ``tools.*.page_title``) — the icons live in the sidebar now, the page H1 no longer needs to carry one. 2. Stats overview on home — new ``_render_stats_overview`` in _home.py emits a 4-card grid above the per-file findings panels: Files analyzed, Total findings, Warnings (severity ``warn`` ∪ ``error``), Info (severity ``info``). Card layout follows the mockup §stats verbatim — Geist 28px / 600 / -0.03em for the numeric value (the "Display number" row in spec §4), tiny uppercase tracked label, paper-surface card with the standard warm border + faint shadow. The Warnings / Info cards tint the number with ``--warn`` / ``--info`` when the count is non-zero. CSS for ``.dt-stats / .dt-stat / .dt-stat-label / .dt-stat-value / .dt-stat-unit`` added to ``_DESIGN_TOKENS_CSS``; falls to a 2-column grid below 900px viewport, matching the mockup's media query. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,61 @@ class _StashedUpload:
|
||||
return self._data
|
||||
|
||||
|
||||
def _render_stats_overview(findings_by_file: dict) -> None:
|
||||
"""4-card grid above the per-file findings — summarizes the run.
|
||||
|
||||
Card layout follows ``datatools_layout_redesign2.html`` §stats:
|
||||
Files analyzed, Total findings, Warnings (severity ``warn`` ∪
|
||||
``error``), Info (severity ``info``). The warn + info cards are
|
||||
tinted via ``.is-warn`` / ``.is-info`` modifiers that read the
|
||||
severity colors theme.py declares.
|
||||
"""
|
||||
import html as _html
|
||||
|
||||
n_files = len(findings_by_file)
|
||||
all_findings = [f for fs in findings_by_file.values() for f in fs]
|
||||
n_total = len(all_findings)
|
||||
# Mockup groups errors with warnings on the "to review" card —
|
||||
# both demand the user act. ``info`` is the lower-priority pile.
|
||||
n_warn = sum(1 for f in all_findings if f.severity in ("warn", "error"))
|
||||
n_info = sum(1 for f in all_findings if f.severity == "info")
|
||||
|
||||
def _card(label: str, value: int, unit: str = "", kind: str = "") -> str:
|
||||
cls = "dt-stat" + (f" {kind}" if kind else "")
|
||||
unit_html = (
|
||||
f'<span class="dt-stat-unit">{_html.escape(unit)}</span>'
|
||||
if unit else ""
|
||||
)
|
||||
return (
|
||||
f'<div class="{cls}">'
|
||||
f'<div class="dt-stat-label">{_html.escape(label)}</div>'
|
||||
f'<div class="dt-stat-value">{value}{unit_html}</div>'
|
||||
f"</div>"
|
||||
)
|
||||
|
||||
cards = (
|
||||
_card("Files analyzed", n_files)
|
||||
+ _card("Total findings", n_total)
|
||||
+ _card(
|
||||
"Warnings",
|
||||
n_warn,
|
||||
unit="to review" if n_warn else "",
|
||||
kind="is-warn" if n_warn else "",
|
||||
)
|
||||
+ _card(
|
||||
"Info",
|
||||
n_info,
|
||||
unit="suggestions" if n_info else "",
|
||||
kind="is-info" if n_info else "",
|
||||
)
|
||||
)
|
||||
|
||||
st.markdown(
|
||||
f'<div class="dt-stats">{cards}</div>',
|
||||
unsafe_allow_html=True,
|
||||
)
|
||||
|
||||
|
||||
def _sync_uploader_to_home_uploads() -> None:
|
||||
"""``on_change`` callback for the home-page file_uploader.
|
||||
|
||||
@@ -272,6 +327,11 @@ def _home_page() -> None:
|
||||
|
||||
if findings_by_file:
|
||||
st.divider()
|
||||
# Overview row before drilling into per-file detail. Mockup
|
||||
# layout (datatools_layout_redesign2.html §stats) puts a
|
||||
# 4-card summary above the findings panels so the user can
|
||||
# eyeball the run before expanding any one file.
|
||||
_render_stats_overview(findings_by_file)
|
||||
# Preserve the upload-stash order so the user sees results in
|
||||
# the same order they appear in the file list above.
|
||||
for name in home_uploads:
|
||||
|
||||
Reference in New Issue
Block a user