Skip to content

Expose complete chart chrome styling to CSS and Tailwind - #412

Open
Alek99 wants to merge 7 commits into
mainfrom
agent/expose-complete-styling-surface
Open

Expose complete chart chrome styling to CSS and Tailwind#412
Alek99 wants to merge 7 commits into
mainfrom
agent/expose-complete-styling-surface

Conversation

@Alek99

@Alek99 Alek99 commented Jul 31, 2026

Copy link
Copy Markdown
Member

Why

The public styling surface stopped at 29 validated DOM slots. That meant class_names, styles, plain CSS, and Tailwind could style the toolbar and its buttons, but not the draggable grip that reveals/moves the modebar. The same gap existed for modebar groups and popovers, Cartesian axis spines/ticks, axis gesture bands, colorbar extensions/contour lines/minor ticks, and the canvas-painted annotation layer. Several of those parts also pinned visual defaults inline, so ordinary utility classes could not win the cascade.

What changed

  • Expands CHART_DOM_SLOTS from 29 to 48 stable hooks.
  • Exposes every visible modebar layer: drag handle, control group, separator, button icon, zoom value, indicators, active selection icon, menus, menu separators/icons/labels, and history controls.
  • Exposes Cartesian axis_line, tick_mark, and axis_band parts, with data-xy-axis, data-xy-axis-side, and data-xy-tick-kind refinements.
  • Exposes colorbar_extension, colorbar_line, and colorbar_minor_tick.
  • Exposes annotation_layer for whole-bitmap CSS effects while keeping individual annotation geometry in the cross-renderer typed API.
  • Moves axis, colorbar-line/minor-tick, and axis-band visual defaults into the zero-specificity base layer so author CSS and Tailwind utilities override them normally.
  • Restores the authored axis-band cursor after drag state instead of leaving a default cursor inline.
  • Adds a source contract for every public slot and a real Chromium probe covering all 19 new surfaces.
  • Adds a category-by-category audit for Overview, Marks, Axes, Legends, Tooltips, Colorbars, Modebars & controls, Annotations, Triangle Mesh, Facets/Layers, and Other: spec/process/css-tailwind-surface-audit-2026-07-30.md.

Marks and triangle-mesh faces remain WebGL/canvas pixels rather than one DOM node per primitive. Their complete styling route is the validated CSS-shaped mark API, typed channels/geometry, and CSS theme-token bridge; preserving that boundary keeps XY's large-data performance model intact.

Browser evidence

Both captures use the same dark-theme chart spec, utility stylesheet, and class strings, including XY's documented .dark selector so the toolbar matches the chart surface. The before capture substitutes the pre-change standalone bundle; the after capture uses this branch. The modebar is intentionally styled as one blue/cyan glow system across its outer surface, buttons, grip, separators, icons, indicators, history controls, and open menu.

Before

Before: new utility classes cannot reach the grip, menu internals, colorbar parts, or Cartesian rules

After

After: the entire modebar is a coherent blue-glow theme, while its nested parts remain independently styleable

The pair is reproducible with scripts/css_tailwind_slot_evidence.py.

Validation

  • node js/build.mjs
  • uv run pytest -q — 3,683 passed, 110 skipped
  • uv run --project docs/app --no-sync pytest docs/app/tests -q — 103 passed, 1 xfailed
  • uv run --with pre-commit pre-commit run --all-files
  • uv run ruff check .
  • uv run ruff format --check .
  • uv run python scripts/gen_capability_matrix.py --check
  • Real Chromium computed-style probe for every added slot and former inline default

uv run ty check remains non-clean on the base repository with 89 pre-existing diagnostics (principally missing optional Reflex imports in the root environment and unrelated pyplot typing issues); none are in the files introduced by this change.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Expanded browser styling support from 29 to 48 independently targetable chart elements.
    • Added granular styling hooks for annotations, axes, ticks, colorbars, modebars, menus, icons, and interaction controls.
    • Added CSS, inline style, and Tailwind customization options, including axis-band cursor and independent modebar icon and label styling.
  • Documentation

    • Updated styling guides, capability references, export notes, and examples.
    • Clarified canvas-rendered annotation and grid-line styling limitations.
  • Tests

    • Added coverage for styling hooks, computed styles, cursors, and visual customization.

