Skip to content

Migrate off Sandpack - #1083

Merged
jakeboone02 merged 2 commits into
mainfrom
migrate-off-sandpack
Aug 10, 2026
Merged

Migrate off Sandpack#1083
jakeboone02 merged 2 commits into
mainfrom
migrate-off-sandpack

Conversation

@jakeboone02

@jakeboone02 jakeboone02 commented Aug 10, 2026

Copy link
Copy Markdown
Member

Remove dependencies on Sandpack and implement a new live example using the updated components.

Summary by CodeRabbit

  • New Features

    • Added interactive, editable code examples with live previews in the documentation.
    • Added file tabs, syntax highlighting, responsive previews, dark-mode support, and automatic preview resizing.
    • Added clearer error reporting for compilation, runtime, and dependency-loading issues.
    • Updated external-controls examples to use the new live example experience across current and versioned documentation.
  • Bug Fixes

    • Preserved support for custom dependencies, hidden files, active files, and CSS imports in live examples.
    • Improved validation for invalid example files and duplicate file paths.

@netlify

netlify Bot commented Aug 10, 2026

Copy link
Copy Markdown

Deploy Preview for react-querybuilder ready!

Name Link
🔨 Latest commit 6bc5461
🔍 Latest deploy log https://app.netlify.com/projects/react-querybuilder/deploys/6a7a175ce35d150008cafafb
😎 Deploy Preview https://deploy-preview-1083--react-querybuilder.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd5cbae0-e666-49e6-b5e1-cddb38dab34f

📥 Commits

Reviewing files that changed from the base of the PR and between 34af8a6 and 6bc5461.

📒 Files selected for processing (5)
  • website/docs/tips/external-controls.mdx
  • website/src/components/LiveExample/LiveExample.tsx
  • website/src/components/LiveExample/runtime.ts
  • website/src/components/SandpackRQB.tsx
  • website/versioned_docs/version-7/tips/external-controls.mdx
🚧 Files skipped from review as they are similar to previous changes (4)
  • website/src/components/SandpackRQB.tsx
  • website/src/components/LiveExample/LiveExample.tsx
  • website/docs/tips/external-controls.mdx
  • website/src/components/LiveExample/runtime.ts

📝 Walkthrough

Walkthrough

The website replaces Sandpack with a Sucrase-based live example system. It compiles MDX code fences, resolves dependencies through esm.sh, runs examples in sandboxed iframes, and updates the external-controls documentation.

Changes

Live example execution

Layer / File(s) Summary
Runtime compilation and iframe bootstrap
website/src/components/LiveExample/runtime.ts
Defines virtual-file contracts, compiles modules, resolves imports, loads CSS, creates iframe documents, and reports runtime state.
Live example UI and iframe messaging
website/src/components/LiveExample/LiveExample.tsx, website/src/components/LiveExample/styles.module.css
Adds file tabs, syntax display, compilation states, iframe resizing, theme forwarding, and error overlays.
SandpackRQB integration and dependency wiring
website/src/components/SandpackRQB.tsx, website/package.json
Parses MDX fences, merges dependencies, handles stylesheet imports, and renders the browser-only live example.
External-controls documentation migration
website/docs/tips/external-controls.mdx, website/versioned_docs/version-7/tips/external-controls.mdx
Converts uncontrolled examples to live SandpackRQB examples and sets controlled examples to React Query Builder v7.

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

Sequence Diagram(s)

sequenceDiagram
  participant SandpackRQB
  participant LiveExample
  participant Runtime
  participant Iframe
  participant esm.sh
  SandpackRQB->>LiveExample: Pass virtual files and dependencies
  LiveExample->>Runtime: Compile files and build srcdoc
  Runtime->>esm.sh: Resolve bare imports and CSS
  Runtime-->>LiveExample: Return compiled iframe document
  LiveExample->>Iframe: Mount srcdoc
  Iframe-->>LiveExample: Send readiness, height, theme, and error events
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing Sandpack with a new live-example implementation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch migrate-off-sandpack

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

@pkg-pr-new

