Skip to content

feat(visualization): redesign color settings popover - #4486

Merged
ChristianHuehn merged 7 commits into
mainfrom
feature/restyle-color-settings-popover
Jun 12, 2026
Merged

feat(visualization): redesign color settings popover#4486
ChristianHuehn merged 7 commits into
mainfrom
feature/restyle-color-settings-popover

Conversation

@ChristianHuehn

@ChristianHuehn ChristianHuehn commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Single-column layout following the new design mockup: header with metric name and reset-thresholds icon, compact quantile distribution chart, segmented gradient-mode control, color bands with building counts, and a folder overrides section to pin, recolor, and unpin fixed folder colors (backed by marked packages) with a scrollable list and folder search.

Colors are picked through a new inline color picker that renders inside the native popover, since the previous overlay-based picker light-dismissed the popover. Reset colors now also resets the gradient mode.

{Meaningful title}

Please read the CONTRIBUTING.md before opening a PR.

Closes: #

Description

Descriptive pull request text, answering:

  • What problem/issue are you fixing?
  • What does this PR implement and how?

Definition of Done

A PR is only ready for merge once all the following acceptance criteria are fulfilled:

  • Changes have been manually tested
  • All TODOs related to this PR have been closed
  • There are automated tests for newly written code and bug fixes
  • All bugs discovered while working on this PR have been submitted as issues (if not already an open issue)
  • Documentation (GH-pages, analysis/visualization READMEs, parser READMEs, --help, etc.) has been updated (almost always necessary except for bug fixes)
  • CHANGELOG.md has been updated

Screenshots or gifs

Summary by CodeRabbit

  • New Features

    • Folder overrides in the Color popover: pin/unpin folders, view file counts, recolor via swatches, and pin via inline search.
    • Inline color picker for band and folder recoloring; gradient-mode radio picker and refined band/selected-row controls.
  • Changed

    • Color settings popover restyled to a single-column layout with reordered controls, resized distribution diagram, and updated floating metrics bar spacing. Reset colors now also resets gradient mode.
  • Bug Fixes

    • Improved picker light-dismiss, search auto-close/mousedown handling, list scrolling/density, invert/reset placement, and other picker/search interaction edge cases.

Single-column layout following the new design mockup: header with
metric name and reset-thresholds icon, compact quantile distribution
chart, segmented gradient-mode control, color bands with building
counts, and a folder overrides section to pin, recolor, and unpin
fixed folder colors (backed by marked packages) with a scrollable
list and folder search.

Colors are picked through a new inline color picker that renders
inside the native popover, since the previous overlay-based picker
light-dismissed the popover. Reset colors now also resets the
gradient mode.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors the Color settings popover into modular single-column sections, adds an inline color picker and gradient-mode radios, implements folder overrides (pin/recolor/unpin) with selectors/stores/services, updates diagram sizing and reset button sizing, and adds comprehensive unit tests and plan/changelog updates.

Changes

Color Settings Popover Restyle with Folder Overrides

