Repository navigation
fix(plugin-charts): place each y axis by the spec yAxis[].position, and lay out and bind horizontal-bar's axes (objectui#10654) - #10686
Conversation
…nd lay out and bind horizontal-bar's axes `placeYAxes` (normalizeChartSchema) is the one place a y side is resolved: the normalizer binds each series it derives from the entries with it, and the renderer places the value axes and writes the `y-axis-position` note from the same answer. A lone right-hand entry now draws on the right, a side a value axis cannot take is refused with a note naming `yAxis[N].position`, and when both entries name one side the first keeps it. horizontal-bar draws its value axes across the plot (bottom / top), binds its bars to the ids it renders, draws `xAxis.title` on the category axis and the `yAxis` title under the value axis. Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
…t value axis, and mirror a right-hand y title A branch that renders its value axes with ids (a combo always; bar, line, area and horizontal-bar with two yAxis entries) renders no axis 0, so the grid and the annotations bound to it by default collapsed or were dropped. They now bind to the left slot's axis. A right-hand y axis lays its title out on the far side of its tick labels, as a top x axis does. Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
…t-hand title in the objectui#10654 enumeration Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
…e plugin-charts patch The yAxis sentence of the axis `position` row now reads what the head does, the changeset states the placement rule, and the enumeration pins the free-side rule on bar and column. Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
…xis-position-honoured Claude-Session: https://claude.ai/code/session_01KUxVUa7e39aNjhkKi1gsoy Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Read: card objectui#10654 (body, comments 5834536782 · 5835132719 · 5835682793; the os-dev-report 5836589916 was not used as evidence), the folded card objectui#10655 and its fold comment 5835169621, PR #10686 body and file list, the diff at merge-base ① Derived judgmentsTriage
② Semver level
Changeset prose, sentence by sentence against the diff:
Docs prose (
Other ③ Boundary flags
Implemented-by: VERDICT: PASS |
Fixes #10654
Clause-②: no
The renderer begins honouring a key the spec already declares (
yAxis[].position, on@objectstack/spec'sChartAxisSchema, which eachyAxisentry takes); no export, schema or accept set moves. objectui#10655, closed as a duplicate and folded into this card, is rows 5 and 6 below.What changed
One resolver.
placeYAxes(inpackages/plugin-charts/src/normalizeChartSchema.ts) is the one place a y side is resolved.normalizeChartSchemabinds each series it derives from the entries (noseries) with it, andAdvancedChartImplplaces the value axes and writes the notes from the same answer. The x-side mechanism of PR objectui#10647 is reused: theChartFootnotenote channel (joined withjoinNotes), and the default side. No second note mechanism.yAxisentrycolumn), line, area, comboleft/rightleft/right, first entry only (scatter draws one y axis)bottom/top(the value axes run across the plot)A series binds to a slot by its spec
yAxis: 'left' | 'right'. On horizontal-bar the chart is the vertical one transposed, so'left'binds the bottom axis and'right'the top one (the same swap PR objectui#10647 reads forxAxisthere).A side a value axis cannot take is refused: the entry is placed as if it named none, and the chart shows
p role="note" data-chart-note="y-axis-position"under the plot, namingyAxis[N].position, the value, and the side it was drawn on. Not aChartRefusal, no console warning, and no schema narrowing, for the reasons the x note gives.horizontal-bar. Two entries now draw two value axes (bottom and top, each a recharts
XAxiswith its ownxAxisId), and the bars bind to those ids. They were bound toyAxisIdleft/right, which the branch never rendered.xAxis.titleis drawn on the category axis, laid out for an axis running down the plot, and theyAxistitle under (or over) the value axis, laid out for an axis running across it.JSDoc. The
yAxesprop JSDoc andNormalizedChartSchema.yAxesno longer say a loneposition: 'right'entry turns on a secondary axis, or that index 0 is the left axis.Docs. The
yAxissentence of thepositionrow incontent/docs/plugins/plugin-charts.mdxnow states what the head does (it pointed at this card). Changeset.changeset/10654-yaxis-position-honoured.md,'@object-ui/plugin-charts': patch.The rule when both entries name a side, on the four axes
Rule: each entry takes the open side it names; when both name the same side, the first keeps it and the second is drawn on the other side, with a note naming
yAxis[1].position; an entry naming no side takes the side the other left free.series[].yAxisbinds by side name, and the docs example bindsmarginto the right-hand axis. Only a per-entry side makes a declaredpositionmean the side the docs promise.yAxis[0]is already the primary axis the docs name (itsshowGridLinesgoverns the horizontal grid), so keeping it primary changes no reading an author relies on.Rejected: the second entry wins a conflict (it overrides the entry the docs call primary); both refused to defaults (more notes, and neither entry honoured); index-only placement (the base behaviour, rows 1 to 4).
Measured on the base (
4758b33;packages/plugin-chartsbyte-identical to02e6d36)A throwaway jsdom probe through
ChartRenderer(probe file deleted) confirmed every H1 row:position: 'right'entry: every value tickorientation="left"on bar, line, area and scatter, and no note;topon a y entry: drawn on the left, no note;[{ revenue, position: 'right', min: 0, max: 100 }, { cost, position: 'left' }]with noseries: the left axis carried the first entry's 0..100 domain and no series, and both series were measured on the right axis (0..20);series: 4 bar rectangles where 6 are owed (barcontrol: 6);xAxis.title: 'Month'and ayAxistitleRevenue: one label,Revenue, rotated-90at x=70;Monthnot drawn (barcontrol:Monthunder the category axis,Revenuerotated at x=10);rightentry titledRevenue: the title drawn on both sides.Pin:
packages/plugin-charts/src/ChartRenderer.yAxisPosition-10654.test.tsxOne enumeration over the rows, through
ChartRendererwith the axes in spec shape, each row with itsbarcontrol. Readings: tickorientation, tick text per side,text.recharts-labelposition and rotation,.recharts-bar-rectanglecount,data-chart-note="y-axis-position"notes, grid lines and reference lines.2fd09e7:Tests 52 passed (52), exit 0.AdvancedChartImpl.tsxblobd97fcee0andnormalizeChartSchema.tsblob6b418617, the base blobs; restored to the head blobs4356fc08/ab7945cbafter,git diff HEADempty):Tests 38 failed | 14 passed (52), exit 1. The 14 green are exactly the controls; every non-control pin is red.Per-hunk ablation (
ablation-replace.mjs, anchor hit as declared, blob changed, restored to the head blob each time)Run at
f531ed9, whose two implementation blobs are byte-identical at2fd09e7.right")xAxisId(back toyAxisId)valueAxisIdForforced to no idyPositionNoteforcednullorientation: 'right'(both sites)rightThe lone-axis ablation's first attempt was refused by the tool (its replacement already occurred once in the file, so the count check failed and nothing ran); it was re-run with a distinct replacement, above.
In-place fixes under the bounded exemption (same defect class, same file, same gates)
0by default, and a branch whose value axes carry ids renders none. Measured at base: a two-entry bar chart drew 2 horizontal grid lines instead of one per tick and dropped itsaxis: 'x'annotation; a combo with fewer than two entries drew no annotation (0 of 2); a two-entry horizontal-bar dropped itsaxis: 'y'annotation. They now bind to the'left'slot's axis (valueAxisIdFor); row 11 pins it. Without it this change would also have regressed a two-entry horizontal-bar's vertical grid.angle: 90,insideRight), as PR objectui#10647 mirrors a top x title. Measured with the base layout: the right-hand title at x=462, its tick labels starting at x=465. Row 10 pins it. This also moves the title of every existing second-entry (right-hand) axis.Gates (local, head
2fd09e7)pnpm exec vitest run packages/plugin-charts/ --maxWorkers=2(via os-verify-lock,VERDICT command-exit 0):Test Files 79 passed (79)·Tests 937 passed (937).pnpm --filter @object-ui/plugin-charts type-check(tsc --noEmit && tsc -p tsconfig.test.json): exit 0, 0error TS. The test program lists the new pin file (--listFiles). Dependency closure built first:pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-charts^...' buildexit 0.check:control-bytes,check:test-path-roots,check:vi-mock-specifiers,check:vi-mock-inherit,check:vi-mock-override-shape: all exit 0 andOK.check:new-line-citations:VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0.check-changeset-presence:✅ 3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/10654-yaxis-position-honoured.md.check-changeset-no-majorexit 0.check-changeset-overwrite:✅ No pre-existing changeset was modified or deleted.check:pending-changeset-literalsexit 0.check:changeset-claims(report-only, exit 0) asks for a read of.changeset/7546-chart-series-keys-declared.md("yAxisbinds the secondary axis") and.changeset/7694-chart-series-chart-type-alias-refusal.md: both read, both still true.check-doc-links(Links are valid across 17 scan roots.),check:doc-types,check:prompt-keys,check:doc-example-ids,check:doc-fences,check:shell-escape-residue,check:doc-example-readers,check-doc-expression-carriage: all exit 0.eslint --format jsonover the three changed TS files: 3 files, 0 errors, 49 warnings. The two source files carry the same rule tally as their base blobs (AdvancedChartImpl.tsx39no-explicit-any, 4exhaustive-deps, 1preserve-manual-memoization;normalizeChartSchema.ts5no-explicit-any); the pin file has none. The resolved config has emptyparserOptions(no type-aware linting) and no rule ineslint-rules/reads another file, so this diff cannot move any untouched file's verdict.origin/main(7baede3) before opening; it touchedObjectChart.tsxin this package, and the suite above ran after the merge.Acceptance notes
check:doc-snippetsandcheck:doc-examplesexit 2 (prerequisite: the scoped build of the packages the covered docs import). The docs edit changes one table cell and no fenced block.plugin-charts.mdx("a second entry declares the right-hand axis"),content/docs/api/schema-reference.md, the@object-ui/typesJSDoc and Zoddescribestrings, and.changeset/7690-chart-axis-config-declared.md.Implemented by the
os-devrun for thedomain:uiseat 5, sessionsession_01KUxVUa7e39aNjhkKi1gsoy.Generated by Claude Code