Repository navigation
fix(plugin-charts): place the x axis by the spec xAxis.position, and refuse a side it cannot take (objectui#10587) - #10647
Conversation
…d refuse a side it cannot take `top` / `bottom` set `orientation` on the x axis of bar, line, area, combo and scatter. On horizontal-bar the `xAxis` object configures the category axis, which runs down the plot, so `left` / `right` set that axis's side. A side the axis cannot take draws the axis at its default side and adds a `data-chart-note="x-axis-position"` note naming `xAxis.position`. A top axis mirrors the title layout and the rotated-label slant, so both stay on the far side from the plot. Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN Co-authored-by: Claude <noreply@anthropic.com>
… the objectui#10516 sentence it falsifies The `position` row now states the x-axis reading: `top` / `bottom` where the x axis runs across the plot, `left` / `right` on horizontal-bar, and the note any other side gets. The objectui#10516 changeset keeps its "at this change" sentence and gains a dated note pointing at this entry; its front matter is byte-identical. Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN Co-authored-by: Claude <noreply@anthropic.com>
…er reads Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN Co-authored-by: Claude <noreply@anthropic.com>
…, not from a derived local A derived local in the `xAxisCommonProps` dependency list added a second React Compiler `preserve-manual-memoization` warning to the file; choosing the layout through a module function keyed on `xAxisAcross` keeps the file's lint findings at the base count. Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN 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
|
|
CI note from the
Generated by Claude Code |
Contract reviewServed-tier: ① Derived judgmentsThe mapping — covered, and stated. At head the file draws a recharts XAxis at four sites: scatter's number XAxis (~2294), the combo ComposedChart (~2406, Horizontal-bar reading — right, and stated in code (the A valid side is never also noted. One false comment (non-blocking, wording). The diff at ~1677 says " "A loud refusal, not silence" — yes, in the file's own terms. The docs Pins (29) — reproduced. Scratch worktree at the head (node_modules borrowed from a sibling worktree at 4a3d500; Dev findings — both real at source, both owed cards. (1) horizontal-bar: measured at head, ② Semver level
③ Boundary flags
Implemented-by: VERDICT: FAIL What stops it: the touched docs Generated by Claude Code |
… the y side at objectui#10654 The row's first sentence was unscoped, so it also described `yAxis`, where `position` does not reliably set the side: an authored combo with a lone right-hand entry and no series draws on the right, and elsewhere the key is ignored or mis-applied. The row now ends by pointing at objectui#10654 instead of restating per-family readings. The `categoriesRunDown` comment no longer claims a horizontal-bar can become a combo: `comboBaseFamily` never widens one, so a horizontal-bar with mixed series stays horizontal and keeps the `left` / `right` reading. Claude-Session: https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN Co-authored-by: Claude <noreply@anthropic.com>
✅ 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: ① Derived judgmentsRound 2 is exactly the two edits. The The comment (~1677-1682). True: The landing body, Round 2 section. "one published sentence … also covered ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #10587
Clause-②: no — the renderer begins honouring a key the spec already declares; no export, schema or accept set moves.
What changed
xAxis.positionis declared on@objectstack/spec'sChartAxisSchema(whichChartSchema.xAxistakes by reference) and, since objectui#10516, kept bynormalizeChartSchema. No axis read it. This change makes the renderer read it, inpackages/plugin-charts/src/AdvancedChartImpl.tsxonly.The mapping (
placeXAxis, stated in its doc comment):xAxisis drawnXAxis(category band) across the plottop/bottom→orientationXAxis type="number"across the plottop/bottom→orientationYAxis type="category"down the plotleft/right→orientationHorizontal-bar reading, decided by what the branch already does: it swaps the axis roles (
yAxisSpecProps(primaryY)configures its numberXAxis, andxTickFormatter, built fromxAxis.format, formats its categoryYAxis). So thexAxisobject already follows the categories there, andpositionfollows them too. Reading it as "the horizontal axis" would split one axis object across two drawn axes.A side the axis cannot take (
left/rightacross the plot;top/bottomon horizontal-bar) is refused, loudly, in the file's existing partial-answer channel: the chart still draws, with the axis at its default side, andChartFootnoteadds ap role="note" data-chart-note="x-axis-position"namingxAxis.position, the value, and the side the axis was drawn on. Not aChartRefusal(that replaces the whole tile and would blank a chart that plots correctly over one presentation key), and no console warning, for the reason the other notes give: the sentence already names the key and the value. No new diagnostic channel; no schema narrowing (ChartAxisSchemais shared by both axes and is the spec's).A top axis mirrors the bottom layout: the title uses
insideTop(theinsideBottomlayout mirrored) and rotated tick labels slant35instead of-35, so both stay on the far side of the axis from the plot.A chart that declares no
positionemits noorientationprop and no note; the bottom / no-position controls below pin that.Docs: the
positionrow ofcontent/docs/plugins/plugin-charts.mdxnow states the x-axis reading and, foryAxis, points at objectui#10654 (round 2, below). Changesets:.changeset/10587-xaxis-position.md('@object-ui/plugin-charts': patch);.changeset/10516-xaxis-presentation-gate.mdkeeps its "at this change no renderer reads it" sentence and gains a dated note pointing here (front matter md5efdd05dcdeaee331682c8032a97b743bbefore and after).Measured on the base (
651632062)ChartRendererwithxAxis: { field: 'month', position: 'top' }(andleft) on bar, line, area, combo, horizontal-bar and scatter: every category tick label carriedorientation="bottom"(horizontal-bar:left), identical to the no-position render, and no note. The x axis ignored the key everywhere.Pins:
ChartRenderer.xAxisPosition-10587.test.tsx(29 tests, throughChartRenderer, reading the rendered tickorientation)904b074ac:Tests 29 passed (29)AdvancedChartImpl.tsxblob364cc5f5= the base blob, restored to the head blob afterwards andgit diff HEADempty):Tests 18 failed | 11 passed. The 18 red are every non-control pin; the 11 green are exactly the controls (bottom/ no position on bar, line, area, scatter;left/ no position on horizontal-bar; the bottom title and bottom rotation controls).Per-hunk ablation (
ablation-replace.mjs, anchor hit x1, blob changed, restored to the head blob each time)Run at
f2fe3e70a, whose five hunks below are byte-identical at904b074ac; the title hunk moved intoxAxisTitleLayoutForin904b074acand was ablated again there.orientationinxAxisCommonPropstoporientationon the scatterXAxistoporientationon the horizontal-bar categoryYAxisrightx-axis-positionnote (forcednull)904b074acinxAxisTitleLayoutFor)-35)Gates (local, head
904b074ac)pnpm --filter @object-ui/plugin-charts type-check(tsc --noEmit && tsc -p tsconfig.test.json; the test program lists the new pin file): exit 0, 0error TS. Dependency closure built first:pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-charts^...' buildexit 0.pnpm exec vitest run packages/plugin-charts/:Test Files 77 passed (77)·Tests 876 passed (876).check-changeset-presence:✅ 2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/10587-xaxis-position.md.check-changeset-no-major:✅ No changeset declares a major bump.·check-changeset-overwrite: report-only, exit 0 (the dated note, below) ·check-changeset-claims: report-only, exit 0 ·check-pending-changeset-literals:✅ No test source names a pending changeset.check:new-line-citations:VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0check:control-bytes:✅ check-control-bytes: OKcheck-doc-links(Links are valid across 17 scan roots.),check-doc-component-types,check-prompt-component-keys,check-doc-example-ids,check-doc-fence-languages(and--self-test),check-shell-escape-residue,check-doc-expression-carriage: all exit 0.check-vi-mock-specifiers,check-vi-mock-inherit,check-vi-mock-override-shape,check-test-path-roots: all✅ … OK.eslint --format jsonover the two changed TS files, the only lintable files this diff changes inpackages/plugin-charts(whoselintscript iseslint .): 2 files, 0 errors, 44 warnings, the same rule tally as the base file (39no-explicit-any, 4exhaustive-deps, 1preserve-manual-memoization). 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.Round 2 (head
ef357e489)Contract review FAIL on one published sentence: the docs row opened with the unscoped "The side of the chart the axis belongs to.", which also covered
yAxis, wherepositiondoes not reliably set the side. Two edits, one commit:positionrow keeps the x-axis text and now ends: "OnyAxisit does not yet reliably set the side the axis is drawn on (objectui#10654, the y-side twin of objectui#10587)." It points at the card instead of restating per-family readings. Those readings are objectui#10654's to change, and a copy in published docs would go false when that card lands (AGENTS.md 完善设计器的每一个细节 #9). A first draft, "OnyAxisit is not yet honoured", was measured false and not landed. An authoredchartType: 'combo'with a loneyAxisentry atposition: 'right'and noseriesdraws its data on a right-hand axis: the normalizer derives the series from the y entries and binds that one to the right. Withposition: 'left'or no position the same chart draws on the left.categoriesRunDownno longer claims a horizontal-bar can become a combo.comboBaseFamilynever widens a horizontal-bar, so one with mixed series stays horizontal and keeps theleft/rightreading. Comment only; no code change.Clause check before commit: a throwaway jsdom probe through
ChartRendererat904b074ac(61 plus 27 schemas, all runs passed, probe files deleted). EveryxAxisclause in the row matched it, and so did theyAxissentence (the side is set in the authored-combo shape above and not in the others).Gates at
ef357e489:ChartRenderer.xAxisPosition-10587.test.tsx:Tests 29 passed (29), via os-verify-lock (VERDICT command-exit 0).check-changeset-presence:✅ 2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/10587-xaxis-position.md.check-changeset-no-major:✅ No changeset declares a major bump.check:control-bytes:✅ check-control-bytes: OK (scanned 8734 tracked text file(s); skipped 85 binary).check:new-line-citations:VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0check-changeset-overwriteandcheck-changeset-claims: report-only, exit 0. They report the same two items as round 1; the.changeset/7546-chart-series-keys-declared.mdparagraph they flag is about series keys and is still true.check-pending-changeset-literals:✅ No test source names a pending changeset.check-doc-links(Links are valid across 17 scan roots.),check-doc-component-types(✅ Every documented component type is registered.),check-prompt-component-keys,check-doc-example-ids(✅ 414 real reference(s) all resolve in the catalog registry.),check-doc-fence-languages(plus--self-test),check-shell-escape-residueandcheck-doc-expression-carriage: all exit 0.git merge-tree --write-treeagainst a freshorigin/main(785d3a731): exit 0, and main touched none of this PR's files, so no merge was needed.904b074acstand.Acceptance notes
insideTopvsinsideBottom, same offset), so its spacing to the ticks is the bottom axis's.xAxiskey at all,positionincluded; unchanged.positionis objectui#10654 (a lone right-handyAxisentry on bar draws on the left,top/bottomon a y entry pass in silence, and the round-2 findings: a horizontal-bar with two y entries drops bars, and a derived series follows a first entry'srightto the right-hand axis); the horizontal-bar axis titles (xAxis.titlenot drawn, theyAxistitle laid out as a vertical-axis title on the horizontal value axis) are objectui#10655.check-changeset-overwritereports the dated-note edit to.changeset/10516-xaxis-presentation-gate.md; that is its case 2 (a deliberate correction), report-only.check-changeset-claimsasks for a re-read of.changeset/7546-chart-series-keys-declared.md, which namesAdvancedChartImpl.tsx: that paragraph is about series keys and is still true.Implemented by the
os-devrun for thedomain:uiseat 2, sessionsession_014mXUNuFomfj24w7s1pZzhN.Generated by Claude Code