Layer / File(s) Summary
Plan & Documentation
plans/2026-05-13-redesign-color-settings-popover.md, plans/color_metric_popover/2026-06-11-restyle-color-metric-popover.md, visualization/CHANGELOG.md
Design plan marked complete and superseded by the new restyle plan; changelog updated with Folder overrides and popover layout/control changes.
Inline Color Picker Component
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.ts, .html, .spec.ts
New inline color picker with signal-driven open state, viewport-aware fixed panel placement, containment-based light-dismiss, pending-change buffering, and colorChange emission.
Folder Path & Marked Package Selectors
visualization/app/codeCharta/features/metricsBar/selectors/markableFolderPaths.selector.ts, .spec.ts, markedPackagesWithCounts.selector.ts, .spec.ts
Selectors collect markable folder paths and compute marked packages annotated with file counts, attributing files to the deepest matching marked package and sorting outputs.
Color Band Row Component
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.ts, .html, .spec.ts
Standalone component that displays a band row with inline recoloring, resolves its color from store state, renders a localized label, and optionally shows a count badge; calls setMapColors on recolor.
Color Bands Section
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandsSection.component.ts, .html, .spec.ts
Section rendering band rows for delta and non-delta modes and exposing color-category counts from the render service.
Color Range Section
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorRangeSection.component.ts, .html, .spec.ts
Range slider + distribution diagram wired to ColorRangeService with debounced commits and flush-on-destroy behavior.
Metric Diagram Configurable Sizing
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/metricColorRangeDiagram.component.ts, .spec.ts
Adds diagramWidth, diagramHeight, and showAxisLabels inputs; ngOnChanges triggers re-render and rendering respects showAxisLabels for margins/labels.
Gradient Mode Picker
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/gradientModePicker.component.ts, .html, .spec.ts
Radio-group component exposing four gradient modes with isolated group names and dispatch via ColorModeService.
Invert + Reset Row
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/invertResetRow.component.ts, .html, .spec.ts
Component showing appropriate invert checkbox (range vs delta) and a reset button whose keys depend on delta state; handlers call MapColorsService inversion methods.
Header & Popover Integration
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsHeader.component.ts, .html, .spec.ts; colorSettingsPopover.component.ts, .html, .spec.ts
Header with swatch/metric label and reset thresholds; main popover refactored to compose child components, simplified DI, and a hasRangeSection computed signal controlling range/gradient visibility.
Folder Overrides UI & Rows
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts, .html, .spec.ts; folderOverrideRow.component.ts, .html
FolderOverrides component listing pinned folders with counts, recolor/unpin handlers, and pinning via inline search; per-row component for recolor/unpin interactions.
Pin Folder Search
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/pinFolderSearch.component.ts, .html
Inline folder search UI for pinning: local filtering, Escape/blur behavior, suggestion mousedown prevention, and limited suggestion count.
Folder Overrides Store & Service
visualization/app/codeCharta/features/metricsBar/stores/folderOverrides.store.ts, visualization/app/codeCharta/features/metricsBar/services/folderOverrides.service.ts
Store wrapper exposing markedPackagesWithCounts$ and markableFolderPaths$ and imperative mark/unmark methods; service forwards to the store and is provided in root.
MapColors Store & Service Updates
visualization/app/codeCharta/features/metricsBar/stores/mapColors.store.ts, visualization/app/codeCharta/features/metricsBar/services/mapColors.service.ts
Added setMapColors methods to store and service to accept partial MapColors updates and dispatch setMapColors action.
Reset Button Small Variant
visualization/app/codeCharta/ui/resetSettingsButton/resetSettingsButton.component.ts, .html
Adds optional small input to toggle compact btn-sm styling on the reset button.
Tests (many components)
visualization/app/codeCharta/features/metricsBar/** (spec files across components)
Extensive new and updated unit/integration tests covering picker behavior, debounced commits, folder pin/search flows, marked-package counting, band rendering, diagram labels/sizing, and header/reset logic.

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~45 minutes

"I hopped through code with careful paws,
A swatch, a band, a popover that awes.
Folders pinned and colors bright,
Radios glow in single-column light,
I nibble bugs and dance in bytes."

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description is partially filled: it includes a concise summary of the implemented changes (header, distribution chart, gradient mode, color bands, folder overrides, inline color picker, and reset behavior) but the Definition of Done checklist is incomplete with all items unchecked, and no issue reference is provided. Complete the Definition of Done checklist by checking off fulfilled items, add a reference to the related GitHub issue in the 'Closes:' field, and optionally add screenshots/GIFs demonstrating the new popover layout.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: redesigning the color settings popover into a single-column layout with new components and interactions.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/restyle-color-settings-popover

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts (2)

23-25: 💤 Low value

Consider defensive handling for selector synchronization.

The requireSync: true option on Lines 23-25 will throw an error if the selectors don't emit synchronously. While this may be intentional to catch configuration errors early, it makes the component fragile during initialization or testing.

♻️ Alternative: Provide default values
-    readonly overrides = toSignal(this.store.select(markedPackagesWithCountsSelector), { requireSync: true })
-    private readonly folderPaths = toSignal(this.store.select(markableFolderPathsSelector), { requireSync: true })
-    private readonly mapColors = toSignal(this.store.select(mapColorsSelector), { requireSync: true })
+    readonly overrides = toSignal(this.store.select(markedPackagesWithCountsSelector), { initialValue: [] })
+    private readonly folderPaths = toSignal(this.store.select(markableFolderPathsSelector), { initialValue: [] })
+    private readonly mapColors = toSignal(this.store.select(mapColorsSelector))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts`
around lines 23 - 25, The component currently uses toSignal(...) with
requireSync: true for overrides, folderPaths, and mapColors (from
markedPackagesWithCountsSelector, markableFolderPathsSelector, and
mapColorsSelector) which will throw if the selectors do not emit synchronously;
change to a defensive pattern by removing requireSync or setting it to false and
provide safe default values so the component can initialize without synchronous
selector emissions (e.g., use toSignal(this.store.select(...), { requireSync:
false }) or ensure the selector stream is seeded with a default via startWith)
and update any code that assumes immediate non-null values to handle the default
until the real selector emits.

47-50: ⚡ Quick win

Add cleanup for the setTimeout to prevent potential memory leaks.

The setTimeout on Line 49 schedules focus without tracking the timer ID. If the component is destroyed before the timeout fires, the callback will attempt to access the destroyed view reference, potentially causing errors or memory leaks.

♻️ Proposed fix using Angular's `afterNextRender`
-import { ChangeDetectionStrategy, Component, computed, ElementRef, inject, signal, viewChild } from "`@angular/core`"
+import { afterNextRender, ChangeDetectionStrategy, Component, computed, ElementRef, inject, signal, viewChild } from "`@angular/core`"
+    private readonly focusInputAfterRender = afterNextRender(() => {
+        if (this.isPinning()) {
+            this.pinInput()?.nativeElement.focus()
+        }
+    })
+
     startPinning() {
         this.isPinning.set(true)
-        setTimeout(() => this.pinInput()?.nativeElement.focus())
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts`
around lines 47 - 50, The startPinning method schedules a focus with setTimeout
but doesn't store the timer ID; modify startPinning (in
folderOverrides.component.ts) to capture the returned timeout ID (e.g.,
this.focusTimeoutId = setTimeout(...)) and ensure the callback uses existing
pinInput()?nativeElement.focus(), then implement ngOnDestroy in the same
component to call clearTimeout(this.focusTimeoutId) to cancel any pending timer
and prevent the callback from running after component teardown.
visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.html (1)

21-23: ⚡ Quick win

Verify accessibility: Ensure the unpin button has appropriate ARIA label.

The unpin button on Line 21 uses a title attribute but no explicit aria-label. Screen readers may not announce the button's purpose clearly, especially since the visible content is just an icon (fa-times).

♿ Proposed fix to add ARIA label
-                <button class="btn btn-ghost btn-xs btn-square" [title]="'Unpin ' + override.path" (click)="handleUnpin(override.path)">
+                <button class="btn btn-ghost btn-xs btn-square" [attr.aria-label]="'Unpin ' + override.path" [title]="'Unpin ' + override.path" (click)="handleUnpin(override.path)">
                     <i class="fa fa-times"></i>
                 </button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.html`
around lines 21 - 23, Add an explicit ARIA label to the unpin button so screen
readers announce its purpose: update the button element that calls
handleUnpin(override.path) to include an aria-label (e.g., aria-label="'Unpin '
+ override.path" or use the same i18n string as the title) so the icon-only
button has accessible text describing the action.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.spec.ts`:
- Around line 19-20: Split the combined "// Arrange & Act" comments into three
explicit comment blocks "// Arrange", "// Act", and "// Assert" in the unit
test(s) that call setup({ mapColorFor: "positive", count: 312 }) (and the
related tests at the other occurrences mentioned), so that the setup call and
any preconditions are under "// Arrange", the awaited setup invocation (or
actions that trigger behavior) are under "// Act", and the expectations
(expect(...) assertions) are under "// Assert"; update all three occurrences
(lines with setup and the two other paired lines) to follow this AAA pattern
consistently.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.html`:
- Line 16: Remove the invalid ARIA role by deleting role="colorpicker" from the
color-chrome element in inlineColorPicker.component.html (the color-chrome
element referenced in the diff), and if necessary replace it with appropriate
accessible attributes such as aria-label or aria-describedby to convey purpose
rather than an unsupported role.

---

Nitpick comments:
In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.html`:
- Around line 21-23: Add an explicit ARIA label to the unpin button so screen
readers announce its purpose: update the button element that calls
handleUnpin(override.path) to include an aria-label (e.g., aria-label="'Unpin '
+ override.path" or use the same i18n string as the title) so the icon-only
button has accessible text describing the action.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts`:
- Around line 23-25: The component currently uses toSignal(...) with
requireSync: true for overrides, folderPaths, and mapColors (from
markedPackagesWithCountsSelector, markableFolderPathsSelector, and
mapColorsSelector) which will throw if the selectors do not emit synchronously;
change to a defensive pattern by removing requireSync or setting it to false and
provide safe default values so the component can initialize without synchronous
selector emissions (e.g., use toSignal(this.store.select(...), { requireSync:
false }) or ensure the selector stream is seeded with a default via startWith)
and update any code that assumes immediate non-null values to handle the default
until the real selector emits.
- Around line 47-50: The startPinning method schedules a focus with setTimeout
but doesn't store the timer ID; modify startPinning (in
folderOverrides.component.ts) to capture the returned timeout ID (e.g.,
this.focusTimeoutId = setTimeout(...)) and ensure the callback uses existing
pinInput()?nativeElement.focus(), then implement ngOnDestroy in the same
component to call clearTimeout(this.focusTimeoutId) to cancel any pending timer
and prevent the callback from running after component teardown.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7e153ff0-4030-4129-8cfa-2dfb18aba56c

📥 Commits

Reviewing files that changed from the base of the PR and between 2ee1594 and c7c7f59.

⛔ Files ignored due to path filters (1)
  • plans/color_metric_popover/restyle_color_metric.png is excluded by !**/*.png
