Skip to content

Commit ab20759

Browse files
jefho-rhclaudenickmazzi
authored
feat(automl): add One vs Rest view to confusion matrix (opendatahub-io#7240)
* feat(automl): add One vs Rest view selector to confusion matrix Co-Authored-By: Claude <noreply@anthropic.com> * feat(automl): add One vs Rest view to confusion matrix Co-Authored-By: Claude <noreply@anthropic.com> * feat(automl): replace inline styles with SCSS classes for confusion matrix cells Co-Authored-By: Claude <noreply@anthropic.com> * feat(automl): improve confusion matrix layout and replace hardcoded values with PF tokens Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): add dark mode support for confusion matrix cell colors Co-Authored-By: Claude <noreply@anthropic.com> * feat(automl): improve confusion matrix loading skeleton to match table layout Co-Authored-By: Claude <noreply@anthropic.com> * test(automl): add unit tests for computeOneVsRest confusion matrix logic Co-Authored-By: Claude <noreply@anthropic.com> * refactor(automl): memoize One vs Rest computation and add non-multiclass test Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): bold confusion matrix summary row header to match thead PF compact table overrides font-weight to normal for tbody th cells. Explicitly set bold on the bottom-left "Percent correct" header. Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): improve dark mode confusion matrix cell and border colors Use PF table background variable for dark mode base/header cells so they match the feature summary table. Add visible grid borders in dark mode via --border--color override. Tone down cell intensity colors for a more natural look against dark backgrounds. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(automl): clean up confusion matrix SCSS Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): improve confusion matrix loading skeleton Co-Authored-By: Claude <noreply@anthropic.com> * test(automl): update confusion matrix loading skeleton tests Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): add horizontal scroll to model details tab content Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): wrap confusion matrix table in InnerScrollContainer Co-Authored-By: Claude <noreply@anthropic.com> * fix(automl): improve confusion matrix header layout and cell min-width Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Nick Mazzitelli <nickmazz@ca.ibm.com>
1 parent 46ad36a commit ab20759

3 files changed

Lines changed: 562 additions & 122 deletions

File tree

packages/automl/frontend/src/app/components/run-results/AutomlModelDetailsModal/AutomlModelDetailsModal.scss

Lines changed: 120 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
/* Sidebar section headers */
1313
.automl-model-details-sidebar-section {
1414
font-size: var(--pf-t--global--font--size--sm);
15-
font-weight: 600;
15+
font-weight: var(--pf-t--global--font--weight--body--bold);
1616
color: var(--pf-t--global--text--color--regular);
1717
text-transform: uppercase;
1818
letter-spacing: 0.05em;
@@ -21,7 +21,7 @@
2121

2222
/* Add spacing between sidebar nav sections */
2323
.automl-model-details-sidebar nav > div + div {
24-
margin-top: 16px;
24+
margin-top: var(--pf-t--global--spacer--md);
2525
}
2626

2727
.automl-model-details-nav-list {
@@ -35,7 +35,7 @@
3535
width: 100%;
3636
padding: var(--pf-t--global--spacer--sm) var(--pf-t--global--spacer--md);
3737
border: none;
38-
border-left: 3px solid transparent;
38+
border-left: var(--pf-t--global--border--width--box--default) solid transparent;
3939
background: none;
4040
text-align: left;
4141
font-size: var(--pf-t--global--font--size--md);
@@ -56,7 +56,7 @@
5656
.automl-model-details-tab-title {
5757
display: inline-flex;
5858
align-items: center;
59-
gap: 2px;
59+
gap: var(--pf-t--global--spacer--xs);
6060
padding-left: var(--pf-t--global--spacer--xl);
6161

6262
.pf-v6-c-title {
@@ -82,17 +82,123 @@
8282
}
8383
}
8484

85+
/* Confusion matrix — theme-aware cell colors.
86+
Palette tokens (--pf-t--color--green--10 etc.) are NOT dark-mode-aware,
87+
so we define custom properties and override them for dark theme. */
88+
@mixin cm-cell-colors($prefix) {
89+
background-color: var(--automl-cm--cell--#{$prefix}--base);
90+
91+
&.m-intensity-low {
92+
background-color: var(--automl-cm--cell--#{$prefix}--low);
93+
}
94+
95+
&.m-intensity-medium {
96+
background-color: var(--automl-cm--cell--#{$prefix}--medium);
97+
}
98+
99+
&.m-intensity-high {
100+
background-color: var(--automl-cm--cell--#{$prefix}--high);
101+
}
102+
}
103+
104+
.automl-confusion-matrix {
105+
--automl-cm--cell--bg: var(--pf-t--global--background--color--secondary--default);
106+
--automl-cm--cell--diagonal--base: var(--pf-t--color--green--10);
107+
--automl-cm--cell--diagonal--low: var(--pf-t--color--green--20);
108+
--automl-cm--cell--diagonal--medium: var(--pf-t--color--green--30);
109+
--automl-cm--cell--diagonal--high: var(--pf-t--color--green--40);
110+
--automl-cm--cell--off-diagonal--base: var(--pf-t--color--blue--10);
111+
--automl-cm--cell--off-diagonal--low: var(--pf-t--color--blue--10);
112+
--automl-cm--cell--off-diagonal--medium: var(--pf-t--color--blue--20);
113+
--automl-cm--cell--off-diagonal--high: var(--pf-t--color--blue--30);
114+
--automl-cm--border--color: var(--pf-t--global--background--color--primary--default);
115+
116+
/* Grid lines between all cells */
117+
--pf-v6-c-table__tr--BorderBlockEndColor: var(--automl-cm--border--color);
118+
119+
:root:where(.pf-v6-theme-dark) & {
120+
--automl-cm--cell--bg: var(--pf-v6-c-table--BackgroundColor);
121+
--automl-cm--cell--diagonal--base: var(--pf-v6-c-table--BackgroundColor);
122+
--automl-cm--cell--diagonal--low: var(--pf-t--color--green--50);
123+
--automl-cm--cell--diagonal--medium: var(--pf-t--color--green--50);
124+
--automl-cm--cell--diagonal--high: var(--pf-t--color--green--40);
125+
--automl-cm--cell--off-diagonal--base: var(--pf-v6-c-table--BackgroundColor);
126+
--automl-cm--cell--off-diagonal--low: var(--pf-t--color--blue--50);
127+
--automl-cm--cell--off-diagonal--medium: var(--pf-t--color--blue--50);
128+
--automl-cm--cell--off-diagonal--high: var(--pf-t--color--blue--40);
129+
--automl-cm--border--color: var(--pf-t--global--border--color--default);
130+
}
131+
132+
th,
133+
td {
134+
border: var(--pf-t--global--border--width--divider--default) solid
135+
var(--automl-cm--border--color);
136+
min-width: 9rem;
137+
}
138+
139+
th,
140+
tbody tr:last-child td,
141+
tbody tr td:last-child {
142+
background-color: var(--automl-cm--cell--bg);
143+
}
144+
145+
146+
tbody th {
147+
font-weight: var(--pf-t--global--font--weight--body--bold);
148+
}
149+
150+
/* Loading state: all cells get the same gray background; skeletons are
151+
darkened so they remain visible against the uniform surface. */
152+
&.m-loading tbody tr td,
153+
&.m-loading tbody tr:last-child td {
154+
background-color: var(--automl-cm--cell--bg);
155+
}
156+
157+
&.m-loading .pf-v6-c-skeleton {
158+
--pf-v6-c-skeleton--BackgroundColor: var(--pf-t--global--border--color--default);
159+
}
160+
161+
/* Center skeleton loading bars within table cells */
162+
.pf-v6-c-skeleton {
163+
margin-inline: auto;
164+
}
165+
166+
/* Data cell colors */
167+
&__cell--diagonal {
168+
font-weight: var(--pf-t--global--font--weight--body--bold);
169+
170+
@include cm-cell-colors('diagonal');
171+
}
172+
173+
&__cell--off-diagonal {
174+
@include cm-cell-colors('off-diagonal');
175+
}
176+
177+
/* View selector */
178+
&-view {
179+
margin-bottom: var(--pf-t--global--spacer--md);
180+
}
181+
}
182+
85183
/* Confusion matrix gradient bar */
86184
.automl-confusion-gradient {
185+
--automl-cm--gradient--start: var(--pf-t--color--blue--20);
186+
--automl-cm--gradient--end: var(--pf-t--color--green--30);
187+
87188
display: flex;
88189
justify-content: space-between;
89190
margin-top: var(--pf-t--global--spacer--md);
90191
padding: var(--pf-t--global--spacer--sm) 0;
91-
background: linear-gradient(to right, rgba(144, 164, 174, 0.5) 0%, #fff 45%, #fff 55%, rgba(56, 142, 60, 0.5) 100%);
92-
border-radius: 4px;
192+
background: linear-gradient(to right, var(--automl-cm--gradient--start) 0%, var(--pf-t--global--background--color--primary--default) 45%, var(--pf-t--global--background--color--primary--default) 55%, var(--automl-cm--gradient--end) 100%);
193+
border-radius: var(--pf-t--global--border--radius--small);
93194
font-size: var(--pf-t--global--font--size--sm);
94195
color: var(--pf-t--global--text--color--subtle);
95196

197+
:root:where(.pf-v6-theme-dark) & {
198+
--automl-cm--gradient--start: var(--pf-t--color--blue--50);
199+
--automl-cm--gradient--end: var(--pf-t--color--green--40);
200+
}
201+
96202
span {
97203
padding: 0 var(--pf-t--global--spacer--sm);
98204
}
@@ -104,7 +210,7 @@
104210
align-items: flex-end;
105211
gap: var(--pf-t--global--spacer--xl);
106212
padding-bottom: var(--pf-t--global--spacer--md);
107-
border-bottom: 1px solid var(--pf-t--global--border--color--default);
213+
border-bottom: var(--pf-t--global--border--width--divider--default) solid var(--pf-t--global--border--color--default);
108214
margin-bottom: var(--pf-t--global--spacer--lg);
109215
}
110216

@@ -123,13 +229,13 @@
123229
.automl-model-details-header-actions {
124230
margin-left: auto;
125231
display: flex;
126-
gap: 8px;
232+
gap: var(--pf-t--global--spacer--sm);
127233
}
128234

129235
.automl-model-details-header-item {
130236
display: flex;
131237
flex-direction: column;
132-
gap: 2px;
238+
gap: var(--pf-t--global--spacer--xs);
133239
}
134240

135241
.automl-model-details-header-label {
@@ -144,12 +250,12 @@
144250

145251
/* Feature importance bar */
146252
.automl-feature-importance-bar {
147-
height: 12px;
148-
border-radius: 2px;
253+
height: var(--pf-t--global--spacer--sm);
254+
border-radius: var(--pf-t--global--border--radius--tiny);
149255
background-color: var(--pf-t--global--color--brand--default);
150256

151257
&.m-has-value {
152-
min-width: 4px;
258+
min-width: var(--pf-t--global--spacer--xs);
153259
}
154260

155261
&.m-negative {
@@ -204,7 +310,7 @@
204310
font-size: var(--pf-t--global--font--size--xl);
205311
margin-bottom: var(--pf-t--global--spacer--md);
206312
padding-bottom: var(--pf-t--global--spacer--sm);
207-
border-bottom: 1px solid var(--pf-t--global--border--color--default);
313+
border-bottom: var(--pf-t--global--border--width--divider--default) solid var(--pf-t--global--border--color--default);
208314
}
209315
}
210316

@@ -214,7 +320,7 @@
214320
.pf-v6-c-description-list__group {
215321
gap: var(--pf-t--global--spacer--xs);
216322
padding-bottom: var(--pf-t--global--spacer--sm);
217-
border-bottom: 1px solid var(--pf-t--global--border--color--default);
323+
border-bottom: var(--pf-t--global--border--width--divider--default) solid var(--pf-t--global--border--color--default);
218324
}
219325

220326
.pf-v6-c-description-list__term,

0 commit comments

Comments
 (0)