Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ auto-generated per-PR notes; this file is the curated, human-readable history.
its) — filed as **#298** rather than deleted or silently fixed here, since
restoring it is a distinct rendering fix that needs its own >1560px-viewport
regression test.
- **Line/area chart X-axis tick labels no longer rotate into an unreadable
wall of timestamps at a few hundred rows.** Line/area charts still draw a
Chart.js `category` scale (one tick per distinct row — no time scale yet),
so `chartJsConfig` (`src/core/chart-data.ts`) now forces the category axis's
ticks to `autoSkip: true, maxRotation: 0, minRotation: 0` for those two chart
types, letting Chart.js drop enough labels to stay horizontal instead of
rotating every one of them. Bar/hbar/pie category axes are unchanged. A real
Chart.js time scale (natural tick boundaries, gap-aware point placement) is
filed as a follow-up: **#309**.

### Added
- **Dashboard v1 contracts, codecs, canonical encoding, and resource limits**
Expand Down
12 changes: 10 additions & 2 deletions src/core/chart-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,10 @@ interface TooltipContext {
interface ChartJsAxis {
display: boolean;
grid: { color: string; drawBorder: boolean; display: boolean };
ticks: { color: string; font: Record<string, unknown>; callback?: (v: number | string) => string };
ticks: {
color: string; font: Record<string, unknown>; callback?: (v: number | string) => string;
autoSkip?: boolean; maxRotation?: number; minRotation?: number;
};
beginAtZero?: boolean;
stacked?: boolean;
}
Expand Down Expand Up @@ -909,7 +912,12 @@ export function chartJsConfig(
beginAtZero: style.scale === 'zero'
|| (style.scale === 'auto' && (horizontal || cfg.type === 'bar')),
};
const catAxis: ChartJsAxis = { display: axesVisible, grid: { ...grid, display: false }, ticks };
// Line/area charts plot every distinct row as its own category tick (no
// Chart.js time scale — #309), which at a few hundred rows is unreadable
// rotated at Chart.js's default up-to-50°. Force horizontal labels and let
// autoSkip drop enough of them to fit instead.
const catTicks = isLine ? { ...ticks, autoSkip: true, maxRotation: 0, minRotation: 0 } : ticks;
const catAxis: ChartJsAxis = { display: axesVisible, grid: { ...grid, display: false }, ticks: catTicks };
options.scales = horizontal ? { x: valueAxis, y: catAxis } : { x: catAxis, y: valueAxis };
const barsStacked = (horizontal || cfg.type === 'bar') && style.mode === 'stacked';
const areaStacked = isArea && style.stack === 'stacked';
Expand Down
12 changes: 12 additions & 0 deletions tests/unit/chart-data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,18 @@ describe('chartJsConfig', () => {
expect(cfg.options.indexAxis).toBe('x');
expect(cfg.options.scales!.y.beginAtZero).toBe(true);
});
it('line/area category-axis ticks force horizontal autoSkip labels (#309); bar keeps Chart.js defaults', () => {
const line = chartJsConfig(cols, rows, { type: 'line', x: 0, y: [1], series: null }, colors);
expect(line.options.scales!.x.ticks).toMatchObject({ autoSkip: true, maxRotation: 0, minRotation: 0 });
const area = chartJsConfig(cols, rows, { type: 'area', x: 0, y: [1], series: null }, colors);
expect(area.options.scales!.x.ticks).toMatchObject({ autoSkip: true, maxRotation: 0, minRotation: 0 });
const bar = chartJsConfig(cols, rows, { type: 'bar', x: 0, y: [1], series: null }, colors);
expect(bar.options.scales!.x.ticks.autoSkip).toBeUndefined();
expect(bar.options.scales!.x.ticks.maxRotation).toBeUndefined();
// hbar's category axis is y, not x
const hbar = chartJsConfig(cols, rows, { type: 'hbar', x: 0, y: [1], series: null }, colors);
expect(hbar.options.scales!.y.ticks.autoSkip).toBeUndefined();
});
it('value-axis ticks humanize via callback (number and coercible string)', () => {
const cfg = chartJsConfig(cols, rows, { type: 'bar', x: 0, y: [1], series: null }, colors);
const cb = cfg.options.scales!.y.ticks.callback!;
Expand Down
Loading