From 2f37778f2baf6e97d530cd19ff624a1259548436 Mon Sep 17 00:00:00 2001 From: Neko Ayaka Date: Tue, 3 Nov 2026 02:50:24 +0800 Subject: [PATCH] feat(ui): lay out large matrices as compact grids with baselines and averages The matrix tab put one card per cell in a single wide row of columns, so a 3 x 2 x 2 x 3 sweep needed three screens of horizontal scrolling and every card repeated the same metadata. - Lay the axes out to fill one screen width (rows may run long), with one header level per column axis and frozen headers and row labels. - Switch between cards and compact cells automatically by grid size and screen; the reader can pin either. Compact cells open a detail card on hover: configuration, full card, every score, 95% interval, baseline comparison, and repeats. - Average repeat axes (seed, repeat, ...) by default, or any axis on demand. - Compare every cell to a baseline chosen per axis; differences are colored around 0 and faded when within noise. - Show row and column means as margin bars, and sort rows best first. - Mark completion with a ring measured against the entry's usual case count, so a one-case rerun reads as 1 of 60 instead of 100%. - Show each value's mean beside the baseline and average menus. - Align card bars across a grid row with CSS subgrid on the home and compare pages, and full-height cells in the matrix card view. Co-Authored-By: Claude Opus 5.5 --- .../client/src/components/CompletionRing.vue | 65 +++ .../client/src/components/HeadlineScore.vue | 4 +- .../ui/client/src/components/MarginBar.vue | 38 ++ .../client/src/components/MatrixCellCard.vue | 170 ++++++ .../src/components/MatrixCellDetail.vue | 102 ++++ .../client/src/components/MatrixHeatCell.vue | 90 +++ .../ui/client/src/components/MatrixTable.vue | 265 +++++++++ .../ui/client/src/components/MatrixView.vue | 517 ++++++++++-------- .../ui/client/src/components/ScoreCard.vue | 21 +- .../ui/client/src/i18n/locales/en/matrix.ts | 55 +- .../client/src/i18n/locales/zh-Hans/matrix.ts | 55 +- packages/ui/client/src/matrixGrid.test.ts | 295 ++++++++++ packages/ui/client/src/matrixGrid.ts | 399 ++++++++++++++ packages/ui/client/src/pages/ComparePage.vue | 4 +- packages/ui/client/src/pages/HomePage.vue | 4 +- packages/ui/client/src/styles.css | 4 + 16 files changed, 1850 insertions(+), 238 deletions(-) create mode 100644 packages/ui/client/src/components/CompletionRing.vue create mode 100644 packages/ui/client/src/components/MarginBar.vue create mode 100644 packages/ui/client/src/components/MatrixCellCard.vue create mode 100644 packages/ui/client/src/components/MatrixCellDetail.vue create mode 100644 packages/ui/client/src/components/MatrixHeatCell.vue create mode 100644 packages/ui/client/src/components/MatrixTable.vue create mode 100644 packages/ui/client/src/matrixGrid.test.ts create mode 100644 packages/ui/client/src/matrixGrid.ts diff --git a/packages/ui/client/src/components/CompletionRing.vue b/packages/ui/client/src/components/CompletionRing.vue new file mode 100644 index 0000000..7535ade --- /dev/null +++ b/packages/ui/client/src/components/CompletionRing.vue @@ -0,0 +1,65 @@ + + + diff --git a/packages/ui/client/src/components/HeadlineScore.vue b/packages/ui/client/src/components/HeadlineScore.vue index 36c249e..aa7e9d5 100644 --- a/packages/ui/client/src/components/HeadlineScore.vue +++ b/packages/ui/client/src/components/HeadlineScore.vue @@ -31,6 +31,8 @@ const props = defineProps<{ align?: 'end' | 'start' /** `score.defined` of the headline's scores (`headlineDefinitions`, `scoreDefinitions`). */ definitions: readonly ScoreDefinition[] + /** Leaves the completion rate out, for a place that shows it another way (the progress ring of a matrix card). */ + hideCompletion?: boolean /** * Called when the completion rate below 100 % is clicked; the page shows the cases without a result. Without it, the * rate is plain text (inside a card that is a link itself, for example). @@ -62,7 +64,7 @@ const column = computed(() => { }) const unscoredCount = computed(() => Object.values(view.value?.summary.unscored ?? {}).reduce((sum, count) => sum + count, 0)) const incomplete = computed(() => view.value != null && view.value.completion.mean != null && view.value.completion.mean < 1) -const showCompletion = computed(() => view.value != null && view.value.kind !== 'per-task' && (props.size !== 'sm' || incomplete.value)) +const showCompletion = computed(() => view.value != null && view.value.kind !== 'per-task' && !props.hideCompletion && (props.size !== 'sm' || incomplete.value)) const valueClass = computed(() => ({ lg: 'text-2xl', md: 'text-xl', sm: 'text-sm' })[props.size ?? 'md']) diff --git a/packages/ui/client/src/components/MarginBar.vue b/packages/ui/client/src/components/MarginBar.vue new file mode 100644 index 0000000..9c5c444 --- /dev/null +++ b/packages/ui/client/src/components/MarginBar.vue @@ -0,0 +1,38 @@ + + + diff --git a/packages/ui/client/src/components/MatrixCellCard.vue b/packages/ui/client/src/components/MatrixCellCard.vue new file mode 100644 index 0000000..283c61b --- /dev/null +++ b/packages/ui/client/src/components/MatrixCellCard.vue @@ -0,0 +1,170 @@ + + + diff --git a/packages/ui/client/src/components/MatrixCellDetail.vue b/packages/ui/client/src/components/MatrixCellDetail.vue new file mode 100644 index 0000000..94d3259 --- /dev/null +++ b/packages/ui/client/src/components/MatrixCellDetail.vue @@ -0,0 +1,102 @@ + + + diff --git a/packages/ui/client/src/components/MatrixHeatCell.vue b/packages/ui/client/src/components/MatrixHeatCell.vue new file mode 100644 index 0000000..cbe1d19 --- /dev/null +++ b/packages/ui/client/src/components/MatrixHeatCell.vue @@ -0,0 +1,90 @@ + + + diff --git a/packages/ui/client/src/components/MatrixTable.vue b/packages/ui/client/src/components/MatrixTable.vue new file mode 100644 index 0000000..ecd962b --- /dev/null +++ b/packages/ui/client/src/components/MatrixTable.vue @@ -0,0 +1,265 @@ + + + diff --git a/packages/ui/client/src/components/MatrixView.vue b/packages/ui/client/src/components/MatrixView.vue index 8f94227..a90a62e 100644 --- a/packages/ui/client/src/components/MatrixView.vue +++ b/packages/ui/client/src/components/MatrixView.vue @@ -1,29 +1,47 @@