pkg-pr-new Bot commented Aug 10, 2026

Copy link
Copy Markdown
More templates

@react-querybuilder/antd

bun add https://pkg.pr.new/@react-querybuilder/antd@1083

@react-querybuilder/bootstrap

bun add https://pkg.pr.new/@react-querybuilder/bootstrap@1083

@react-querybuilder/bulma

bun add https://pkg.pr.new/@react-querybuilder/bulma@1083

@react-querybuilder/chakra

bun add https://pkg.pr.new/@react-querybuilder/chakra@1083

@react-querybuilder/core

bun add https://pkg.pr.new/@react-querybuilder/core@1083

@react-querybuilder/datetime

bun add https://pkg.pr.new/@react-querybuilder/datetime@1083

@react-querybuilder/dnd

bun add https://pkg.pr.new/@react-querybuilder/dnd@1083

@react-querybuilder/expr

bun add https://pkg.pr.new/@react-querybuilder/expr@1083

@react-querybuilder/fluent

bun add https://pkg.pr.new/@react-querybuilder/fluent@1083

@react-querybuilder/mantine

bun add https://pkg.pr.new/@react-querybuilder/mantine@1083

@react-querybuilder/material

bun add https://pkg.pr.new/@react-querybuilder/material@1083

@react-querybuilder/native

bun add https://pkg.pr.new/@react-querybuilder/native@1083

@react-querybuilder/prime

bun add https://pkg.pr.new/@react-querybuilder/prime@1083

react-querybuilder

bun add https://pkg.pr.new/react-querybuilder@1083

@react-querybuilder/rules-engine

bun add https://pkg.pr.new/@react-querybuilder/rules-engine@1083

@react-querybuilder/tremor

bun add https://pkg.pr.new/@react-querybuilder/tremor@1083

commit: 6bc5461

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (ee0d877) to head (6bc5461).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #1083   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          362       362           
  Lines        11085     11085           
  Branches      4778      4814   +36     
=========================================
  Hits         11085     11085           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🧹 Nitpick comments (6)
website/docs/tips/external-controls.mdx (1)

25-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use type-only imports in both TSX virtual files. Field and RuleGroupType only occur in type positions.

  • website/docs/tips/external-controls.mdx#L25-L39: move Field and RuleGroupType to an import type declaration.
  • website/versioned_docs/version-7/tips/external-controls.mdx#L25-L39: make the same import change.

As per coding guidelines, **/*.{ts,tsx} requires import type for type-only imports.

🤖 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 `@website/docs/tips/external-controls.mdx` around lines 25 - 39, Update the
imports in website/docs/tips/external-controls.mdx (lines 25-39) and
website/versioned_docs/version-7/tips/external-controls.mdx (lines 25-39) so
Field and RuleGroupType are moved to an import type declaration, while runtime
imports remain unchanged.

Source: Coding guidelines

website/src/components/SandpackRQB.tsx (2)

117-120: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Share the entry-path list with the runtime.

runtime.ts line 299 accepts /App.tsx, /App.js, /App.jsx, and /App.ts as the entry module. This check only looks at /App.tsx and /App.js. An /App.jsx entry that already imports the stylesheet still gets the extra <link>. The duplicate is harmless today because collectCSSLinks dedupes, but the two lists will drift. Export the entry-path list from runtime.ts and reuse it here.

🤖 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 `@website/src/components/SandpackRQB.tsx` around lines 117 - 120, Export the
shared entry-path list from runtime.ts and reuse it in the extraCSSImports
useMemo in SandpackRQB, replacing the local /App.tsx and /App.js checks so
/App.jsx and /App.ts are handled consistently with the runtime entry-module
logic.

55-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace the any element cast with a narrow fence type.

The guideline asks for strict TypeScript. Line 56 casts to React.ReactElement<any>, so props.metastring, props.className, and props.children are unchecked. Line 86 then re-asserts props.className as string | undefined. Declare a local interface FenceProps { metastring?: string; className?: string; children: string } and cast once to React.ReactElement<{ children: React.ReactElement<FenceProps> }>. The oxlint suppression then becomes unnecessary.

As per coding guidelines: "**/*.{ts,tsx}: Use strict TypeScript with constrained generics, conditional types, branded types, and import type for type-only imports."

