Skip to content

feat: Box plot for mosaic dashboards - #588

Merged
dmitriy-kostianetskiy merged 29 commits into
mainfrom
feat--Box-plot-for-mosaic-dashboards
May 14, 2026
Merged

dmitriy-kostianetskiy merged 29 commits into
mainfrom
feat--Box-plot-for-mosaic-dashboards

Conversation

@ilyabo

@ilyabo ilyabo commented May 5, 2026 •

Copy link
Copy Markdown
Collaborator

Solving #606

image

Summary by CodeRabbit

  • New Features

    • Added Box Plot chart with Observable Plot rendering and interactive Y-axis brushing
    • Chart builder now supports both spec-based and renderer-based chart outputs; dashboard panels can host either
  • Improvements

    • Generalized dashboard chart panel infrastructure and settings UI for broader chart types and retention/brush handling
    • New spec viewer, error handling, and client-side box-plot data queries for summaries/outliers
  • Documentation

    • Updated examples and README to demonstrate new chart panel and box-plot usage
  • Dependencies

    • Added Observable Plot for advanced chart rendering

@coderabbitai

coderabbitai Bot commented May 5, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Refactors chart types from a vgplot-only model to a unified ChartConfig/ChartType system, adds a component-based Box Plot (client, renderer, utilities, tests), relocates chart-settings to shared chart modules, and updates dashboard panel types/factories to use chart-panel configs.

Changes

Unified chart model, Box Plot feature, and dashboard integration

