SupraDashboard / docs /DESIGN.md
Tianyi-Billy-Ma
Deploy: simplify codebase (dead-code removal, behavior-preserving)
1727091
|
Raw
History Blame Contribute Delete
15.7 kB

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 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.