Also applies to: 86-86

🤖 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 `@website/src/components/SandpackRQB.tsx` around lines 55 - 56, In SandpackRQB,
replace the React.ReactElement<any> cast for codeSnippets with a local
FenceProps interface defining optional metastring and className strings plus
required string children, then cast once to React.ReactElement<{ children:
React.ReactElement<FenceProps> }>. Remove the oxlint suppression and the
redundant props.className as string | undefined assertion, relying on the
constrained FenceProps type.

Source: Coding guidelines

website/src/components/LiveExample/LiveExample.tsx (1)

176-195: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Complete the tab ARIA pattern.

The tab list declares role="tablist" and role="tab", but no element declares role="tabpanel", and the tabs have no aria-controls. Screen readers announce a tab widget that has no associated panel. The tablist role also implies arrow-key navigation between tabs, which is not implemented.

Add id and aria-controls links plus role="tabpanel" on the code container, or drop the tab roles and keep plain buttons.

🤖 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 `@website/src/components/LiveExample/LiveExample.tsx` around lines 176 - 195,
The tab widget in the LiveExample render lacks an accessible panel and keyboard
navigation support. Either complete the ARIA pattern by assigning stable tab and
panel IDs, linking each tab’s aria-controls to the code container, adding
role="tabpanel" with the active tab’s aria-labelledby, and implementing
arrow-key navigation, or remove the tablist/tab roles and retain plain buttons.
website/src/components/LiveExample/runtime.ts (1)

211-221: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Reconsider the unconditional 250 ms polling loop.

ResizeObserver on #root plus the load listener already cover content-driven changes. The interval at line 221 adds a forced layout read every 250 ms for the life of each iframe. A docs page with several examples pays this cost continuously, including while the examples are off screen.

If the interval only covers absolutely positioned overflow that ResizeObserver misses, then observe document.body as well and remove the interval, or stop the interval once the height stabilizes.

🤖 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 `@website/src/components/LiveExample/runtime.ts` around lines 211 - 221, Remove
the unconditional setInterval polling from the report setup and extend
ResizeObserver coverage to document.body alongside `#root`, preserving the
existing load listener and height-change reporting behavior in report.
website/src/components/LiveExample/styles.module.css (1)

1-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

This file deviates from the stylesheet guideline.

The guideline asks for SCSS with BEM-like class names and SCSS variables for design tokens. This file is plain CSS with camelCase CSS-module class names. The camelCase names are required by the styles.codeColumn access pattern in LiveExample.tsx, so confirm that the guideline is intended to cover Docusaurus CSS modules. If it is, rename the file to styles.module.scss.

As per coding guidelines: "**/*.{scss,css}: Use SCSS with CSS custom properties, BEM-like class names such as .queryBuilder-rule, and SCSS variables for design tokens."

🤖 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 `@website/src/components/LiveExample/styles.module.css` around lines 1 - 19,
Convert LiveExample’s stylesheet from styles.module.css to styles.module.scss,
preserving the existing styles.codeColumn and related CSS-module access patterns
in LiveExample.tsx. Retain CSS custom properties for design tokens and update
class selectors only as needed to follow the project’s BEM-like naming
guideline.

Source: Coding guidelines

🤖 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 `@website/src/components/LiveExample/LiveExample.tsx`:
- Around line 63-95: Validate the message sender before processing payloads in
both handlers: in LiveExample.tsx, have the onMessage handler return unless
event.source equals iframeRef.current?.contentWindow before handling height or
error data; in website/src/components/LiveExample/runtime.ts lines 240-244,
return unless e.source equals parent before toggling the dark class. These are
the only required changes at the listed sites.
- Around line 25-28: Update loadSucrase so a rejected dynamic import clears
sucrasePromise before propagating the error, allowing subsequent LiveExample
instances or client-side navigations to retry the load while preserving the
single shared promise for successful loads.

