Skip to content

facet_chart: add opt-in linked panel interactions#105

Merged
Alek99 merged 5 commits into
mainfrom
codex/add-linked-zoom-and-selection-for-facet_chart
Jul 20, 2026
Merged

facet_chart: add opt-in linked panel interactions#105
Alek99 merged 5 commits into
mainfrom
codex/add-linked-zoom-and-selection-for-facet_chart

Conversation

@FarhanAliRaza

@FarhanAliRaza FarhanAliRaza commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Motivation

  • Facet panels should be able to synchronize navigation and brushing so users can compare the same data window or selection across panels while preserving the current default of independent panel interactions.

Description

  • Add link: Optional[str] = None and link_select: bool = False to facet_chart/FacetChart with eager validation of allowed values (None, "x", "y", "both").
  • Make linked axes share their initial domain at build time and set a browser-local link_group + link_axes on per-panel Figure instances when linking is requested, preserving existing share_x/share_y behavior for initial-domain alignment.
  • Extend the client to broadcast and receive linked selection predicates (range, polygon, and clear) over the existing BroadcastChannel, add _broadcastLinkedSelection, and update selection handlers to accept opts that suppress duplicate dispatch/broadcast when applying incoming linked selections.
  • Surface the new options in docs (docs/guides/dashboards-and-linked-views.md) and add/adjust tests covering independent defaults, explicit link choices, link-implied domain sharing, invalid link values, and selection linking logic.

Testing

  • Built client bundle with node js/build.mjs and ran targeted suites PYTHONPATH=python pytest -q tests/test_facets.py tests/test_components.py tests/test_static_client_security.py, which all passed (138 tests).
  • Ran the full test suite with PYTHONPATH=python pytest -q, which succeeded (1,835 passed, 77 skipped).
  • Verified static client contract tests and fixed a transient client-regression discovered during the first run before the final verification, after which the security/contract tests passed.

Closes #92

@codspeed-hq

codspeed-hq Bot commented Jul 20, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 94 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing codex/add-linked-zoom-and-selection-for-facet_chart (6a75f8d) with main (e3311dd)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

@FarhanAliRaza FarhanAliRaza added valid Issue is validated. This pr actually fixes the issue. Needs Code Review. and removed codex labels Jul 20, 2026

@Alek99 Alek99 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review findings:

  • [P1] python/xy/components.py:3306: link=None removes the runtime linking that existing share_x=True/share_y=True facets receive today. This is a breaking change against the prior tests/docs; preserve it or provide an explicit migration/versioning path.
  • [P1] js/src/50_chartview.js:442: incoming linked selections use _selectLocal*, which skips density traces and cannot select drilled GPU data. Receiver facets do not highlight, and selection callbacks only see the source facet rather than the requested cross-panel result.
  • [P2] js/src/50_chartview.js:458: selection-only links still broadcast/apply view events with an empty link_axes, producing redundant LOD requests and callbacks on untouched facets. Avoid broadcasting view updates when no axes are linked.

@Alek99
Alek99 merged commit d3e9dfe into main Jul 20, 2026
24 checks passed
Alek99 added a commit that referenced this pull request Jul 21, 2026
The move in this PR promoted docs/engineering/ to spec/ and CLAUDE.md
declares that tree the source of truth. An audit of all 24 documents
against the code found the tree had drifted at PR #96: five behavior
PRs (#103, #105, #106, #108, #115) had landed with no spec update, and
~100 claims contradicted shipped code.

Accuracy: correct claims that no longer match the implementation,
including the Rust ABI version (v31 -> v36), the "zero-crate cdylib"
claim (png is a real dependency), the pyramid ABI function names, the
panic-shield status, the R2/VAO claim in the renderer doc, the
WASM/Web-Worker architecture in dossier §3/§8 (superseded by §32's
C-ABI cdylib), the count-only tier rule, the matplotlib shim overhead
figures (the cited guardrail says +60% at 10k, not +9%), and the
Plotly Scattergl 10M figure that appeared as two different numbers
from the same run.

Coverage: add spec/api/export.md, spec/api/interaction.md and
spec/design/wire-protocol.md for three surfaces that had no coverage
at all, plus the config.py threshold table, full JS and Rust module
inventories, and the hexbin centers-only wire contract that three
renderers must expand identically.

Structure: group 15 top-level files into api/, design/, matplotlib/,
benchmarks/ and process/, and rewrite spec/README.md as a real index
(it previously listed only the two SVG assets, leaving 21 of 22 docs
unreachable). All 150 consumer references repointed, including the CI
--emit-md target and the compat-matrix generator.

Guard: verify_sdist.py pinned only 5 top-level spec files, so the
sdist could silently lose spec/design/ or spec/assets/ and still
pass; it now asserts markdown under every subdirectory and both SVGs.
Alek99 added a commit that referenced this pull request Jul 21, 2026
…roup the tree (#122)

* Move engineering docs to root spec directory

* Resync spec/ with the implementation and group the tree

The move in this PR promoted docs/engineering/ to spec/ and CLAUDE.md
declares that tree the source of truth. An audit of all 24 documents
against the code found the tree had drifted at PR #96: five behavior
PRs (#103, #105, #106, #108, #115) had landed with no spec update, and
~100 claims contradicted shipped code.

Accuracy: correct claims that no longer match the implementation,
including the Rust ABI version (v31 -> v36), the "zero-crate cdylib"
claim (png is a real dependency), the pyramid ABI function names, the
panic-shield status, the R2/VAO claim in the renderer doc, the
WASM/Web-Worker architecture in dossier §3/§8 (superseded by §32's
C-ABI cdylib), the count-only tier rule, the matplotlib shim overhead
figures (the cited guardrail says +60% at 10k, not +9%), and the
Plotly Scattergl 10M figure that appeared as two different numbers
from the same run.

Coverage: add spec/api/export.md, spec/api/interaction.md and
spec/design/wire-protocol.md for three surfaces that had no coverage
at all, plus the config.py threshold table, full JS and Rust module
inventories, and the hexbin centers-only wire contract that three
renderers must expand identically.

Structure: group 15 top-level files into api/, design/, matplotlib/,
benchmarks/ and process/, and rewrite spec/README.md as a real index
(it previously listed only the two SVG assets, leaving 21 of 22 docs
unreachable). All 150 consumer references repointed, including the CI
--emit-md target and the compat-matrix generator.

Guard: verify_sdist.py pinned only 5 top-level spec files, so the
sdist could silently lose spec/design/ or spec/assets/ and still
pass; it now asserts markdown under every subdirectory and both SVGs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

valid Issue is validated. This pr actually fixes the issue. Needs Code Review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

facet_chart: opt-in linked zoom/pan/selection across panels (default stays independent)

2 participants