@codspeed-hq

codspeed-hq Bot commented Jul 31, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 109 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing agent/expose-complete-styling-surface (e1c9f3b) with main (a2f2976)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The browser styling contract expands from 29 to 48 DOM slots. Rendering and interaction code applies slots for annotations, colorbars, axes, ticks, and modebar components. Documentation, browser evidence, and regression tests cover the expanded surface.

Changes

Browser styling contract

Layer / File(s) Summary
Slot contract and documentation
python/xy/dom.py, docs/..., spec/..., CHANGELOG.md
Defines and documents the 48 browser styling slots.
Renderer CSS slot application
js/src/20_theme.ts, js/src/50_chartview.ts
Moves visual properties into stylesheet slots and CSS custom properties.
Modebar and axis interaction slots
js/src/53_interaction.ts, js/src/57_viewstate.ts
Adds granular modebar elements and manages axis-band cursor state.
Browser styling evidence
scripts/css_tailwind_slot_evidence.py
Builds an instrumented chart fixture and captures Chromium evidence.
Slot and interaction regression coverage
tests/*, docs/app/tests/test_docs_site.py, scripts/render_smoke_nonumpy.py
Validates slot registration, DOM application, Tailwind styles, computed dimensions, and cursor transitions.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ChartRenderer
  participant StyleSheet
  participant Browser
  participant RegressionTests
  ChartRenderer->>Browser: Apply DOM styling slots and CSS custom properties
  StyleSheet->>Browser: Apply slot selectors and visual defaults
  Browser->>RegressionTests: Expose computed styles and DOM slot markers
  RegressionTests->>RegressionTests: Validate styling and cursor transitions
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: exposing chart chrome styling through CSS and Tailwind.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/expose-complete-styling-surface

Comment @coderabbitai help to get the list of available commands.

@Alek99
Alek99 force-pushed the agent/expose-complete-styling-surface branch from f3aed86 to d03765e Compare July 31, 2026 07:21
@Alek99
Alek99 marked this pull request as ready for review July 31, 2026 18:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
scripts/css_tailwind_slot_evidence.py (1)

254-279: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Verify the screenshot file exists after Chromium runs.

_screenshot only checks result.returncode. Chromium can exit 0 without writing png_path in some sandboxed or resource-constrained conditions. Since this script generates the release evidence referenced in the PR validation steps, a silent no-op here lets the audit workflow report success without producing the required image.

Add an existence check after the subprocess call.

🛡️ Proposed fix
     if result.returncode != 0:
         raise RuntimeError(result.stderr.strip() or f"Chromium exited {result.returncode}")
+    if not png_path.exists():
+        raise RuntimeError(f"Chromium exited 0 but did not write {png_path}")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/css_tailwind_slot_evidence.py` around lines 254 - 279, Update
_screenshot after subprocess.run to verify that png_path exists, raising a clear
RuntimeError if Chromium exits successfully without producing the screenshot;
preserve the existing nonzero-return handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/components/axes.md`:
- Around line 230-236: Update the axis styling example’s axis_band cursor rule
to distinguish x- and y-axis gesture bands using data-xy-axis selectors: apply
ew-resize to x and ns-resize to y, or replace the directional cursor with a
direction-neutral class.

In `@js/src/57_viewstate.ts`:
- Around line 473-476: Update the drag lifecycle around _applySlot and the
pointer release handlers to preserve the axis-band’s existing inline cursor
value and priority before applying “grabbing”. Restore both with setProperty on
pointerup and pointercancel instead of removing the cursor property, and add a
regression test covering styles={"axis_band": {"cursor": "crosshair"}}.

---

Nitpick comments:
In `@scripts/css_tailwind_slot_evidence.py`:
- Around line 254-279: Update _screenshot after subprocess.run to verify that
png_path exists, raising a clear RuntimeError if Chromium exits successfully
without producing the screenshot; preserve the existing nonzero-return handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5884e271-ce24-4546-852a-60d743320262

📥 Commits

Reviewing files that changed from the base of the PR and between d505ef5 and dcd71fe.

⛔ Files ignored due to path filters (2)
  • pr-assets/css-tailwind-slot-audit/after.png is excluded by !**/*.png
  • pr-assets/css-tailwind-slot-audit/before.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • CHANGELOG.md
  • docs/app/tests/test_docs_site.py
  • docs/components/annotations.md
  • docs/components/axes.md
  • docs/components/colorbars.md
  • docs/components/modebars-and-interaction-controls.md
  • docs/styling/capabilities.md
  • docs/styling/chrome-slots.md
  • docs/styling/component-variations.md
  • docs/styling/customize.md
  • docs/styling/mark-styles.md
  • js/src/20_theme.ts
  • js/src/50_chartview.ts
  • js/src/53_interaction.ts
  • js/src/57_viewstate.ts
  • python/xy/dom.py
  • scripts/css_tailwind_slot_evidence.py
  • scripts/render_smoke_nonumpy.py
  • spec/README.md
  • spec/api/capability-matrix.md
  • spec/api/export.md
  • spec/api/styling.md
  • spec/design-dossier.md
  • spec/design/reflex-shaped-api.md
  • spec/process/css-tailwind-surface-audit-2026-07-30.md
  • tests/test_static_client_security.py
  • tests/test_tailwind_root_customization.py
  • tests/test_type_surface.py
  • tests/test_view_state_client.py