In `@website/src/components/LiveExample/runtime.ts`:
- Line 68: Update buildImportMap and the REACT_VERSION configuration so
customSetup.dependencies entries for react and react-dom are either honored when
constructing imports or explicitly rejected with a clear error; do not silently
ignore requested versions while forcing React 18. Preserve React Query Builder’s
React >=18 compatibility when no custom versions are provided.

In `@website/src/components/SandpackRQB.tsx`:
- Around line 54-93: Update parseFences and its useMemo caller to avoid throwing
for malformed author input: validate each child’s fence shape before accessing
codeSnippet.props.children, and return a parse-error result instead of throwing
for invalid children, missing filenames, or duplicate paths. Propagate that
error to the component state and render it beside the existing compile-error
overlay, while preserving normal LiveFile parsing for valid fences.

---

Nitpick comments:
In `@website/docs/tips/external-controls.mdx`:
- Around line 25-39: Update the imports in
website/docs/tips/external-controls.mdx (lines 25-39) and
website/versioned_docs/version-7/tips/external-controls.mdx (lines 25-39) so
Field and RuleGroupType are moved to an import type declaration, while runtime
imports remain unchanged.

In `@website/src/components/LiveExample/LiveExample.tsx`:
- Around line 176-195: The tab widget in the LiveExample render lacks an
accessible panel and keyboard navigation support. Either complete the ARIA
pattern by assigning stable tab and panel IDs, linking each tab’s aria-controls
to the code container, adding role="tabpanel" with the active tab’s
aria-labelledby, and implementing arrow-key navigation, or remove the
tablist/tab roles and retain plain buttons.

In `@website/src/components/LiveExample/runtime.ts`:
- Around line 211-221: Remove the unconditional setInterval polling from the
report setup and extend ResizeObserver coverage to document.body alongside
`#root`, preserving the existing load listener and height-change reporting
behavior in report.

In `@website/src/components/LiveExample/styles.module.css`:
- Around line 1-19: Convert LiveExample’s stylesheet from styles.module.css to
styles.module.scss, preserving the existing styles.codeColumn and related
CSS-module access patterns in LiveExample.tsx. Retain CSS custom properties for
design tokens and update class selectors only as needed to follow the project’s
BEM-like naming guideline.

In `@website/src/components/SandpackRQB.tsx`:
- Around line 117-120: Export the shared entry-path list from runtime.ts and
reuse it in the extraCSSImports useMemo in SandpackRQB, replacing the local
/App.tsx and /App.js checks so /App.jsx and /App.ts are handled consistently
with the runtime entry-module logic.
- Around line 55-56: In SandpackRQB, replace the React.ReactElement<any> cast
for codeSnippets with a local FenceProps interface defining optional metastring
and className strings plus required string children, then cast once to
React.ReactElement<{ children: React.ReactElement<FenceProps> }>. Remove the
oxlint suppression and the redundant props.className as string | undefined
assertion, relying on the constrained FenceProps type.
🪄 Autofix

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: fb89b7aa-f301-4637-bedd-6d377dcaba17

📥 Commits

Reviewing files that changed from the base of the PR and between 7cb18a2 and 34af8a6.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • website/docs/tips/external-controls.mdx
  • website/package.json
  • website/src/components/LiveExample/LiveExample.tsx
  • website/src/components/LiveExample/runtime.ts
  • website/src/components/LiveExample/styles.module.css
  • website/src/components/SandpackRQB.tsx
  • website/versioned_docs/version-7/tips/external-controls.mdx

Comment thread website/src/components/LiveExample/LiveExample.tsx Outdated
Comment thread website/src/components/LiveExample/LiveExample.tsx
Comment thread website/src/components/LiveExample/runtime.ts Outdated
Comment thread website/src/components/SandpackRQB.tsx Outdated
@jakeboone02
jakeboone02 merged commit 85b7d64 into main Aug 10, 2026
16 of 17 checks passed
@jakeboone02
jakeboone02 deleted the migrate-off-sandpack branch August 10, 2026 20:37
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