Spaces:
Running
Running
| # SupraDashboard — Design Rationale (v0) | |
| > Companion to `SPEC.md`. This document is the UI/UX contract for `app.py`. It | |
| > covers the aesthetic direction, layout, visual hierarchy, the rule-header color | |
| > system, typography, the streaming/loading UX, and how each SPEC user-flow step | |
| > maps to a concrete UI element. | |
| --- | |
| ## 0. Aesthetic direction (and why it is NOT the editorial default) | |
| SupraDashboard is an **internal expert-review instrument**, not an editorial or | |
| brand surface. The dominant content is a dense, color-coded scientific reasoning | |
| trace that ~3 chemists will read for minutes at a time, many guests per sitting. | |
| The design goal is *legibility under sustained reading* + *glanceable comparison* | |
| + *calm chrome that never competes with the data*. | |
| So this is deliberately **not** the warm-cream / serif / terracotta editorial look. | |
| It is a **"scientific instrument"** direction: | |
| - **Palette — cool slate/ink neutrals with a single teal primary.** | |
| - App background: `#F5F7FA` (very light cool slate, almost white but with a blue | |
| undertone so the white reasoning card lifts off it). | |
| - Surface / cards: `#FFFFFF` with a `#E3E8EF` hairline border and a soft shadow. | |
| - Ink (body text): `#1F2933`; muted labels: `#5B6B7B`. | |
| - Primary action / focus / combined-emphasis: **teal** `#0E7C86` | |
| (hover `#0A5F67`). One accent, used sparingly, so it reads as "the system", | |
| not decoration. Avoids the AI-slop purple-on-white gradient entirely. | |
| - Semantic: ok `#1A7F37`, warn `#9A6700`, error `#B42318`. | |
| - **The rule-header accents are the ONLY place saturated color appears in volume**, | |
| and that is intentional: color = meaning (rule index), not chrome. Keeping the | |
| rest of the UI desaturated is what lets the rule colors carry signal. | |
| - **Typography.** | |
| - UI chrome / labels: the system UI stack (`ui-sans-serif, -apple-system, …`) — | |
| chrome should be invisible, not expressive. (System fonts are correct *here*: | |
| this is an instrument, and we're spending the reader's font-attention budget on | |
| the reasoning, not the frame.) | |
| - **Reasoning body + summaries: a serif reading face** — | |
| `"Source Serif 4", "Iowan Old Style", Charter, "Georgia", serif`, **16px / | |
| line-height 1.7**. Prior reviewer feedback explicitly asked for a *bigger, | |
| more readable* reasoning block; a serif at 16/1.7 is measurably easier for | |
| long-form sustained reading than a 13px sans, and it visually marks "this is the | |
| thing to read" vs. the sans chrome around it. | |
| - **Numbers (logKa) + InChIKey: a monospace face** — | |
| `"IBM Plex Mono", "SF Mono", ui-monospace, monospace`. Tabular numerals make the | |
| three predictions vertically scannable and unambiguous. | |
| If the user or brand later mandates the editorial aesthetic, that overrides this — | |
| but for a data-dense expert review tool the instrument direction is the correct | |
| default, per the domain mapping. | |
| --- | |
| ## 1. The ONE memorable thing | |
| **A reading-grade, color-coded reasoning panel that feels like a lab notebook, | |
| not a chat bubble.** Everything else (structure, prediction table, summaries, | |
| rating) is sized and colored to orbit it. A reviewer's eye should land on the | |
| reasoning first and stay there. | |
| --- | |
| ## 2. Layout (wireframe) | |
| Single scrolling page, three vertical zones. Max content width ~1280px, centered. | |
| ``` | |
| ┌──────────────────────────────────────────────────────────────────────────────┐ | |
| │ SupraDashboard CB[7] host–guest logKa reasoning review │ ← header band | |
| │ ● proxy configured (model=gpt-5.5-codex) ● dataset loaded (142 guests) │ ← health strip (colored dots) | |
| ├──────────────────────────────────────────────────────────────────────────────┤ | |
| │ [ Guest molecule ▾ ............................. ] [ ▶ Run prediction ] │ ← control bar (sticky-ish) | |
| ├──────────────────────────────────────────────────────────────────────────────┤ | |
| │ RUN STATUS: ◷ Running trajectory 2/3 — chemistry-guided… │ ← streaming status line (hidden when idle) | |
| ├───────────────────────────────┬──────────────────────────────────────────────┤ | |
| │ LEFT RAIL (scale 2) │ HERO (scale 3) │ | |
| │ │ │ | |
| │ ┌─────────────────────────┐ │ REASONING — combined trajectory │ | |
| │ │ 2D structure (RDKit) │ │ ┌────────────────────────────────────────┐ │ | |
| │ │ [ molecule ] │ │ │ 16px serif, line-height 1.7 │ │ | |
| │ └─────────────────────────┘ │ │ │ │ | |
| │ │ │ 1. Hydrophobic cavity filling — … ←blue│ │ | |
| │ PREDICTED logKa │ │ 2. Portal ion–dipole contacts — … ←purpl│ │ | |
| │ ┌──────────┬───────┐ │ │ 3. Desolvation penalty — … ←green │ │ | |
| │ │ Combined │ 4.82 │◀ prim. │ │ 4. Preorganization — … ←pink │ │ | |
| │ │ Physics │ 4.10 │ │ │ … │ │ | |
| │ │ Chemistry│ 5.21 │ │ │ │ │ | |
| │ └──────────┴───────┘ │ └────────────────────────────────────────┘ │ | |
| │ │ │ | |
| │ PHYSICS ⟶ tldr card │ │ | |
| │ CHEMISTRY ⟶ tldr card │ │ | |
| ├───────────────────────────────┴──────────────────────────────────────────────┤ | |
| │ EXPERT REVIEW (full-width band, visually set apart by a top divider) │ | |
| │ Does the reasoning make chemical sense? │ | |
| │ ( ) Absolutely right ( ) Mostly right ( ) Partially right (mixed) … │ ← horizontal radio | |
| │ [ comment textarea, 4 rows ......................................... ] │ | |
| │ [ Submit review ] ✓ Saved review #37. Thank you! │ | |
| └──────────────────────────────────────────────────────────────────────────────┘ | |
| ``` | |
| Responsive: below ~860px the left-rail / hero `Row` reflows to a single column | |
| (Gradio columns stack), structure on top, reasoning below, table and tldr cards | |
| full-width. The horizontal rating radio wraps. No horizontal scroll at 360px. | |
| --- | |
| ## 3. Visual hierarchy (largest signal → smallest) | |
| 1. **Reasoning panel** — biggest type (16px serif), white card, most screen real | |
| estate (3/5 width), the color comes from here. This is the hero per FR6 + prior | |
| feedback. | |
| 2. **Predicted-logKa comparison** — mono numerals; **Combined** row is bolded, gets | |
| a teal left-accent bar and a slightly larger number; physics/chemistry are | |
| secondary (muted). Glanceable in <1s (priority 2). | |
| 3. **2D structure** — anchored top-left, fixed card; orienting, not dominant. | |
| 4. **Physics / chemistry tldr cards** — small labeled cards, one line each, muted | |
| border + a tiny mode tag. Supportive context (priority 3). | |
| 5. **Expert review block** — deliberately set apart by a full-width divider and its | |
| own band so it reads as a distinct *action*, but it sits **below** the reading | |
| zone so it never competes with reasoning (priority 5). | |
| 6. **Chrome** (header, health strip, labels) — smallest, desaturated, system font. | |
| --- | |
| ## 4. Rule-header color system | |
| The combined `<think>` contains numbered binding-driver rules of the form | |
| `N. Title — explanation` or `N. Title: explanation`. We bold the `N. Title` run and | |
| color it by **rule index mod palette** so consecutive rules are visually separable | |
| and a reviewer can say "rule 3 is wrong" and find it instantly. | |
| Palette (saturated, accessible on white, distinct hues — refined from the existing | |
| `RULE_COLORS`; kept on the same blue→purple→green→pink→amber→cyan wheel so rule N | |
| always maps to the same hue across guests): | |
| | idx | hue | hex | WCAG AA on #FFF | | |
| |-----|--------|-----------|-----------------| | |
| | 1 | blue | `#0969DA` | ✓ (4.6:1) | | |
| | 2 | purple | `#8250DF` | ✓ (4.5:1) | | |
| | 3 | green | `#1A7F37` | ✓ (4.7:1) | | |
| | 4 | pink | `#BF3989` | ✓ (4.5:1) | | |
| | 5 | amber | `#9A6700` | ✓ (4.8:1) | | |
| | 6 | cyan | `#1B7C83` | ✓ (4.6:1) | | |
| Rendering rule (refined `_color_reason`): | |
| - Only the `N. Title` span is colored + `font-weight:700`; the explanation stays ink | |
| `#1F2933` so the *header* pops but the prose stays calm and readable. | |
| - Each rule also gets a **faint left border** in its hue (`border-left:3px` + small | |
| left padding) so the rule blocks are scannable as bands even in peripheral vision. | |
| - Non-rule lines (intro/transition prose) render as plain serif body, indented to | |
| align with rule text. | |
| - The whole block is wrapped in `white-space:pre-wrap; font-size:16px; | |
| line-height:1.7; font-family:<serif>` so the SPEC's "≈15–16px / line-height ~1.6" | |
| ask is met (we go 16/1.7, slightly more generous, which prior feedback favored). | |
| --- | |
| ## 5. Streaming / loading UX (generator-driven) | |
| `predict()` is an **async generator** that yields after each milestone, so the | |
| expert sees structure instantly and results stream in (NFR1, decision-critical SDK | |
| facts). The `.click()` uses `show_progress="full"` so Gradio also paints its native | |
| queue/progress spinner. | |
| Yield timeline (each yield repaints only what changed; everything else is | |
| `gr.update()`): | |
| | # | When | What becomes visible | Status line text | | |
| |---|------|----------------------|------------------| | |
| | 0 | immediately | 2D structure; table skeleton with all `…`; reasoning placeholder "running…"; tldr cards show a pulsing skeleton | `◷ Rendering structure & dispatching trajectories…` | | |
| | 1 | after **combined** returns | combined logKa fills + **full reasoning panel renders** (hero first — the reviewer can start reading while the rest runs) | `◷ Running trajectory 2/3 — physics-guided…` | | |
| | 2 | after **physics** returns | physics logKa + physics tldr card | `◷ Running trajectory 3/3 — chemistry-guided…` | | |
| | 3 | after **chemistry** returns | chemistry logKa + chemistry tldr card | `● Done — 3/3 trajectories. Review below.` | | |
| Design choices: | |
| - **Combined first**, not last. The hero (reasoning) is the slowest-value-per-second | |
| thing to read, so we surface it at yield 1 and let physics/chemistry trickle in. | |
| (Implementer may parallelize the three calls behind the generator; the yield | |
| contract is independent of execution order as long as combined is awaited first.) | |
| - **Status line** is a dedicated `gr.Markdown` that is empty/hidden when idle and | |
| shows a `◷` running glyph (amber) while in-flight, flipping to a green `●` Done. | |
| - **Per-call failure is isolated** (NFR1): if a trajectory raises, that cell shows | |
| `error` in red and the status line notes which trajectory failed, but | |
| already-rendered panels are kept. The generator catches per-mode and continues. | |
| States: | |
| - **Empty (pre-run):** structure card shows a faint flask glyph + "Pick a guest and | |
| Run prediction"; table shows `—` rows; reasoning panel shows a dashed-border | |
| placeholder "The combined reasoning trace will appear here." | |
| - **Error (config):** the health strip dot is red and the reasoning/structure area | |
| shows a single error card with the readable message (proxy/dataset not configured) | |
| instead of a broken run. Never crashes (NFR5). | |
| --- | |
| ## 6. Component choices (Gradio 5.x) | |
| | UI element | Gradio component | Notes | | |
| |---|---|---| | |
| | Header + health strip | `gr.HTML` | colored status dots, custom markup | | |
| | Guest picker | `gr.Dropdown(value=None)` | blank default (Gradio 5 would else pick first) | | |
| | Run button | `gr.Button(variant="primary")` | teal primary | | |
| | Run-status line | `gr.Markdown` | streamed by the generator | | |
| | Structure | `gr.Image(height=300, show_label=False)` | PIL from RDKit | | |
| | Prediction table | `gr.HTML` | custom card-table so we can emphasize Combined + use mono numerals (Markdown table can't carry the styling) | | |
| | tldr cards | `gr.HTML` x2 | labeled mode cards | | |
| | Reasoning hero | `gr.HTML` | color-coded serif render | | |
| | Rating | `gr.Radio(choices=RATINGS)` | horizontal; secondary placement | | |
| | Comment | `gr.Textbox(lines=4)` | | | |
| | Submit | `gr.Button` | non-primary (secondary action) | | |
| | Feedback ack | `gr.Markdown` | shows saved row id | | |
| | Admin export | `gr.Tab` "Admin" → `gr.DataFrame` + `gr.DownloadButton` | FR12; gated by same `auth=` | | |
| Styling delivered via a `gr.themes.Soft(...)`-based theme (teal primary, slate | |
| neutrals) **plus** a `css=` string for the reasoning serif, the table emphasis, the | |
| status glyphs, and the card borders. Queue enabled: | |
| `demo.queue(default_concurrency_limit=1).launch(...)`. | |
| --- | |
| ## 7. SPEC user-flow → UI mapping | |
| | SPEC step (§4) | UI realization | | |
| |---|---| | |
| | 1. Pass `APP_AUTH` wall | `launch(auth=_auth())` — unchanged | | |
| | 2. Health line + dropdown | header health strip (two colored dots) + `guest_dd` | | |
| | 3. Pick guest + Run | control bar; `run_btn.click → predict` generator | | |
| | 4. Loading state | run-status line + `show_progress="full"`; structure shows at yield 0 | | |
| | 5. Render structure / table / tldr / reasoning | left rail (structure, table, tldr cards) + hero reasoning panel, filled across yields 0–3 | | |
| | 6. Read, rate, comment | reasoning hero → expert-review band (radio + textbox) | | |
| | 7. Submit + confirm row id | `submit_btn.click → submit_feedback`; ack Markdown shows `#id` | | |
| | 8. Next guest | dropdown stays; new Run resets panels via yield 0 | | |
| FR coverage: FR2 structure (graceful empty), FR5 tag parsing (`—` on miss), FR6 | |
| table + color-coded rules, FR7 no-rating warning, FR8 persisted row + id, FR11 | |
| health strip, FR12 admin export tab. | |
| --- | |
| ## 8. Accessibility | |
| - Rule colors all pass WCAG AA (≥4.5:1) on white; color is **redundant** with the | |
| bold weight + left-border band + the literal `N.` number, so color-blind reviewers | |
| still parse rule boundaries (color is never the sole signal). | |
| - Radio + textbox carry visible `label`s; focus ring uses the teal primary at 3:1+. | |
| - Status glyphs (`◷`, `●`) are paired with text, never icon-only. | |
| - Reasoning panel is selectable text (real HTML), not an image, so it's | |
| screen-reader and copy-paste friendly. | |
| ``` | |