📒 Files selected for processing (22)
  • plans/2026-05-13-redesign-color-settings-popover.md
  • plans/color_metric_popover/2026-06-11-restyle-color-metric-popover.md
  • visualization/CHANGELOG.md
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsPopover.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsPopover.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsPopover.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/metricColorRangeDiagram.component.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markableFolderPaths.selector.spec.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markableFolderPaths.selector.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markedPackagesWithCounts.selector.spec.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markedPackagesWithCounts.selector.ts
  • visualization/app/codeCharta/ui/resetSettingsButton/resetSettingsButton.component.html
  • visualization/app/codeCharta/ui/resetSettingsButton/resetSettingsButton.component.ts

Comment on lines +19 to +20
// Arrange & Act
await setup({ mapColorFor: "positive", count: 312 })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use explicit separate AAA comments instead of combined Arrange & Act.

Please split these into distinct // Arrange, // Act, // Assert sections to match the repository’s test pattern consistently.

As per coding guidelines, "Use Arrange-Act-Assert pattern with comments in tests".

Also applies to: 27-28, 36-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.spec.ts`
around lines 19 - 20, Split the combined "// Arrange & Act" comments into three
explicit comment blocks "// Arrange", "// Act", and "// Assert" in the unit
test(s) that call setup({ mapColorFor: "positive", count: 312 }) (and the
related tests at the other occurrences mentioned), so that the setup call and
any preconditions are under "// Arrange", the awaited setup invocation (or
actions that trigger behavior) are under "// Act", and the expectations
(expect(...) assertions) are under "// Assert"; update all three occurrences
(lines with setup and the two other paired lines) to follow this AAA pattern
consistently.

Source: Coding guidelines

ChristianHuehn and others added 4 commits June 11, 2026 14:44
Addresses all findings from the code review of the popover redesign:

- Inline color picker closes on pointerdown instead of click, so a drag
  released outside the panel no longer discards the picked color; a
  pending color is emitted if closing races the debounced change event
- Picker panel also closes on container scroll, window resize, and
  popover close instead of floating at stale viewport coordinates
- Escape cancels the folder search without light-dismissing the popover
- Suggestion mousedown preventDefault moved off the list so the
  scrollbar stays draggable
- Folder override copy corrected (marking colors tint folder floors)
  and counts got a "n files" tooltip
- Excluded nodes no longer counted or suggested; count attribution is
  an O(leaves x depth) path walk-up instead of O(leaves x packages)
- Nested pins avoid their marked parent's color, which the reducer
  would drop as redundant
- rounded-btn (removed in DaisyUI 5) replaced with rounded-md
- Gradient mode group exposes role=radiogroup with a per-popover radio
  name; reset tooltip no longer mentions gradient mode in delta mode
- Components rewired through feature stores/services to satisfy the
  dependency-cruiser ngrx boundary rule
- New tests covering the above plus header threshold reset and the
  diagram size inputs

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The popover and folder overrides templates had grown too large to read.
The popover is now a thin composition of focused section components:

- cc-color-settings-header (metric name, gradient dot, reset thresholds)
- cc-color-range-section (threshold slider + distribution diagram)
- cc-gradient-mode-picker (segmented control)
- cc-color-bands-section (band rows with counts)
- cc-invert-reset-row (invert toggle + reset colors)
- cc-folder-override-row / cc-pin-folder-search (extracted from
  cc-folder-overrides)

Each section owns its service wiring, and the moved logic took its
tests along (debounced threshold commit, threshold reset, inversion
flags, reset keys, gradient mode dispatch). No behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Replace the label-styled wrapper around the folder search with a div
  and give the input an aria-label (Web:S6853)
- Drop the invalid "colorpicker" ARIA role from the inline picker
  (Web:S6821)
- Type the inline picker's ElementRef as HTMLElement so the remaining
  target cast is meaningful (typescript:S4325)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts`:
- Around line 41-48: The code assumes markingColors has at least one entry
before returning markingColors[0]; add a guard for an empty markingColors array
in the function that uses mapColors() and findMarkedParentColor(path): if
markingColors.length === 0 return a safe fallback (e.g., undefined or a known
default color) instead of indexing markingColors[0], so no invalid color is
passed into markPackage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 40e56fec-2870-4b7e-820e-440ecc820761

📥 Commits

Reviewing files that changed from the base of the PR and between 9403ace and f0ae716.

📒 Files selected for processing (39)
  • plans/color_metric_popover/2026-06-11-restyle-color-metric-popover.md
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandsSection.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandsSection.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandsSection.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorRangeSection.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorRangeSection.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorRangeSection.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsHeader.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsHeader.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsHeader.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsPopover.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsPopover.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorSettingsPopover.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrideRow.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrideRow.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/gradientModePicker.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/gradientModePicker.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/gradientModePicker.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/invertResetRow.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/invertResetRow.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/invertResetRow.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/metricColorRangeDiagram.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/pinFolderSearch.component.html
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/pinFolderSearch.component.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markableFolderPaths.selector.spec.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markableFolderPaths.selector.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markedPackagesWithCounts.selector.spec.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markedPackagesWithCounts.selector.ts
  • visualization/app/codeCharta/features/metricsBar/services/folderOverrides.service.ts
  • visualization/app/codeCharta/features/metricsBar/services/mapColors.service.ts
  • visualization/app/codeCharta/features/metricsBar/stores/folderOverrides.store.ts
  • visualization/app/codeCharta/features/metricsBar/stores/mapColors.store.ts
✅ Files skipped from review due to trivial changes (3)
  • visualization/app/codeCharta/features/metricsBar/services/folderOverrides.service.ts
  • visualization/app/codeCharta/features/metricsBar/stores/folderOverrides.store.ts
  • plans/color_metric_popover/2026-06-11-restyle-color-metric-popover.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.html
  • visualization/app/codeCharta/features/metricsBar/selectors/markedPackagesWithCounts.selector.spec.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markableFolderPaths.selector.spec.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/colorBandRow.component.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.spec.ts
  • visualization/app/codeCharta/features/metricsBar/selectors/markedPackagesWithCounts.selector.ts
  • visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/inlineColorPicker.component.ts

Comment on lines +41 to +48
const markingColors = this.mapColors().markingColors
// a pin with its marked parent's color is dropped as redundant by the reducer,
// so that color must not be handed out for a nested pin
const parentColor = this.findMarkedParentColor(path)
const candidates = markingColors.filter(color => color !== parentColor)
if (candidates.length === 0) {
return markingColors[0]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Guard empty markingColors before fallback indexing.

At Line 47, markingColors[0] is returned when candidates is empty. If markingColors is empty, this yields undefined and propagates an invalid color into markPackage.

Suggested fix
 private nextMarkingColor(path: string) {
     const markingColors = this.mapColors().markingColors
+    if (markingColors.length === 0) {
+        return defaultMapColors.markingColors[0]
+    }
     // a pin with its marked parent's color is dropped as redundant by the reducer,
     // so that color must not be handed out for a nested pin
     const parentColor = this.findMarkedParentColor(path)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@visualization/app/codeCharta/features/metricsBar/components/colorSettingsPopover/folderOverrides.component.ts`
around lines 41 - 48, The code assumes markingColors has at least one entry
before returning markingColors[0]; add a guard for an empty markingColors array
in the function that uses mapColors() and findMarkedParentColor(path): if
markingColors.length === 0 return a safe fallback (e.g., undefined or a known
default color) instead of indexing markingColors[0], so no invalid color is
passed into markPackage.

christian-huehn-mw and others added 2 commits June 11, 2026 16:39
Resolves Sonar S4325 on the color picker outside-click handler.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@ChristianHuehn
ChristianHuehn merged commit 80dfe91 into main Jun 12, 2026
8 checks passed
@ChristianHuehn
ChristianHuehn deleted the feature/restyle-color-settings-popover branch June 12, 2026 05:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants