Spaces:
Running
SupraDashboard β Design Rationale (v0)
Companion to
SPEC.md. This document is the UI/UX contract forapp.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:
#FFFFFFwith a#E3E8EFhairline 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.
- App background:
- 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.
- UI chrome / labels: the system UI stack (
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)
- 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.
- 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).
- 2D structure β anchored top-left, fixed card; orienting, not dominant.
- Physics / chemistry tldr cards β small labeled cards, one line each, muted border + a tiny mode tag. Supportive context (priority 3).
- 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).
- 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. Titlespan is colored +font-weight:700; the explanation stays ink#1F2933so 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.Markdownthat 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
errorin 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
labels; 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.