Layer / File(s) Summary
Chart type core & types
packages/mosaic/src/chart-types/base-types.ts, packages/mosaic/src/chart-types/chart-config.ts, packages/mosaic/src/chart-types/tool-types.ts
Replace VgPlot-specific types with ChartConfig/ChartType, introduce SpecChartTypeDefinition and ComponentChartTypeDefinition, add type-guards isSpecChartType/isComponentChartType, and update tool-type contracts to use ChartConfig.
Registry → store lookup & hooks
packages/mosaic/src/chart-types/registry.ts (removed), packages/mosaic/src/chart-types/useChartTypeDefinition.ts, packages/mosaic/src/chart-types/index.ts
Remove module-level registry and auto-registration; add useChartTypeDefinition to resolve chart types from dashboard store; update public re-exports to the new chart types.
Box Plot client & SQL
packages/mosaic/src/boxplot/BoxPlotClient.ts, packages/mosaic/__tests__/BoxPlotClient.test.ts
Add BoxPlotClient (query building with CTEs for quartiles/fences/whiskers, parsing of summaries/outliers), lifecycle (queryPending/result/error), updateYBrush/reset, and tests covering SQL generation, selection predicates, brush normalization, and result parsing.
Box Plot renderer & utilities
packages/mosaic/src/chart-types/box-plot/renderer/* (BoxPlotPanelRenderer.tsx, plot.ts, utils.ts, constants.ts, useBoxPlotClient.ts, BoxPlotErrorBoundary.tsx)
Add a React renderer using @observablehq/plot, plot creation helper, pixel↔value utilities, rendering constants, brush interaction (pointer-driven Y-brush), hook to wire BoxPlotClient, and an error boundary.
Box Plot type & schema
packages/mosaic/src/chart-types/box-plot/definition.ts, packages/mosaic/src/chart-types/box-plot/schema.ts
Migrate boxPlotChartType to a ComponentChartTypeDefinition<BoxPlotChartConfig> with renderer: BoxPlotPanelRenderer; make x/y required in schema and remove prior spec file.
Spec chart types migration
packages/mosaic/src/chart-types/{histogram,line-chart,count-plot,heatmap,bubble-chart,custom-spec}/definition.ts and spec.ts (custom-spec)
Switch existing vgplot chart definitions to SpecChartTypeDefinition<...Config>. Move custom-spec spec generation into createCustomSpec.
Chart settings refactor
packages/mosaic/src/chart/chart-settings/*, packages/mosaic/src/chart/chart-settings/ChartSettingsContext.tsx
Relocate chart settings from dashboard namespace to shared chart/chart-settings, generalize context and providers to ChartConfig, add ExtractChartConfig<T> overloads, and update ChartSettings to use useChartTypeDefinition and render settings via createElement.
Spec generation hook & utilities
packages/mosaic/src/chart/useGenerateSpec.ts, packages/mosaic/src/dashboard/utils.ts, packages/mosaic/src/chart/chart-settings/ChartSpecViewerPanel.tsx
Add useGenerateSpec hook that memoizes spec creation with error handling (returns ChartSpecError), add toRenderableMosaicSpec for validation/conversion, and refactor spec viewer to accept a Spec.
Dashboard panel type & factories
packages/mosaic/src/dashboard/MosaicDashboardSlice.ts, packages/mosaic/src/dashboard/defaultPanelRenderers.ts
Replace vgplot panel type with generic chart panel type (MOSAIC_DASHBOARD_CHART_PANEL_TYPE), add ChartPanelConfig, createMosaicDashboardChartPanelConfig factory, update eviction/type-guards and default renderer registration to use the new chart renderer.
Dashboard chart rendering layer
packages/mosaic/src/chart/* (MosaicDashboardChartRenderer.tsx, MosaicDashboardChart.tsx, MosaicDashboardChartContent.tsx, MosaicDashboardComponentChart.tsx, MosaicDashboardVgPlotChart.tsx, MosaicDashboardVgPlotError.tsx, header actions)
Introduce chart-panel rendering components: resolve chartType via store hook, branch between spec-based (VgPlotChart) and component-based renderers, wire settings drawer, retention and brush params, and provide header actions/renderer registration.
Chart builder & callers
packages/mosaic/src/chart-builders/*, apps/sqlrooms-cli-ui/src/createChartToolDeps.ts, examples/deckgl-mosaic/src/components/filters/FiltersPanel.tsx, examples/deckgl-mosaic/src/components/filters/filterPlots.ts
Propagate ChartConfig types across chart-builder flow (onCreateChart, context, dialog, fields, store); update example and CLI to call createMosaicDashboardChartPanelConfig and handle ChartConfig/chartTypes, adjust example filter chart item typing.
Tests, docs, deps
packages/mosaic/__tests__/*, packages/mosaic/README.md, packages/mosaic/package.json
Update/add tests to reflect new types and renderer pattern (add box-plot tests, remove old spec-generation test), document box-plot and dashboard changes in README, and add @observablehq/plot dependency.
sequenceDiagram
    participant User
    participant Dashboard
    participant Store
    participant ChartRenderer
    participant TypeDef
    participant ChartContent
    participant SpecChart
    participant CompChart
    participant BoxPlotRenderer
    participant BoxPlotClient
    User->>Dashboard: create panel (createMosaicDashboardChartPanelConfig)
    Dashboard->>Store: add panel
    Store->>ChartRenderer: render panel
    ChartRenderer->>TypeDef: useChartTypeDefinition(chartType)
    TypeDef-->>ChartRenderer: ChartTypeDefinition
    ChartRenderer->>ChartContent: dispatch by chart type
    alt spec-based
        ChartContent->>SpecChart: render VgPlot chart (useGenerateSpec)
        SpecChart->>Store: request data (coordinator)
        SpecChart-->>User: render VgPlot
    else component-based (box-plot)
        ChartContent->>CompChart: createElement(renderer, props)
        CompChart->>BoxPlotRenderer: mount
        BoxPlotRenderer->>BoxPlotClient: useBoxPlotClient (query)
        BoxPlotClient->>Store: execute SQL
        Store-->>BoxPlotClient: rows
        BoxPlotClient-->>BoxPlotRenderer: summaries/outliers
        BoxPlotRenderer-->>User: render Observable Plot
        User->>BoxPlotRenderer: brush Y
        BoxPlotRenderer->>BoxPlotClient: updateYBrush -> update selection
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • Dashboards: box plot #606: Implements a component-based Box Plot with server-side quartile/fence computation and Y-axis brushing, addressing that issue's objectives.

Possibly related PRs

  • sqlrooms/sqlrooms#581: Overlaps on migrating dashboard panel factory usage from vgplot-specific helpers to chart-panel factories.

Suggested labels

codex

Suggested reviewers

  • dmitriy-kostianetskiy
  • bdjulbic
  • mihajlo-stojkovic

Poem

🐇 I hopped from vgplot to charts anew,
Boxes and whiskers in tidy view—
With queries that crunch, and brushes that play,
A rabbit-made plot to brighten your day.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat--Box-plot-for-mosaic-dashboards

@ilyabo
ilyabo force-pushed the feat--Box-plot-for-mosaic-dashboards branch from 8ce43bb to 38ecc15 Compare May 5, 2026 13:22
This was referenced May 6, 2026
dmitriy-kostianetskiy and others added 17 commits May 11, 2026 15:55
- Add renderer component pattern to ChartTypeDefinition
- Remove createSpec from interface (logic moves to renderers)
- Create HistogramRenderer as example
- Define ChartRendererProps interface

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Completes Task 4 of the box-plot migration plan by creating dedicated
renderer components for all remaining vgPlot chart types.

Chart types migrated:
- line-chart: LineChartRenderer
- bubble-chart: BubbleChartRenderer
- count-plot: CountPlotRenderer
- ecdf: EcdfRenderer
- heatmap: HeatmapRenderer
- custom-spec: CustomSpecRenderer

Each renderer follows the established pattern:
- Generates vgPlot spec internally using useMemo
- Renders via VgPlotChart component
- Depends on tableName and settings for proper memoization

The createSpec logic from each definition has been moved directly into
the corresponding renderer component, preserving all existing behavior
including styling constants, mark types, and crossfilter configuration.

Backward compatibility:
- Added deprecated createSpec/outputKind/createOutput fields to
  ChartTypeDefinition to maintain compatibility during transition
- Added BoxPlotStubRenderer as temporary placeholder for Task 5
- Updated toChartTypeDefinition helper to include renderer field

This establishes a uniform pattern where ALL chart types specify a
renderer component, setting the stage for Task 6 to update the
dashboard to use renderers directly.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Create BoxPlotPanelRenderer in chart-types/box-plot/
- Adapt existing BoxPlotClient integration
- Update definition to use BoxPlotPanelRenderer
- Preserve all custom rendering and interaction logic

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Update ChartRendererProps to include params and retention
- Update all chart renderer components to accept and forward params/retention to VgPlotChart
- Update MosaicDashboardVgPlotPanelRenderer to use chartType.renderer instead of pre-generated spec
- Remove toRenderableMosaicSpec helper (no longer needed)
- Update chart builders to work with renderer pattern:
  - Use createOutput for custom dashboard panels (box-plot)
  - Create vgplot panels with chartType and settings (no pre-generated spec)
- Keep createSpec, createOutput, outputKind as deprecated fields for backward compatibility
- Simplify rendering logic: dashboard gets renderer from chart type and passes it the required props

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Remove BoxPlotStubRenderer (temporary placeholder, no longer needed)
- Remove backward compatibility fields from box-plot definition (outputKind, createOutput)
- Remove box-plot to boxplot panel type conversion logic from VgPlotPanelRenderer
- Update ChartSettings to not pre-generate vgplot specs (renderers generate specs internally)
- Deprecate generateMosaicChartSpec function
- Remove generateMosaicChartSpec tests (function is deprecated)
- Update chartTypes tests to reflect new renderer pattern

All chart types now use the unified renderer pattern:
- VgPlot charts generate specs internally in their renderers
- Box-plot uses custom BoxPlotClient rendering via BoxPlotPanelRenderer
- Dashboard calls renderer components which handle their own spec generation

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
…ashboardVgPlotError components for improved user experience

Co-authored-by: Copilot <[email protected]>
…d add createSpec methods for enhanced functionality

Co-authored-by: Copilot <[email protected]>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/mosaic/src/index.ts (1)

189-215: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Internal VgPlot naming migration is incomplete and lacks deprecation documentation.

The backward-compatibility alias at line 39 provides compatibility for the old MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE name, but internal usages remain heavily tied to VgPlot* naming:

  • VgPlotChart component (packages/mosaic/src/VgPlotChart.tsx) and its types (RetainedVgPlotChart, ChartBuilderVgPlotOutput) are still the canonical internal implementation
  • Multiple dashboard and chart files import and use VgPlotChart and RetainedVgPlotChart directly (MosaicDashboardVgPlotChart.tsx, MosaicDashboardVgPlotError.tsx, base-types.ts, etc.)
  • The panel type constant value remains 'vgplot' in the slice

If the intent is to migrate fully to Chart* naming, internal types and the component should be renamed. If VgPlot* is meant as an internal implementation detail, that should be documented (currently no deprecation notice exists for the old alias).

🤖 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 `@packages/mosaic/src/index.ts` around lines 189 - 215, The codebase still
mixes old VgPlot* names with new Chart* names and lacks deprecation
documentation for the alias MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE; to fix, pick one
approach and make changes consistently: either fully migrate internals to Chart*
(rename VgPlotChart -> ChartChart or ChartComponent, RetainedVgPlotChart ->
RetainedChart, ChartBuilderVgPlotOutput -> ChartBuilderOutput, update imports in
MosaicDashboardVgPlotChart.tsx, MosaicDashboardVgPlotError.tsx, base-types.ts,
slice where panel type value 'vgplot' is used) or explicitly mark VgPlot* as
private/legacy by adding clear deprecation comments and export a compatibility
alias that logs the deprecation and points to the new Chart* names; update the
MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE handling to document the legacy name and
ensure all internal references are aligned with the chosen approach.
🧹 Nitpick comments (4)
packages/mosaic/src/boxplot/BoxPlotClient.ts (1)

68-79: 💤 Low value

Minor: Array.from is redundant.

The toArray() method already returns an array, so wrapping it in Array.from is unnecessary. However, this doesn't cause any issues.

♻️ Simplification
-  return Array.from((data as {toArray(): T[]}).toArray());
+  return (data as {toArray(): T[]}).toArray();
🤖 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 `@packages/mosaic/src/boxplot/BoxPlotClient.ts` around lines 68 - 79, The
rowsFromQueryResult function redundantly wraps the toArray() result in
Array.from; change the return to directly return the array from toArray() (e.g.,
return (data as {toArray(): T[]}).toArray();), keeping the existing guards
intact so rowsFromQueryResult<T> still validates data and then returns the
toArray() result without the extra Array.from call.
packages/mosaic/__tests__/ChartSettings.test.tsx (1)

45-74: ⚡ Quick win

Consider using parameterized tests instead of forEach for better failure diagnostics.

When a test fails inside forEach, the error message doesn't clearly indicate which chart type caused the failure. Jest provides it.each for this purpose.

♻️ Suggested refactor using it.each
-    it('renders with different chart types', () => {
-      const chartTypes: ChartConfig['chartType'][] = [
-        'histogram',
-        'count-plot',
-        'line-chart',
-        'heatmap',
-        'box-plot',
-        'bubble-chart',
-      ];
-
-      chartTypes.forEach((chartType) => {
-        const config: ChartConfig = {
-          chartType,
-          settings: {},
-        };
-
-        const markup = renderToStaticMarkup(
-          <ChartSettings.Root
-            tableName="test_table"
-            config={config}
-            columns={mockColumns}
-            onChange={mockOnChange}
-          >
-            <div>Test content</div>
-          </ChartSettings.Root>,
-        );
-
-        expect(markup).toContain('Test content');
-      });
-    });
+    it.each([
+      'histogram',
+      'count-plot',
+      'line-chart',
+      'heatmap',
+      'box-plot',
+      'bubble-chart',
+    ] as const)('renders with chart type: %s', (chartType) => {
+      const config: ChartConfig = {
+        chartType,
+        settings: {},
+      };
+
+      const markup = renderToStaticMarkup(
+        <ChartSettings.Root
+          tableName="test_table"
+          config={config}
+          columns={mockColumns}
+          onChange={mockOnChange}
+        >
+          <div>Test content</div>
+        </ChartSettings.Root>,
+      );
+
+      expect(markup).toContain('Test content');
+    });
🤖 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 `@packages/mosaic/__tests__/ChartSettings.test.tsx` around lines 45 - 74, The
test currently iterates chartTypes with chartTypes.forEach inside a single it
block which hides which chartType fails; refactor to a parameterized test using
Jest's it.each (or test.each) so each chartType runs as its own test case and
failures show the failing value — replace the it('renders with different chart
types', ...) body with an it.each([...]) that supplies each ChartConfig
chartType and constructs the same ChartConfig and renderToStaticMarkup call
against ChartSettings.Root (keeping tableName, columns, mockOnChange and the
'Test content' assertion) so failures indicate the specific chartType.
packages/mosaic/src/chart/chart-settings/ChartTypeSelector.tsx (1)

21-59: 💤 Low value

Consider explicit handling when chart types are unavailable.

The component uses optional chaining (chartTypes?.find, chartTypes?.map) to handle potentially undefined chartTypes, which prevents crashes but results in an empty dropdown. If chart types should always be available, consider adding a loading state or error message for better UX.

🤖 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 `@packages/mosaic/src/chart/chart-settings/ChartTypeSelector.tsx` around lines
21 - 59, ChartTypeSelector currently uses optional chaining on chartTypes which
yields an empty/selectable UI when chartTypes is undefined; update the component
to explicitly handle missing chartTypes by showing a loading or error state and
disabling the Select until data is present. Inside ChartTypeSelector, check
chartTypes before rendering Select (or inside SelectTrigger/SelectContent): if
chartTypes is undefined render a small loading indicator or “Loading chart
types…”/“No chart types available” message and set the Select to disabled (or
return early), and only map chartTypes to SelectItem when it’s a defined
non-empty array; ensure selectedChartType logic with selectedChartType?.icon
remains intact.
packages/mosaic/src/chart/chart-settings/ChartSettingsContext.tsx (1)

74-85: ⚡ Quick win

Type cast on line 82 may hide errors; consider preserving generic type parameter.

The as ChartConfig cast widens from the specific config type T to the entire ChartConfig union. This loses type safety—if settings are modified incorrectly, TypeScript won't catch it.

The root issue is that the spread operation doesn't preserve the discriminated union type. A safer approach would be to keep the generic type parameter throughout:

♻️ Suggested refactor to preserve type safety
 const onChangeConfig = useCallback(
-  function <K extends keyof ChartSetting>(key: K, value: ChartSetting) {
+  function <K extends keyof ChartSetting<T>>(key: K, value: ChartSetting<T>[K]) {
     onChange({
       ...config,
       settings: {
         ...config.settings,
         [key]: value,
       },
-    } as ChartConfig);
+    } as T);
   },
   [config, onChange],
 );

This preserves the specific chart config type rather than widening to the union, improving type safety for callers.

🤖 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 `@packages/mosaic/src/chart/chart-settings/ChartSettingsContext.tsx` around
lines 74 - 85, The current onChangeConfig implementation widens the specific
config type to the ChartConfig union via "as ChartConfig", losing type safety;
change onChangeConfig to preserve the generic config type (T) instead of
casting: make the callback generic over the concrete config type and the
specific setting key/value (referencing onChangeConfig, onChange, ChartConfig,
ChartSetting), accept a value typed as the specific ChartSetting property rather
than ChartSetting, and construct the new config while keeping its original
generic type so you can pass the correctly typed config to onChange without
using "as ChartConfig".
🤖 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 `@examples/deckgl-mosaic/src/components/filters/FiltersPanel.tsx`:
- Line 8: There is a name collision: ChartConfig is imported from both
`@sqlrooms/mosaic` and ./filterPlots; update one import to use a distinct local
alias (for example import { ChartConfig as PlotChartConfig } from
'./filterPlots' or import { ChartConfig as MosaicChartConfig } from
'@sqlrooms/mosaic') and then update all usages in FiltersPanel (references to
ChartConfig within this file) to the new alias (e.g., PlotChartConfig or
MosaicChartConfig) so the two bindings no longer collide; ensure you update any
type annotations, props, or function parameters that reference ChartConfig.

In `@packages/mosaic/src/chart-builders/ChartBuilderRoot.tsx`:
- Around line 24-25: The JSDoc for the ChartBuilderRoot prop chartTypes is
inaccurate: it says the default is "all registered types" but the implementation
(see chartTypes?: ChartTypeDefinition[] and the defaulting at the component
where chartTypes falls back to an empty array) uses an empty list. Update the
prop comment for chartTypes in ChartBuilderRoot (and any duplicate doc at the
other location around the defaulting code) to state that the default is an empty
array (no chart types) rather than all registered types so the docs match the
actual fallback behavior.

In `@packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotPanelRenderer.tsx`:
- Around line 132-140: In BoxPlotPanelRenderer.tsx inside the state.yBrush.map
block, guard the division by (yDomain[1] - yDomain[0]) to avoid NaN/Infinity
when the Y domain collapses: compute a safe denominator (e.g., const span =
yDomain[1] - yDomain[0] || 1) before doing ((yDomain[1] - value) / span) *
plotHeight, and then clamp the final pixel value to the plot bounds (between
MARGINS.top and MARGINS.top + plotHeight) so the brush style always receives a
finite, valid number; update the mapping logic where yDomain and plotHeight are
used in BoxPlotPanelRenderer to use these safe values.

In `@packages/mosaic/src/chart/chart-settings/ChartSettings.tsx`:
- Line 55: The ChartSettingsViewSpecButton currently makes onClick optional
which permits rendering the button without an action; update the component prop
type in ChartSettingsViewSpecButton to require onClick (change FC<{onClick?: ()
=> void}> to FC<{onClick: () => void}>) so the click handler is enforced at
compile time, and adjust any call sites to pass a valid handler (or explicitly
pass a no-op if intentional) to preserve type-safety for action wiring.

In `@packages/mosaic/src/chart/chart-settings/ChartSettingsPanel.tsx`:
- Around line 55-56: The ViewSpecButton is currently rendered whenever spec is
truthy even if onViewSpec is undefined, making the clickable UI inert; change
the render condition to require both spec and onViewSpec (or alternatively
render a disabled/non-clickable variant) so ChartSettings.ViewSpecButton is only
interactive when the onViewSpec handler exists — update the conditional around
ChartSettings.ViewSpecButton to check both spec and onViewSpec (or render a
disabled state) to prevent a non-functional button.

In `@packages/mosaic/src/dashboard/MosaicDashboardSlice.ts`:
- Around line 711-715: isChartPanelConfig currently narrows by only comparing
panel.type to MOSAIC_DASHBOARD_CHART_PANEL_TYPE which misidentifies
LegacyPanelConfig entries; update isChartPanelConfig to also validate the
payload shape (e.g., that the panel has the ChartPanelConfig-specific fields
such as a non-null config/spec/chart object and expected keys like encoding or
mark) before returning true. In other words, inside isChartPanelConfig (and
still checking MOSAIC_DASHBOARD_CHART_PANEL_TYPE), add runtime checks that panel
has the ChartPanelConfig properties (for example existence and typeof checks for
panel.config or panel.spec and nested keys like encoding/mark) so the predicate
only narrows to ChartPanelConfig when the shape matches.

---

Outside diff comments:
In `@packages/mosaic/src/index.ts`:
- Around line 189-215: The codebase still mixes old VgPlot* names with new
Chart* names and lacks deprecation documentation for the alias
MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE; to fix, pick one approach and make changes
consistently: either fully migrate internals to Chart* (rename VgPlotChart ->
ChartChart or ChartComponent, RetainedVgPlotChart -> RetainedChart,
ChartBuilderVgPlotOutput -> ChartBuilderOutput, update imports in
MosaicDashboardVgPlotChart.tsx, MosaicDashboardVgPlotError.tsx, base-types.ts,
slice where panel type value 'vgplot' is used) or explicitly mark VgPlot* as
private/legacy by adding clear deprecation comments and export a compatibility
alias that logs the deprecation and points to the new Chart* names; update the
MOSAIC_DASHBOARD_VGPLOT_PANEL_TYPE handling to document the legacy name and
ensure all internal references are aligned with the chosen approach.

---

Nitpick comments:
In `@packages/mosaic/__tests__/ChartSettings.test.tsx`:
- Around line 45-74: The test currently iterates chartTypes with
chartTypes.forEach inside a single it block which hides which chartType fails;
refactor to a parameterized test using Jest's it.each (or test.each) so each
chartType runs as its own test case and failures show the failing value —
replace the it('renders with different chart types', ...) body with an
it.each([...]) that supplies each ChartConfig chartType and constructs the same
ChartConfig and renderToStaticMarkup call against ChartSettings.Root (keeping
tableName, columns, mockOnChange and the 'Test content' assertion) so failures
indicate the specific chartType.

In `@packages/mosaic/src/boxplot/BoxPlotClient.ts`:
- Around line 68-79: The rowsFromQueryResult function redundantly wraps the
toArray() result in Array.from; change the return to directly return the array
from toArray() (e.g., return (data as {toArray(): T[]}).toArray();), keeping the
existing guards intact so rowsFromQueryResult<T> still validates data and then
returns the toArray() result without the extra Array.from call.

In `@packages/mosaic/src/chart/chart-settings/ChartSettingsContext.tsx`:
- Around line 74-85: The current onChangeConfig implementation widens the
specific config type to the ChartConfig union via "as ChartConfig", losing type
safety; change onChangeConfig to preserve the generic config type (T) instead of
casting: make the callback generic over the concrete config type and the
specific setting key/value (referencing onChangeConfig, onChange, ChartConfig,
ChartSetting), accept a value typed as the specific ChartSetting property rather
than ChartSetting, and construct the new config while keeping its original
generic type so you can pass the correctly typed config to onChange without
using "as ChartConfig".

In `@packages/mosaic/src/chart/chart-settings/ChartTypeSelector.tsx`:
- Around line 21-59: ChartTypeSelector currently uses optional chaining on
chartTypes which yields an empty/selectable UI when chartTypes is undefined;
update the component to explicitly handle missing chartTypes by showing a
loading or error state and disabling the Select until data is present. Inside
ChartTypeSelector, check chartTypes before rendering Select (or inside
SelectTrigger/SelectContent): if chartTypes is undefined render a small loading
indicator or “Loading chart types…”/“No chart types available” message and set
the Select to disabled (or return early), and only map chartTypes to SelectItem
when it’s a defined non-empty array; ensure selectedChartType logic with
selectedChartType?.icon remains intact.
🪄 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: a3d2004b-4934-4df3-92dd-81cc67efcb34

📥 Commits

Reviewing files that changed from the base of the PR and between 9dfa02e and b554b67.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (79)
  • apps/sqlrooms-cli-ui/src/createChartToolDeps.ts
  • examples/deckgl-mosaic/src/components/filters/FiltersPanel.tsx
  • packages/mosaic/README.md
  • packages/mosaic/__tests__/BoxPlotClient.test.ts
  • packages/mosaic/__tests__/ChartSettings.test.tsx
  • packages/mosaic/__tests__/MosaicDashboardSlice.test.ts
  • packages/mosaic/__tests__/chartTypes.test.ts
  • packages/mosaic/__tests__/generateMosaicChartSpec.test.ts
  • packages/mosaic/package.json
  • packages/mosaic/src/MosaicSlice.ts
  • packages/mosaic/src/boxplot/BoxPlotClient.ts
  • packages/mosaic/src/chart-builders/ChartBuilderActions.tsx
  • packages/mosaic/src/chart-builders/ChartBuilderContent.tsx
  • packages/mosaic/src/chart-builders/ChartBuilderContext.tsx
  • packages/mosaic/src/chart-builders/ChartBuilderDialog.tsx
  • packages/mosaic/src/chart-builders/ChartBuilderFields.tsx
  • packages/mosaic/src/chart-builders/ChartBuilderRoot.tsx
  • packages/mosaic/src/chart-builders/ColumnSelector.tsx
  • packages/mosaic/src/chart-builders/MultiFieldSelector.tsx
  • packages/mosaic/src/chart-builders/createChartBuilderStore.ts
  • packages/mosaic/src/chart-types/base-types.ts
  • packages/mosaic/src/chart-types/box-plot/BoxPlotSettings.tsx
  • packages/mosaic/src/chart-types/box-plot/definition.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotPanelRenderer.tsx
  • packages/mosaic/src/chart-types/box-plot/renderer/constants.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/plot.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/useBoxPlotClient.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/utils.ts
  • packages/mosaic/src/chart-types/box-plot/schema.ts
  • packages/mosaic/src/chart-types/box-plot/spec.ts
  • packages/mosaic/src/chart-types/bubble-chart/BubbleChartSettings.tsx
  • packages/mosaic/src/chart-types/bubble-chart/definition.ts
  • packages/mosaic/src/chart-types/chart-config.ts
  • packages/mosaic/src/chart-types/count-plot/CountPlotSettings.tsx
  • packages/mosaic/src/chart-types/count-plot/definition.ts
  • packages/mosaic/src/chart-types/custom-spec/CustomSpecSettings.tsx
  • packages/mosaic/src/chart-types/custom-spec/definition.ts
  • packages/mosaic/src/chart-types/custom-spec/spec.ts
  • packages/mosaic/src/chart-types/errors.ts
  • packages/mosaic/src/chart-types/heatmap/HeatmapSettings.tsx
  • packages/mosaic/src/chart-types/heatmap/definition.ts
  • packages/mosaic/src/chart-types/histogram/HistogramSettings.tsx
  • packages/mosaic/src/chart-types/histogram/definition.ts
  • packages/mosaic/src/chart-types/index.ts
  • packages/mosaic/src/chart-types/line-chart/LineChartSettings.tsx
  • packages/mosaic/src/chart-types/line-chart/definition.ts
  • packages/mosaic/src/chart-types/registry.ts
  • packages/mosaic/src/chart-types/tool-types.ts
  • packages/mosaic/src/chart-types/useChartTypeDefinition.ts
  • packages/mosaic/src/chart/MosaicDashboardChart.tsx
  • packages/mosaic/src/chart/MosaicDashboardChartContent.tsx
  • packages/mosaic/src/chart/MosaicDashboardChartHeaderActions.tsx
  • packages/mosaic/src/chart/MosaicDashboardChartRenderer.tsx
  • packages/mosaic/src/chart/MosaicDashboardComponentChart.tsx
  • packages/mosaic/src/chart/MosaicDashboardVgPlotChart.tsx
  • packages/mosaic/src/chart/MosaicDashboardVgPlotError.tsx
  • packages/mosaic/src/chart/chart-settings/ChartSettings.tsx
  • packages/mosaic/src/chart/chart-settings/ChartSettingsContent.tsx
  • packages/mosaic/src/chart/chart-settings/ChartSettingsContext.tsx
  • packages/mosaic/src/chart/chart-settings/ChartSettingsPanel.tsx
  • packages/mosaic/src/chart/chart-settings/ChartSpecViewerPanel.tsx
  • packages/mosaic/src/chart/chart-settings/ChartTypeSelector.tsx
  • packages/mosaic/src/chart/chart-settings/useTableColumns.ts
  • packages/mosaic/src/chart/useBrushSelectionParams.tsx
  • packages/mosaic/src/chart/useChartRetainer.tsx
  • packages/mosaic/src/chart/useGenerateSpec.ts
  • packages/mosaic/src/dashboard/ChartSpecErrorDisplay.tsx
  • packages/mosaic/src/dashboard/MosaicDashboard.tsx
  • packages/mosaic/src/dashboard/MosaicDashboardSlice.ts
  • packages/mosaic/src/dashboard/MosaicDashboardVgPlotPanelRenderer.tsx
  • packages/mosaic/src/dashboard/chart-settings/ChartSettingsPanel.tsx
  • packages/mosaic/src/dashboard/chart-settings/index.ts
  • packages/mosaic/src/dashboard/defaultPanelRenderers.ts
  • packages/mosaic/src/dashboard/generateMosaicChartSpec.ts
  • packages/mosaic/src/dashboard/useGenerateSpec.ts
  • packages/mosaic/src/dashboard/utils.ts
  • packages/mosaic/src/index.ts
  • packages/mosaic/src/profiler/MosaicDashboardProfilerPanelRenderer.tsx
  • python/sqlrooms-cli/sqlrooms/web/launcher.py
💤 Files with no reviewable changes (10)
  • packages/mosaic/tests/generateMosaicChartSpec.test.ts
  • packages/mosaic/src/dashboard/ChartSpecErrorDisplay.tsx
  • packages/mosaic/src/dashboard/useGenerateSpec.ts
  • packages/mosaic/src/dashboard/generateMosaicChartSpec.ts
  • packages/mosaic/src/dashboard/chart-settings/index.ts
  • packages/mosaic/src/dashboard/chart-settings/ChartSettingsPanel.tsx
  • packages/mosaic/src/chart-types/box-plot/spec.ts
  • packages/mosaic/src/chart-types/registry.ts
  • packages/mosaic/src/dashboard/MosaicDashboardVgPlotPanelRenderer.tsx
  • packages/mosaic/src/chart-types/errors.ts

Comment thread examples/deckgl-mosaic/src/components/filters/FiltersPanel.tsx Outdated
Comment thread packages/mosaic/src/chart-builders/ChartBuilderRoot.tsx Outdated
Comment thread packages/mosaic/src/chart-types/chart-config.ts
Comment thread packages/mosaic/src/chart/chart-settings/ChartSettings.tsx
Comment thread packages/mosaic/src/chart/chart-settings/ChartSettingsPanel.tsx
Comment thread packages/mosaic/src/dashboard/MosaicDashboardSlice.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 `@packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotErrorBoundary.tsx`:
- Around line 37-39: The component BoxPlotErrorBoundary currently renders raw
error text via this.state.error.message in its render output; replace that UI
display with a generic user-facing message (e.g., "An unexpected error occurred
while rendering the chart") and remove any direct exposure of error details from
the DOM, while keeping the original error object sent to logging/telemetry (or
console.error) inside the componentDidCatch or error handling path for
diagnostics; update references in the render method and componentDidCatch to
ensure only generic text is shown to users and detailed error info is recorded
in telemetry/logging.
🪄 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: e99b2f0b-8ed6-4a13-80cb-d530409fbcd3

📥 Commits

Reviewing files that changed from the base of the PR and between b554b67 and 17c6a9c.

📒 Files selected for processing (12)
  • examples/deckgl-mosaic/src/components/filters/FiltersPanel.tsx
  • examples/deckgl-mosaic/src/components/filters/filterPlots.ts
  • packages/mosaic/README.md
  • packages/mosaic/src/boxplot/BoxPlotClient.ts
  • packages/mosaic/src/chart-builders/ChartBuilderRoot.tsx
  • packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotErrorBoundary.tsx
  • packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotPanelRenderer.tsx
  • packages/mosaic/src/chart-types/box-plot/renderer/constants.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/useBoxPlotClient.ts
  • packages/mosaic/src/chart-types/chart-config.ts
  • packages/mosaic/src/chart-types/line-chart/LineChartSettings.tsx
  • packages/mosaic/src/index.ts
✅ Files skipped from review due to trivial changes (2)
  • examples/deckgl-mosaic/src/components/filters/filterPlots.ts
  • packages/mosaic/README.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/mosaic/src/chart-types/box-plot/renderer/constants.ts
  • packages/mosaic/src/chart-types/chart-config.ts
  • packages/mosaic/src/index.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotPanelRenderer.tsx
  • packages/mosaic/src/boxplot/BoxPlotClient.ts
  • packages/mosaic/src/chart-types/box-plot/renderer/useBoxPlotClient.ts

Comment on lines +37 to +39
<div className="mt-2 text-xs opacity-75">
{this.state.error.message}
</div>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid exposing raw error messages in end-user UI.

Rendering this.state.error.message can leak internal details (query text/system info). Show a generic message here and keep detailed diagnostics in logging/telemetry only.

Suggested change
-          <div className="mt-2 text-xs opacity-75">
-            {this.state.error.message}
-          </div>
+          <div className="mt-2 text-xs opacity-75">
+            Please try refreshing the panel or adjusting chart settings.
+          </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="mt-2 text-xs opacity-75">
{this.state.error.message}
</div>
<div className="mt-2 text-xs opacity-75">
Please try refreshing the panel or adjusting chart settings.
</div>
🤖 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 `@packages/mosaic/src/chart-types/box-plot/renderer/BoxPlotErrorBoundary.tsx`
around lines 37 - 39, The component BoxPlotErrorBoundary currently renders raw
error text via this.state.error.message in its render output; replace that UI
display with a generic user-facing message (e.g., "An unexpected error occurred
while rendering the chart") and remove any direct exposure of error details from
the DOM, while keeping the original error object sent to logging/telemetry (or
console.error) inside the componentDidCatch or error handling path for
diagnostics; update references in the render method and componentDidCatch to
ensure only generic text is shown to users and detailed error info is recorded
in telemetry/logging.

@dmitriy-kostianetskiy dmitriy-kostianetskiy self-assigned this May 14, 2026
@dmitriy-kostianetskiy
dmitriy-kostianetskiy self-requested a review May 14, 2026 12:32
@dmitriy-kostianetskiy
dmitriy-kostianetskiy merged commit 2fc7d18 into main May 14, 2026
6 checks passed
@dmitriy-kostianetskiy
dmitriy-kostianetskiy deleted the feat--Box-plot-for-mosaic-dashboards branch May 14, 2026 12:32
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