Comment thread docs/components/axes.md
Comment thread js/src/57_viewstate.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 31 files

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread js/src/50_chartview.ts Outdated
Comment thread scripts/css_tailwind_slot_evidence.py Outdated
Comment thread scripts/css_tailwind_slot_evidence.py Outdated
Comment thread docs/components/colorbars.md Outdated
Comment thread docs/components/axes.md Outdated
Comment thread scripts/css_tailwind_slot_evidence.py Outdated
Comment thread js/src/57_viewstate.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
scripts/css_tailwind_slot_evidence.py (1)

289-291: 🔒 Security & Privacy | 🔵 Trivial

--no-sandbox disables Chromium's OS-level sandbox.

This script only loads a locally generated HTML fixture, so the practical exposure is limited compared to loading untrusted or remote content. Keep this scoped to trusted, internally generated evidence HTML. Do not reuse this flag combination for a script that could load external or user-supplied URLs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/css_tailwind_slot_evidence.py` around lines 289 - 291, Keep the
--no-sandbox flag limited to the Chromium invocation in the trusted local
evidence-HTML flow of the script. Ensure this browser configuration is not
reused by code that loads external or user-supplied URLs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/css_tailwind_slot_evidence.py`:
- Around line 246-252: Update the SLOT_CLASSES definition to include the missing
documented colorbar slots: colorbar, colorbar_bar, colorbar_tick, and
colorbar_title, alongside the existing entries. Preserve the renderer’s
seven-slot colorbar contract and avoid changing the colorbar specification shown
in the diff.

In `@tests/test_view_state_client.py`:
- Line 1685: Update the assertion in the relevant view-state client test to
compare result against an explicit mapping containing all five expected probe
keys with True values, rather than deriving expected keys from result. Ensure
the assertion fails if any expected field is missing from the JSON payload.

---

Nitpick comments:
In `@scripts/css_tailwind_slot_evidence.py`:
- Around line 289-291: Keep the --no-sandbox flag limited to the Chromium
invocation in the trusted local evidence-HTML flow of the script. Ensure this
browser configuration is not reused by code that loads external or user-supplied
URLs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7ee1ff2a-df6c-43e1-a47e-83d64a02a90c

📥 Commits

Reviewing files that changed from the base of the PR and between dcd71fe and ebcd3a5.

📒 Files selected for processing (7)
  • docs/components/axes.md
  • docs/components/colorbars.md
  • js/src/50_chartview.ts
  • js/src/57_viewstate.ts
  • scripts/css_tailwind_slot_evidence.py
  • tests/test_tailwind_root_customization.py
  • tests/test_view_state_client.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/components/axes.md
  • tests/test_tailwind_root_customization.py
  • js/src/57_viewstate.ts
  • js/src/50_chartview.ts

Comment thread scripts/css_tailwind_slot_evidence.py
Comment thread tests/test_view_state_client.py Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 9 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread docs/components/axes.md Outdated
Comment thread docs/components/colorbars.md Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

Comment thread docs/components/colorbars.md Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant