Remove weird chart example and update tests

This commit is contained in:
Nate Kelley 2025-09-19 15:34:57 -06:00
parent 9e3b69af1f
commit 241b2c4f88
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
8 changed files with 157 additions and 105 deletions

View File

@ -29,7 +29,7 @@ describe('LegendItemDot', () => {
it('renders with different sizes', () => {
const { rerender } = render(<LegendItemDot {...defaultProps} size="default" />);
expect(screen.getByTestId('legend-dot-container')).toHaveClass('w-4.5');
expect(screen.getByTestId('legend-dot-container')).toHaveClass('w-4');
rerender(<LegendItemDot {...defaultProps} size="sm" />);
expect(screen.getByTestId('legend-dot-container')).toHaveClass('w-2');

View File

@ -71,14 +71,7 @@ const OverflowPopoverContent = React.memo(
});
return (
<div
ref={parentRef}
style={{
maxHeight: '100%',
width: '100%',
overflow: 'auto',
}}
>
<div ref={parentRef} className="max-h-[100%] w-full overflow-auto min-h-7">
<div
style={{
height: `${rowVirtualizer.getTotalSize()}px`,

View File

@ -455,7 +455,7 @@ function createSeparateDatasetsByColor<
for (const originalDataset of datasets) {
for (let i = 0; i < uniqueColorValues.length; i++) {
const colorValue = uniqueColorValues[i];
const color = colorMapping.get(colorValue)!; // Safe to use ! since we filtered above
const color = colorMapping.get(colorValue); // Safe to use ! since we filtered above
// Create new data array with nulls where the color value doesn't match
const newData: (number | null)[] = [];

View File

@ -288,7 +288,7 @@ export function modifyDatasets({
if (!datasets.datasets.length) return datasets;
// Only clone when we actually need to modify something
let needsModification = false;
let needsModification: boolean = false;
// Check if we need to modify for pie charts
const isPie = selectedChartType === 'pie';
@ -301,9 +301,10 @@ export function modifyDatasets({
(selectedChartType === 'line' && lineGroupType === 'percentage-stack');
// Check if we need to modify for bar sorting
const needsBarSort = selectedChartType === 'bar' && barSortBy && barSortBy.some((o) => o !== 'none');
const needsBarSort =
selectedChartType === 'bar' && barSortBy && barSortBy.some((o) => o !== 'none');
needsModification = needsPieThreshold || needsPieSort || needsPercentageStack || needsBarSort;
needsModification = needsPieThreshold || !!needsPieSort || needsPercentageStack || !!needsBarSort;
// If no modifications needed, return original
if (!needsModification) {
@ -323,14 +324,15 @@ export function modifyDatasets({
// Apply minimum threshold if needed
if (needsPieThreshold) {
modifiedDatasets = handlePieThreshold(modifiedDatasets, pieMinimumSlicePercentage!);
modifiedDatasets = handlePieThreshold(modifiedDatasets, pieMinimumSlicePercentage);
}
// Apply sorting if needed
if (needsPieSort) {
// Only clone ticks if we need to sort
const ticksToSort = modifiedDatasets !== datasets.datasets ? result.ticks : cloneDeep(result.ticks);
const sortResult = sortPie(modifiedDatasets, pieSortBy!, ticksToSort);
const ticksToSort =
modifiedDatasets !== datasets.datasets ? result.ticks : cloneDeep(result.ticks);
const sortResult = sortPie(modifiedDatasets, pieSortBy, ticksToSort);
modifiedDatasets = sortResult.datasets;
result.ticks = sortResult.ticks;
}
@ -347,7 +349,8 @@ export function modifyDatasets({
// Bar sorting
if (needsBarSort) {
const sortKey = barSortBy!.find((o) => o !== 'none')!;
const sortKey = barSortBy.find((o) => o !== 'none');
if (!sortKey) return result;
const sortResult = sortBar(datasets.datasets, sortKey, cloneDeep(result.ticks));
result.datasets = sortResult.datasets;
result.ticks = sortResult.ticks;

View File

@ -1166,80 +1166,6 @@ export const WithTrendlines: Story = {
},
};
//IT got the x and y axis mixed up... which is fair...
export const ProblematicBarChart: Story = {
args: {
selectedChartType: 'bar',
barLayout: 'horizontal',
barAndLineAxis: {
x: ['metric_clv_all_time'],
y: ['customer_name'],
category: [],
tooltip: null,
colorBy: null,
},
columnLabelFormats: {
customer_name: {
...DEFAULT_COLUMN_LABEL_FORMAT,
columnType: 'text',
style: 'string',
numberSeparatorStyle: null,
replaceMissingDataWith: null,
},
metric_clv_all_time: {
...DEFAULT_COLUMN_LABEL_FORMAT,
columnType: 'number',
style: 'currency',
numberSeparatorStyle: ',',
replaceMissingDataWith: 0,
currency: 'USD',
},
},
data: [
{
customer_name: 'Customer A',
metric_clv_all_time: 800000.0,
},
{
customer_name: 'Customer B',
metric_clv_all_time: 780000.0,
},
{
customer_name: 'Customer C',
metric_clv_all_time: 760000.0,
},
{
customer_name: 'Customer D',
metric_clv_all_time: 740000.0,
},
{
customer_name: 'Customer E',
metric_clv_all_time: 720000.0,
},
{
customer_name: 'Customer F',
metric_clv_all_time: 700000.0,
},
{
customer_name: 'Customer G',
metric_clv_all_time: 680000.0,
},
{
customer_name: 'Customer H',
metric_clv_all_time: 660000.0,
},
{
customer_name: 'Customer I',
metric_clv_all_time: 640000.0,
},
{
customer_name: 'Customer J',
metric_clv_all_time: 620000.0,
},
],
},
};
export const WithYearInXAxis: Story = {
args: {
...Default.args,

View File

@ -123,7 +123,14 @@ describe('createDefaultChartConfig', () => {
const message = {
chart_config: {
...DEFAULT_CHART_CONFIG,
comboChartAxis: { x: [], y: [], y2: undefined as any, tooltip: null, category: [], colorBy: null },
comboChartAxis: {
x: [],
y: [],
y2: undefined as any,
tooltip: null,
category: [],
colorBy: null,
},
},
data_metadata: TEST_DATA_METADATA,
} as Parameters<typeof createDefaultChartConfig>[0];
@ -165,7 +172,14 @@ describe('createDefaultChartConfig', () => {
const message = {
chart_config: {
...DEFAULT_CHART_CONFIG,
comboChartAxis: { x: [], y: [], y2: ['test-y2'], tooltip: null, category: [], colorBy: null },
comboChartAxis: {
x: [],
y: [],
y2: ['test-y2'],
tooltip: null,
category: [],
colorBy: null,
},
},
data_metadata: TEST_DATA_METADATA,
} as Parameters<typeof createDefaultChartConfig>[0];

View File

@ -484,12 +484,31 @@ definitions:
type: array
items:
type: string
description: LOWERCASE column name from SQL for category grouping.
description: |
LOWERCASE column name from SQL for category grouping.
Category vs ColorBy:
- Use CATEGORY: When you want to create multiple series/lines (one per category value). Creates separate data points and enables legend.
- Use COLORBY: When you want to apply colors to bars/points based on a column value, but keep them as a single series.
Example: Sales by month
- With category=['region']: Creates separate lines/bars for each region (North, South, East, West)
- With colorBy.columnId='region': Colors bars by region but keeps them as one series
tooltip:
type: [array, 'null']
items:
type: string
description: Column names for tooltip. If null, y axis is used. Default: null
colorBy:
type: [object, 'null']
description: |
Optional color configuration to apply colors based on a column's values.
Use this when you want visual differentiation without creating separate series.
Perfect for: Status indicators (red/yellow/green), priority levels, or any categorical color coding.
properties:
columnId:
type: [string, 'null']
description: LOWERCASE column name whose values will determine colors
required:
- x
- y
@ -545,6 +564,9 @@ definitions:
type: array
items:
type: string
description: |
LOWERCASE column name from SQL for category grouping.
Creates separate colored series of points for each category value.
size:
type: array
items:
@ -555,6 +577,15 @@ definitions:
items:
type: string
description: Column names for tooltip. If null, y axis is used. Default: null
colorBy:
type: [object, 'null']
description: |
Optional color configuration to apply colors to scatter points based on a column's values.
Use when you want all points in one series with color-coded differentiation.
properties:
columnId:
type: [string, 'null']
description: LOWERCASE column name whose values will determine point colors
required:
- x
- y
@ -586,6 +617,15 @@ definitions:
items:
type: string
description: Column names for tooltip. If null, y axis is used. Default: null
colorBy:
type: [object, 'null']
description: |
Optional color configuration for pie slices based on x-axis values.
Allows custom color mapping for specific slice categories.
properties:
columnId:
type: [string, 'null']
description: LOWERCASE column name whose values will determine slice colors
required:
- x
- y
@ -620,12 +660,23 @@ definitions:
type: array
items:
type: string
description: LOWERCASE column name from SQL for category grouping.
description: |
LOWERCASE column name from SQL for category grouping.
Creates separate series for each category value in combo chart.
tooltip:
type: [array, 'null']
items:
type: string
description: Column names for tooltip. If null, y axis is used. Default: null
colorBy:
type: [object, 'null']
description: |
Optional color configuration to apply colors based on a column's values in combo chart.
Useful for color-coding bars while lines remain as separate series.
properties:
columnId:
type: [string, 'null']
description: LOWERCASE column name whose values will determine colors
required:
- x
- y

View File

@ -2,11 +2,24 @@ import { z } from 'zod';
export const ColorBySchema = z
.object({
//will use the values from the column to assign colors to the bars or lines
/**
* Column ID whose values will determine colors for chart elements.
* Use this when you want to apply colors based on a column's values
* without creating separate series (unlike category which creates multiple series).
*
* Example use cases:
* - Color bars by status (red for "failed", green for "success")
* - Color points by priority level
* - Apply conditional formatting based on categorical values
*/
columnId: z.string().nullable().optional(),
/**
* Optional override for specific value-to-color mappings.
* This allows custom color assignment for specific values.
*/
overrideColorByValue: z
.object({
//the value and the color to assign to the value
// The specific value to override color for
value: z.string(),
})
.nullable()
@ -22,11 +35,27 @@ export const BarAndLineAxisSchema = z
x: z.array(z.string()).default([]),
// the column ids to use for the y axis.
y: z.array(z.string()).default([]),
// the column ids to use for the category axis. If multiple column ids are provided, they will be grouped together. THE LLM SHOULD NEVER SET MULTIPLE CATEGORY COLUMNS. ONLY THE USER CAN SET THIS.
/**
* Column IDs for category grouping - creates SEPARATE SERIES for each category value.
*
* CATEGORY vs COLORBY - Key Differences:
* - CATEGORY: Creates multiple series/lines (one per unique value). Each appears in legend.
* - COLORBY: Applies colors to elements within a SINGLE series based on values.
*
* Example: Monthly sales chart
* - category=['region'] 4 separate lines/bar groups (North, South, East, West)
* - colorBy.columnId='region' 1 series with bars colored by region
*
* THE LLM SHOULD NEVER SET MULTIPLE CATEGORY COLUMNS. ONLY THE USER CAN SET THIS.
*/
category: z.array(z.string()).default([]),
// if null the y axis will automatically be used, the y axis will be used for the tooltip.
tooltip: z.nullable(z.array(z.string())).default(null),
//if the user wants to override the color by value
/**
* Apply colors to chart elements based on a column's values.
* Unlike 'category', this keeps all data in a single series with color differentiation.
* Perfect for status indicators, priority levels, or categorical color coding.
*/
colorBy: ColorBySchema,
})
.default({
@ -41,15 +70,31 @@ export const ScatterAxisSchema = z
.object({
// the column ids to use for the x axis. If multiple column ids are provided, they will be grouped together and summed. The LLM should NEVER set multiple x axis columns. Only the user can set this.
x: z.array(z.string()).default([]),
// the column ids to use for the y axis. If multiple column ids are provided, they will be grouped together and summed. The LLM should NEVER set multiple x axis columns. Only the user can set this.
// the column ids to use for the y axis. If multiple column ids are provided, they will be grouped together and summed. The LLM should NEVER set multiple y axis columns. Only the user can set this.
y: z.array(z.string()).default([]),
// the column ids to use for the category axis. If multiple column ids are provided, they will be grouped together. THE LLM SHOULD NEVER SET MULTIPLE CATEGORY COLUMNS. ONLY THE USER CAN SET THIS.
/**
* Column IDs for category grouping - creates SEPARATE SERIES of points for each category value.
*
* CATEGORY vs COLORBY - Key Differences:
* - CATEGORY: Creates multiple point series (one per unique value). Each appears in legend.
* - COLORBY: Colors all points in a SINGLE series based on column values.
*
* Example: Customer satisfaction vs response time
* - category=['department'] Separate point series for Sales, Support, Engineering
* - colorBy.columnId='priority' All points in one series, colored by priority level
*
* THE LLM SHOULD NEVER SET MULTIPLE CATEGORY COLUMNS. ONLY THE USER CAN SET THIS.
*/
category: z.array(z.string()).default([]),
// the column id to use for the size range of the dots. ONLY one column id should be provided.
size: z.tuple([z.string()]).or(z.array(z.string()).length(0)).default([]),
// if null the y axis will automatically be used, the y axis will be used for the tooltip.
tooltip: z.nullable(z.array(z.string())).default(null),
//if the user wants to override the color by value
/**
* Apply colors to chart elements based on a column's values.
* Unlike 'category', this keeps all data in a single series with color differentiation.
* Perfect for status indicators, priority levels, or categorical color coding.
*/
colorBy: ColorBySchema,
})
.default({
@ -69,11 +114,27 @@ export const ComboChartAxisSchema = z
y: z.array(z.string()).default([]),
// the column ids to use for the right y axis. If multiple column ids are provided, they will be grouped together and summed. The LLM should NEVER set multiple y axis columns. Only the user can set this.
y2: z.array(z.string()).default([]),
// the column ids to use for the category axis. If multiple column ids are provided, they will be grouped together. THE LLM SHOULD NEVER SET MULTIPLE CATEGORY COLUMNS. ONLY THE USER CAN SET THIS.
/**
* Column IDs for category grouping - creates SEPARATE SERIES for each category value.
*
* CATEGORY vs COLORBY - Key Differences:
* - CATEGORY: Creates multiple series/lines (one per unique value). Each appears in legend.
* - COLORBY: Applies colors to elements within a SINGLE series based on values.
*
* Example: Monthly sales chart
* - category=['region'] 4 separate lines/bar groups (North, South, East, West)
* - colorBy.columnId='region' 1 series with bars colored by region
*
* THE LLM SHOULD NEVER SET MULTIPLE CATEGORY COLUMNS. ONLY THE USER CAN SET THIS.
*/
category: z.array(z.string()).default([]),
// if null the y axis will automatically be used, the y axis will be used for the tooltip.
tooltip: z.nullable(z.array(z.string())).default(null),
//if the user wants to override the color by value
/**
* Apply colors to chart elements based on a column's values.
* Unlike 'category', this keeps all data in a single series with color differentiation.
* Perfect for status indicators, priority levels, or categorical color coding.
*/
colorBy: ColorBySchema,
})
.default({
@ -93,7 +154,11 @@ export const PieChartAxisSchema = z
y: z.array(z.string()).default([]),
// if null the y axis will automatically be used, the y axis will be used for the tooltip.
tooltip: z.nullable(z.array(z.string())).default(null),
//if the user wants to override the color by value
/**
* Apply colors to chart elements based on a column's values.
* Unlike 'category', this keeps all data in a single series with color differentiation.
* Perfect for status indicators, priority levels, or categorical color coding.
*/
colorBy: ColorBySchema,
})
.default({