From 15a38172bb5f81249117b16d25abb894455f5752 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 19 Feb 2026 13:13:25 +0000 Subject: [PATCH 1/3] Fix superimposed plots ignoring card width setting The superimposed cards grid had its column width hardcoded via a SCSS variable ($metrics-min-card-width: 335px) and never read the dynamic cardMinWidth setting from the store. Regular card grids (CardGridComponent) receive cardMinWidth as an input and apply it via [style.grid-template-columns], which overrides the SCSS default. Superimposed cards were missing this entirely. Changes: - SuperimposedCardsViewContainer: select getMetricsCardMinWidth from the store and pass it as [cardMinWidth] to the presentation component. - SuperimposedCardsViewComponent: accept cardMinWidth input, compute gridTemplateColumn in ngOnChanges (same logic as CardGridComponent), and bind it via [style.grid-template-columns] on the grid div. Fixes #55 Co-authored-by: Samuel --- .../superimposed_cards_view_component.ts | 36 +++++++++++++++++-- .../superimposed_cards_view_container.ts | 8 +++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_component.ts b/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_component.ts index e2540c921c8..65f5952bd6f 100644 --- a/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_component.ts +++ b/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_component.ts @@ -12,7 +12,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -import {ChangeDetectionStrategy, Component, Input} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Input, + OnChanges, + SimpleChanges, +} from '@angular/core'; import {Store} from '@ngrx/store'; import {Observable} from 'rxjs'; import {State} from '../../../app_state'; @@ -21,6 +27,9 @@ import {SuperimposedCardMetadata} from '../../types'; import {superimposedCardFullWidthChanged} from '../../actions'; import {getFullWidthSuperimposedCards} from '../../store'; +const MIN_CARD_MIN_WIDTH_IN_PX = 335; +const MAX_CARD_MIN_WIDTH_IN_PX = 735; + @Component({ standalone: false, selector: 'superimposed-cards-view-component', @@ -39,7 +48,10 @@ import {getFullWidthSuperimposedCards} from '../../store'; -
+
>; cardsAtFullHeight = new Set(); @@ -69,6 +84,21 @@ export class SuperimposedCardsViewComponent { this.cardsAtFullWidth$ = this.store.select(getFullWidthSuperimposedCards); } + ngOnChanges(changes: SimpleChanges) { + if (changes['cardMinWidth']) { + const width = changes['cardMinWidth'].currentValue; + if ( + width && + width >= MIN_CARD_MIN_WIDTH_IN_PX && + width <= MAX_CARD_MIN_WIDTH_IN_PX + ) { + this.gridTemplateColumn = `repeat(auto-fill, minmax(${width}px, 1fr))`; + } else { + this.gridTemplateColumn = ''; + } + } + } + trackByCard(index: number, card: SuperimposedCardMetadata): string { return card.id; } diff --git a/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_container.ts b/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_container.ts index 15231d87808..1ccd19084ea 100644 --- a/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_container.ts +++ b/tensorbored/webapp/metrics/views/main_view/superimposed_cards_view_container.ts @@ -17,6 +17,7 @@ import {Store} from '@ngrx/store'; import {Observable} from 'rxjs'; import {startWith} from 'rxjs/operators'; import {State} from '../../../app_state'; +import {getMetricsCardMinWidth} from '../../../selectors'; import {getSuperimposedCardsWithMetadata} from '../../store'; import {SuperimposedCardMetadata} from '../../types'; import {CardObserver} from '../card_renderer/card_lazy_loader'; @@ -28,6 +29,7 @@ import {CardObserver} from '../card_renderer/card_lazy_loader'; `, changeDetection: ChangeDetectionStrategy.OnPush, @@ -35,11 +37,13 @@ import {CardObserver} from '../card_renderer/card_lazy_loader'; export class SuperimposedCardsViewContainer { @Input() cardObserver!: CardObserver; + readonly superimposedCards$: Observable; + readonly cardMinWidth$: Observable; + constructor(private readonly store: Store) { this.superimposedCards$ = this.store .select(getSuperimposedCardsWithMetadata) .pipe(startWith([])); + this.cardMinWidth$ = this.store.select(getMetricsCardMinWidth); } - - readonly superimposedCards$: Observable; } From fd8934087491231637107c75e641c7edf79c2001 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 19 Feb 2026 13:58:45 +0000 Subject: [PATCH 2/3] Fix tooltip dots shifted from curves after resize + refresh When a line chart has disableUpdate=true (card not yet visible via intersection observer), the container may be resized by persistResize restoring a saved height, or by a full-width class being applied asynchronously from the store. The ResizeDetectorDirective's skip(1) can batch this resize with the initial ResizeObserver event, causing the only notification to be swallowed. The chart then holds stale dimensions from ngAfterViewInit, so the renderer draws curves at one scale while the interactive overlay positions tooltip dots at another. Fix: when disableUpdate transitions from true to false, re-read the DOM dimensions and resize the chart renderer so both the canvas and the coordinate mapping match the current layout. Co-authored-by: Samuel --- .../widgets/line_chart_v2/line_chart_component.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts b/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts index b7cbf9d5f78..51eb4c06b2a 100644 --- a/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts +++ b/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts @@ -250,6 +250,21 @@ export class LineChartComponent this.setIsViewBoxOverridden(false); } + // When the chart transitions from disabled to enabled, the container may + // have been resized while updates were suppressed (e.g. persistResize + // restoring a height, or a full-width toggle applied asynchronously). + // The ResizeDetectorDirective's skip(1) can swallow the only + // ResizeObserver event in that window, leaving the renderer and the + // interactive overlay with stale dimensions. Re-read and apply now. + if ( + changes['disableUpdate'] && + !this.disableUpdate && + this.lineChart + ) { + this.readAndUpdateDomDimensions(); + this.lineChart.resize(this.domDimensions.main); + } + this.isViewBoxChanged = this.isViewBoxChanged || this.userViewBoxUpdated || From cbcf40b37a3b28875204c9ad4289d68326251a8a Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 19 Feb 2026 14:35:03 +0000 Subject: [PATCH 3/3] Fix prettier formatting in line_chart_component.ts Co-authored-by: Samuel --- .../webapp/widgets/line_chart_v2/line_chart_component.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts b/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts index 51eb4c06b2a..911b76abd9d 100644 --- a/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts +++ b/tensorbored/webapp/widgets/line_chart_v2/line_chart_component.ts @@ -256,11 +256,7 @@ export class LineChartComponent // The ResizeDetectorDirective's skip(1) can swallow the only // ResizeObserver event in that window, leaving the renderer and the // interactive overlay with stale dimensions. Re-read and apply now. - if ( - changes['disableUpdate'] && - !this.disableUpdate && - this.lineChart - ) { + if (changes['disableUpdate'] && !this.disableUpdate && this.lineChart) { this.readAndUpdateDomDimensions(); this.lineChart.resize(this.domDimensions.main); }