From f19589e817d8ee5b4a46d6041ad6c4921feb6c71 Mon Sep 17 00:00:00 2001 From: frapercan Date: Fri, 8 May 2026 18:01:59 +0200 Subject: [PATCH] =?UTF-8?q?feat(web):=20visual=20coherence=20=E2=80=94=20s?= =?UTF-8?q?late=20palette,=20density=20bumps,=20Skeleton=20adoption?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three swings across the Next.js app to retire mismatched style choices that landed in different sessions. No logic changes. 1) Palette unification: gray-* → slate-* The platform polish (#68) introduced slate on the header / home / nav while every other page kept gray-. The same session showed two neutral palettes side-by-side. Single sed sweep across 24 page and component files (641 occurrences) brings everything to slate-. Semantic colors (red / blue / emerald / amber / violet) untouched. 2) Density bump in body cells text-xs (12px) is hostile for tabular numbers in the data-heavy pages. Selective bump to text-[13px] inside cells and body paragraphs in /scoring, /annotations, /reranker, /evaluation, /jobs/[id], /proteins/[accession]. Labels, chips, badges and tracking-* uppercase headers stay at text-xs (intentional). 3) Skeleton adoption The repo ships components/Skeleton.tsx but pages roll their own `bg-gray-100 rounded animate-pulse`. Migrated the most visible loading screen (/benchmark) to use . Other ad-hoc pulse patterns in cards (jobs / proteins / annotations / fa[id]) are wrapper-level pulses, not inner skeletons — left intact for a follow-up that designs proper skeleton card variants. CI: next build green; backend untouched. --- apps/web/app/[locale]/annotations/page.tsx | 88 ++++---- apps/web/app/[locale]/benchmark/page.tsx | 77 +++---- apps/web/app/[locale]/embeddings/page.tsx | 66 +++--- apps/web/app/[locale]/evaluation/page.tsx | 144 ++++++------ .../functional-annotation/[id]/page.tsx | 206 +++++++++--------- .../[locale]/functional-annotation/page.tsx | 58 ++--- apps/web/app/[locale]/jobs/[id]/page.tsx | 44 ++-- apps/web/app/[locale]/jobs/page.tsx | 46 ++-- apps/web/app/[locale]/maintenance/page.tsx | 22 +- .../[locale]/proteins/[accession]/page.tsx | 98 ++++----- apps/web/app/[locale]/proteins/page.tsx | 72 +++--- apps/web/app/[locale]/query-sets/page.tsx | 32 +-- apps/web/app/[locale]/reranker/page.tsx | 88 ++++---- apps/web/app/[locale]/scoring/page.tsx | 88 ++++---- apps/web/app/[locale]/stack/page.tsx | 44 ++-- apps/web/app/[locale]/support/page.tsx | 12 +- apps/web/components/AnnotateForm.tsx | 16 +- apps/web/components/ContextBanner.tsx | 6 +- apps/web/components/DocLinks.tsx | 6 +- apps/web/components/EventTimeline.tsx | 14 +- apps/web/components/GoGraph.tsx | 14 +- apps/web/components/ResetDbButton.tsx | 6 +- apps/web/components/Skeleton.tsx | 2 +- apps/web/components/StatusBadge.tsx | 4 +- apps/web/components/SupportButton.tsx | 18 +- apps/web/components/Tooltip.tsx | 4 +- apps/web/components/UsagePolicyModal.tsx | 8 +- 27 files changed, 642 insertions(+), 641 deletions(-) diff --git a/apps/web/app/[locale]/annotations/page.tsx b/apps/web/app/[locale]/annotations/page.tsx index 0affb9e..fde76ed 100644 --- a/apps/web/app/[locale]/annotations/page.tsx +++ b/apps/web/app/[locale]/annotations/page.tsx @@ -18,7 +18,7 @@ import { useTranslations } from "next-intl"; type Tab = "sets" | "snapshots" | "load-snapshot" | "load-goa" | "load-quickgo"; const inputClass = "w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"; -const labelClass = "block text-sm font-medium text-gray-700 mb-1"; +const labelClass = "block text-sm font-medium text-slate-700 mb-1"; function formatDate(iso?: string | null) { if (!iso) return "—"; @@ -209,7 +209,7 @@ export default function AnnotationsPage() { className={`px-3 sm:px-4 py-2 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${ activeTab === tab.key ? "border-blue-600 text-blue-600" - : "border-transparent text-gray-500 hover:text-gray-700" + : "border-transparent text-slate-500 hover:text-slate-700" }`} > {tab.label} @@ -221,8 +221,8 @@ export default function AnnotationsPage() { {activeTab === "sets" && (
-

{t("setsTab.annotationSets", { count: sets.length })}

-
@@ -230,19 +230,19 @@ export default function AnnotationsPage() {
{loadingSets && Array.from({ length: 3 }).map((_, i) => (
-
-
+
+
))} {!loadingSets && sets.length === 0 && ( -
+
{t("setsTab.noSetsFound")}
)} {sets.map((a) => (
- {a.source} + {a.source}
-

{a.source_version ?? "—"} · {(a.annotation_count ?? 0).toLocaleString()} annotations

+

{a.source_version ?? "—"} · {(a.annotation_count ?? 0).toLocaleString()} annotations

{a.meta && Object.entries(a.meta).map(([k, v]) => ( - + {k}: {Array.isArray(v) ? v.join(", ") : String(v)} ))}
-
+
{shortId(a.id)} {formatDate(a.created_at)} {a.job_id && ( @@ -271,29 +271,29 @@ export default function AnnotationsPage() { {/* Desktop table */}
-
+
{t("setsTab.tableHeaders.id")}
{t("setsTab.tableHeaders.source")}
{t("setsTab.tableHeaders.version")}
{t("setsTab.tableHeaders.annotations")}
{t("setsTab.tableHeaders.meta")}
{t("setsTab.tableHeaders.created")}
{loadingSets && Array.from({ length: 3 }).map((_, i) => )} {!loadingSets && sets.length === 0 && ( -
+
{t("setsTab.noSetsFound")}
)} {sets.map((a) => (
-
{shortId(a.id)}
-
{a.source}
-
{a.source_version ?? "—"}
-
{(a.annotation_count ?? 0).toLocaleString()}
+
{shortId(a.id)}
+
{a.source}
+
{a.source_version ?? "—"}
+
{(a.annotation_count ?? 0).toLocaleString()}
{a.meta && Object.entries(a.meta).map(([k, v]) => ( - + {k}: {Array.isArray(v) ? v.join(", ") : String(v)} ))}
-
+
{formatDate(a.created_at)} {a.job_id && ( ↗ @@ -317,8 +317,8 @@ export default function AnnotationsPage() { {activeTab === "snapshots" && (
-

{t("snapshotsTab.snapshots", { count: snapshots.length })}

-
@@ -326,20 +326,20 @@ export default function AnnotationsPage() {
{loadingSnaps && Array.from({ length: 2 }).map((_, i) => (
-
-
+
+
))} {!loadingSnaps && snapshots.length === 0 && ( -
+
{t("snapshotsTab.noSnapshotsFound")}
)} {snapshots.map((s) => (
- {s.obo_version} - {(s.go_term_count ?? 0).toLocaleString()} terms + {s.obo_version} + {(s.go_term_count ?? 0).toLocaleString()} terms
{iaEditId === s.id ? ( @@ -358,25 +358,25 @@ export default function AnnotationsPage() { />
- +
) : ( )}
-
+
{shortId(s.id)} {formatDate(s.loaded_at)}
@@ -386,20 +386,20 @@ export default function AnnotationsPage() { {/* Desktop table */}
-
+
{t("snapshotsTab.tableHeaders.id")}
{t("snapshotsTab.tableHeaders.version")}
{t("snapshotsTab.tableHeaders.goTerms")}
{t("snapshotsTab.tableHeaders.iaUrl")}
{t("snapshotsTab.tableHeaders.loaded")}
{loadingSnaps && Array.from({ length: 2 }).map((_, i) => )} {!loadingSnaps && snapshots.length === 0 && ( -
+
{t("snapshotsTab.noSnapshotsFound")}
)} {snapshots.map((s) => (
-
{shortId(s.id)}
-
{s.obo_version}
-
{(s.go_term_count ?? 0).toLocaleString()}
+
{shortId(s.id)}
+
{s.obo_version}
+
{(s.go_term_count ?? 0).toLocaleString()}
{iaEditId === s.id ? (
@@ -424,7 +424,7 @@ export default function AnnotationsPage() { @@ -432,19 +432,19 @@ export default function AnnotationsPage() { ) : ( )}
-
{formatDate(s.loaded_at)}
+
{formatDate(s.loaded_at)}
))}
@@ -456,7 +456,7 @@ export default function AnnotationsPage() {

{t("loadSnapshotTab.title")}

-

{t("loadSnapshotTab.description")}

+

{t("loadSnapshotTab.description")}

@@ -491,7 +491,7 @@ export default function AnnotationsPage() {

{t("loadGoaTab.title")}

-

{t("loadGoaTab.description")}

+

{t("loadGoaTab.description")}

@@ -550,7 +550,7 @@ export default function AnnotationsPage() {

{t("loadQuickgoTab.title")}

-

{t("loadQuickgoTab.description")}

+

{t("loadQuickgoTab.description")}

diff --git a/apps/web/app/[locale]/benchmark/page.tsx b/apps/web/app/[locale]/benchmark/page.tsx index b93c04d..5c33b92 100644 --- a/apps/web/app/[locale]/benchmark/page.tsx +++ b/apps/web/app/[locale]/benchmark/page.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from "react"; import Link from "next/link"; +import { Skeleton } from "@/components/Skeleton"; import { getBenchmarkEmbeddings, getBenchmarkMatrix, @@ -227,8 +228,8 @@ export default function BenchmarkPage() { if (!embeddings || !matrix || stage === null) { return (
-
-
+ +
); } @@ -254,8 +255,8 @@ export default function BenchmarkPage() { {/* Header */}
-

Benchmark matrix

-

+

Benchmark matrix

+

Per-embedding Fmax across categories and aspects for every evaluation run in the database.{" "} @@ -272,7 +273,7 @@ export default function BenchmarkPage() { rowsToCsv(embeddings, matrix.rows, stage), ) } - className="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed" + className="rounded-md border border-slate-300 bg-white px-3 py-1.5 text-sm text-slate-700 hover:bg-slate-50 disabled:opacity-50 disabled:cursor-not-allowed" > Download CSV @@ -339,10 +340,10 @@ export default function BenchmarkPage() { {/* Filters */}

-