Skip to content

feat: Add interactive browser-based playground and component gallery#1646

Open
Subhash21022 wants to merge 2 commits into
Karanjot786:mainfrom
Subhash21022:feat/InteractivePlayGroundComponenets
Open

feat: Add interactive browser-based playground and component gallery#1646
Subhash21022 wants to merge 2 commits into
Karanjot786:mainfrom
Subhash21022:feat/InteractivePlayGroundComponenets

Conversation

@Subhash21022

@Subhash21022 Subhash21022 commented Jun 19, 2026

Copy link
Copy Markdown

Description

This PR introduces an interactive, browser-based playground and component gallery for the TermUI website. It utilizes @babel/standalone to parse TypeScript/JSX in the browser on the fly, and seamlessly integrates xterm.js to render the TermUI components exactly as they would appear in a real terminal (complete with absolute positioning, flexbox layouts, and true colors). Users can select from several preset examples (e.g., System Dashboard, Command Palette, Form) and edit the code in real-time to immediately see the capabilities of the library live.

Related Issue

Closes #1637

Which package(s)?

website, @termuijs/jsx

Type of Change

  • 🐛 Bug fix (type:bug)
  • ✨ Feature (type:feature)
  • 📝 Docs (type:docs)
  • 🧪 Tests (type:testing)
  • ♻️ Refactor (type:refactor)
  • 🎨 Design / UX (type:design)
  • ♿ Accessibility (type:accessibility)
  • ⚡ Performance (type:performance)
  • 🔧 DevOps / CI (type:devops)
  • 🔒 Security (type:security)

Checklist

  • ⭐ You starred the repo. The needs-star check blocks your merge otherwise.
  • Tests pass locally: bun vitest run
  • Build passes: bun run build
  • Typecheck passes: bun run typecheck
  • You read CONTRIBUTING.md.
  • Your PR title follows type: short description. (Suggested title: feat: add interactive playground and component gallery to website)
  • Widget state mutators call markDirty() (if your change affects rendering).
  • No new any types without an inline comment explaining why.
  • No unrelated refactors bundled into this PR.

GSSoC 2026 Participation

  • You are a GSSoC 2026 contributor.
  • Your GSSoC profile: https://gssoc.girlscript.org/profile/____

Screenshots / Recordings (UI changes)

image

Notes for the Reviewer

  • A new setCurrentApp export was added to @termuijs/jsx/src/index.ts to support providing the app context to hooks during live editing.
  • We handled the unmount lifecycle of React's useEffect carefully to ensure that termuijsJsx.unmountAll() is called and that we don't accidentally get xterm.js stuck in the alternate screen buffer when the code hot-reloads on every keystroke.

Summary by CodeRabbit

  • New Features

    • Added an interactive in-browser TermUI playground with selectable examples, live editing, transpilation, execution, and one-click copy of code/installation commands.
    • Expanded the JSX runtime API with a way to set the current app context.
  • Chores

    • Updated the website app entry to use the new React entrypoint, added global styling, and refreshed the example library powering the playground.
    • Adjusted the website build setup with React tooling, browser-safe Node polyfills, and aliases for filesystem/process imports.

@github-actions github-actions Bot added type:feature +10 pts. New feature. area:website Docs website. area:jsx @termuijs/jsx needs-star PR author has not starred the repo. area:core @termuijs/core labels Jun 19, 2026
@github-actions

Copy link
Copy Markdown

Hi @Subhash21022 👋

Star this repo before your PR merges.

Why? GSSoC 2026 contributors who star get priority review and points credit. After you star, push any commit (or re-run this check). The needs-star label lifts automatically.

Thanks for your contribution to TermUI.

@github-actions github-actions 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.

🎉 Thanks for your first PR to TermUI, @Subhash21022.

Before your PR merges:

  1. Star the repo. Required. The star-check job blocks your merge otherwise.
  2. ✅ All checks green: build, test, typecheck.
  3. 🏷 PR title follows type: short description. Example: fix: handle empty list.
  4. 🔗 Link your closing issue in the description.

GSSoC 2026 points come from labels after merge:

  • gssoc:approved. +50 base points.
  • level:beginner / intermediate / advanced / critical. +20 / +35 / +55 / +80.
  • quality:clean / exceptional. x 1.2 / x 1.5.
  • type:*. Stackable bonus.

Your reviewer responds within 48 hours. Ping @Karanjot786 on Discord for urgent help.

🚀 Welcome to the cohort.

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

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: db38a3c4-c572-400b-be31-26bab49929e3

📥 Commits

Reviewing files that changed from the base of the PR and between 2761407 and 2165718.

📒 Files selected for processing (5)
  • website/src/components/Playground.tsx
  • website/src/empty.ts
  • website/src/main.tsx
  • website/src/style.css
  • website/vite.config.ts
💤 Files with no reviewable changes (2)
  • website/vite.config.ts
  • website/src/empty.ts
✅ Files skipped from review due to trivial changes (1)
  • website/src/style.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • website/src/main.tsx
  • website/src/components/Playground.tsx

📝 Walkthrough

Walkthrough

The PR replaces the static TermUI website with a React-based interactive playground. It adds a Playground component that uses Babel to transpile TypeScript/JSX, evaluates it in a sandboxed scope, and renders the result in an xterm terminal with mocked stdout/stdin. Vite is reconfigured with React and Node polyfill plugins, Node core modules are aliased to a stub module, and five preset TermUI examples are embedded.

Changes

Interactive TermUI Playground

Layer / File(s) Summary
Vite config, Node stubs, and dependency additions
website/vite.config.ts, website/src/empty.ts, website/package.json, package.json, .gitignore
Vite gains the React and vite-plugin-node-polyfills plugins with Buffer/process globals and resolve.alias entries redirecting all Node core module imports to empty.ts, which exports no-op sync/async/stream filesystem stubs. Website and root package.json acquire React, xterm, Prism, @termuijs/*, and polyfill dependencies. .gitignore stops excluding website/.
setCurrentApp export from jsx package
packages/jsx/src/index.ts
setCurrentApp is added as a named re-export from ./runtime.js alongside the existing getCurrentApp, expanding the public runtime API used by the playground's eval scope.
Preset example templates
website/src/examples.ts
Adds EXAMPLES mapping five keys (dashboard, form, commandPalette, logViewer, aiChat) to { name, code } objects, each code being a full embedded TermUI component implementation.
Playground component
website/src/components/Playground.tsx
Implements the split-screen playground: state tracks the selected example and editor code; one useEffect initializes xterm with FitAddon and resize handling; the main useEffect transpiles via Babel, evaluates with a sandboxed require map and TermUI JSX pragma wiring, mounts a TermUI App to a Box whose mock stdout writes to xterm and mock stdin feeds keystrokes via EventEmitter, and cleans up on teardown. The render produces the editor/terminal split with a Prism-highlighted editor and error panel.
React entrypoint, HTML wiring, and global styles
website/index.html, website/src/main.tsx, website/src/style.css, scripts/install-theme.js
main.ts (which injected raw HTML) is removed and replaced with main.tsx that calls createRoot and renders Playground in StrictMode. index.html is updated to load /src/main.tsx. style.css adds baseline body/scrollbar styles. The shebang is removed from install-theme.js.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Playground as Playground Component
  participant Babel as `@babel/standalone`
  participant Eval as Sandboxed eval()
  participant TermUI as TermUI App/Box
  participant Xterm as xterm.js Terminal

  User->>Playground: selects example or edits code
  Playground->>Babel: transpile TypeScript+JSX source
  Babel-->>Playground: transpiled JS string
  Playground->>Eval: execute with custom require() scope
  Eval-->>Playground: default export (component function)
  Playground->>TermUI: mount(component, Box) with mock stdout/stdin
  TermUI->>Xterm: write ANSI sequences via mock stdout
  User->>Xterm: key input
  Xterm->>TermUI: feed to EventEmitter stdin
  TermUI->>TermUI: setRequestRender triggers re-reconcile
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Karanjot786/TermUI#609: Also modifies packages/jsx/src/index.ts to adjust runtime app API exports, directly related to the setCurrentApp export added in this PR.
  • Karanjot786/TermUI#1457: Modifies the same website/src/main.ts HTML injection logic that this PR removes and replaces with a React entrypoint.

Suggested labels

area:examples

Suggested reviewers

  • Karanjot786

Poem

🐰 Hop into the browser, no install required!
A terminal blooms where React is wired.
Babel transpiles, xterm glows bright,
Five examples ready — pick one, take flight.
The playground is live, the widgets are free,
Type your TermUI dreams right here with me! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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
Title check ✅ Passed The PR title 'feat: Add interactive browser-based playground and component gallery' clearly describes the main feature introduced, aligning with the primary changes in the changeset.
Description check ✅ Passed The PR description is comprehensive and follows the template. It includes a detailed description of the feature, linked issue, affected packages, type of change (Feature), complete checklist, GSSoC participation, and explanatory notes for reviewers.
Linked Issues check ✅ Passed The PR comprehensively implements the MVP objectives from issue #1637: split-screen interface with code editor and live terminal preview [#1637], preset examples (dashboard, form, command palette, log viewer, ai chat) [#1637], real-time rendering with hot reload [#1637], copy code and install commands [#1637], and the required setCurrentApp export for hook context [#1637].
Out of Scope Changes check ✅ Passed All changes directly support the playground implementation: website package.json adds required dependencies, vite config enables React and Node polyfills, new Playground component and supporting files (empty.ts, examples.ts, style.css) implement the feature, and jsx export enables hook context during live editing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

3 similar comments
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 9

🤖 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/Playground.tsx`:
- Around line 186-208: The Playground component sets global JSX runtime state
with termuijsJsx.setCurrentApp(app) and termuijsJsx.setRequestRender(...) but
does not clean them up during unmount or on error paths, which can leave stale
callbacks pointing to dead app instances. Add a cleanup function to the
useEffect hook that resets both termuijsJsx.setCurrentApp and
termuijsJsx.setRequestRender to null or their initial empty states, ensuring
this cleanup is called when the effect unmounts or when the app state changes.
- Line 21: Change the Playground component in
website/src/components/Playground.tsx from a default export to a named export by
replacing export default function Playground() with export function
Playground(). Then update the corresponding import statement in
website/src/main.tsx line 3 to use a named import syntax instead of a default
import, importing Playground as a named export rather than as the default
export.
- Around line 169-175: The onData subscription in the Playground component is
not being cleaned up when the effect reruns, causing multiple handlers to
accumulate and keystrokes to be emitted repeatedly. Store the IDisposable object
returned by xtermRef.current.onData() in a variable, and then return a cleanup
function from the useEffect that calls .dispose() on this subscription. This
ensures each handler is properly cleaned up before a new one is registered when
the code dependency changes.
- Around line 127-128: The code execution in the Function constructor at lines
where `new Function` is instantiated and `fn(...Object.values(scope))` is called
executes editor input directly in the main page context, exposing DOM, storage,
and network access to the docs origin. Refactor this by creating an isolated
sandbox boundary using a sandboxed iframe or Web Worker, then establish a
message bridge to communicate between the main Playground component and the
sandbox. Move the Function creation and execution logic to run inside the
sandbox instead of the main context, passing the termuiTranspiled code and scope
data through the message bridge, and receive execution results back through the
same bridge to maintain the component's functionality while preventing access to
browser APIs and sensitive resources.
- Line 29: Replace the `useRef<any>(null)` type parameter in the termuiAppRef
declaration with the proper type `useRef<termuijsCore.App | null>` to provide
explicit typing for the ref instead of bypassing type safety with the any type.
This ensures the ref is properly typed to hold either a termuijsCore.App
instance or null value.

In `@website/src/empty.ts`:
- Line 1: Remove the default export statement from the empty.ts file. The line
containing `export default {};` violates the TypeScript guideline that requires
using named exports only and never using default exports. Delete this entire
line from the file, as the default export is not being used anywhere in the
codebase and conflicts with the established coding standards.

In `@website/src/main.tsx`:
- Around line 6-7: The code at line 6 uses a non-null assertion on
document.getElementById('app') without an explicit guard clause, which violates
strict TypeScript guidelines and creates a potential runtime crash path. Remove
the non-null assertion operator (!) and replace it with an explicit guard clause
that checks if the app element exists. If the element is not found, throw an
error or handle the missing element appropriately before passing it to the
createRoot function.

In `@website/src/style.css`:
- Line 4: The font-family property in the style.css file has unnecessary quotes
around the Inter font name, which violates the Stylelint font-family-name-quotes
rule. Remove the single quotes surrounding Inter in the font-family declaration
so it reads Inter instead of 'Inter'. Since the font name contains no
whitespace, digits, or special characters, the quotes are not required per the
always-where-recommended Stylelint rule.

In `@website/vite.config.ts`:
- Around line 25-26: Remove both the 'path' and 'node:path' alias entries from
the alias configuration in vite.config.ts. These aliases redirect to an empty
stub file which contradicts the nodePolyfills plugin configuration that is
explicitly enabled to provide proper path module support. Removing these aliases
will allow nodePolyfills to provide a working implementation of the path module
and prevent potential bugs if future code attempts to use path module APIs like
join, resolve, dirname, or basename.
🪄 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: d982729f-8afd-4910-a918-2e95a4b2bf98

📥 Commits

Reviewing files that changed from the base of the PR and between 4b874c0 and 2761407.

⛔ Files ignored due to path filters (2)
  • bun.lock is excluded by !**/*.lock
  • packages/core/src/terminal/__snapshots__/snapshot.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (13)
  • .gitignore
  • package.json
  • packages/jsx/src/index.ts
  • scripts/install-theme.js
  • website/index.html
  • website/package.json
  • website/src/components/Playground.tsx
  • website/src/empty.ts
  • website/src/examples.ts
  • website/src/main.ts
  • website/src/main.tsx
  • website/src/style.css
  • website/vite.config.ts
💤 Files with no reviewable changes (2)
  • website/src/main.ts
  • scripts/install-theme.js

Comment thread website/src/components/Playground.tsx Outdated
Comment thread website/src/components/Playground.tsx Outdated
const terminalContainerRef = useRef<HTMLDivElement>(null);
const xtermRef = useRef<XTerm | null>(null);
const fitAddonRef = useRef<FitAddon | null>(null);
const termuiAppRef = useRef<any>(null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and get its size
wc -l website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 104


🏁 Script executed:

# View the specific lines mentioned in the review (29, 131, 179-180, 194, 212)
sed -n '25,35p; 127,135p; 175,185p; 190,200p; 208,216p' website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 1602


🏁 Script executed:

# Check the imports at the top of the file to understand available types
head -30 website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 1265


🏁 Script executed:

# Get full context around each flagged line with line numbers
sed -n '125,135p' website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 411


🏁 Script executed:

# Check lines around 179-180
sed -n '175,185p' website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 301


🏁 Script executed:

# Check lines around 194 and 212
sed -n '190,215p' website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 854


🏁 Script executed:

# Search for all occurrences of 'any' in the file to see if review caught them all
rg '\bany\b' website/src/components/Playground.tsx -n

Repository: Karanjot786/TermUI

Length of output: 348


🏁 Script executed:

# Check the beginning of the function to see module/exports setup
sed -n '65,145p' website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 2510


🏁 Script executed:

# Find where mockStdout and mockStdin are defined
rg 'mockStdout|mockStdin' website/src/components/Playground.tsx -B2 -A2

Repository: Karanjot786/TermUI

Length of output: 797


🏁 Script executed:

# Check the entire relevant section to see variable declarations
sed -n '100,200p' website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 3207


Remove untyped any and type assertions in strict TS paths.

useRef<any>, as any casts, and catch (err: any) bypass type safety and violate strict typing rules. Each occurrence lacks an inline comment explaining why:

  • Line 29: useRef<any> should be useRef<termuijsCore.App | null>
  • Line 131: module.exports as any — first type exports and module properly instead
  • Lines 179–180: mockStdout as any and mockStdin as any need proper type annotations
  • Line 194: globalThis as any should use a specific type assertion
  • Line 212: catch (err: any) should be catch (err: unknown) with type narrowing
Suggested fixes
- const termuiAppRef = useRef<any>(null);
+ const termuiAppRef = useRef<termuijsCore.App | null>(null);

- const exports = {};
- const module = { exports };
+ const exports: Record<string, unknown> = {};
+ const module: { exports: Record<string, unknown> } = { exports };

- const AppComponent = (module.exports as any).default;
+ const AppComponent = module.exports.default;

- stdout: mockStdout as any,
- stdin: mockStdin as any,
+ stdout: mockStdout,
+ stdin: mockStdin,

- const instances = (globalThis as any).__termuijs_instances;
+ const instances = (globalThis as { __termuijs_instances?: Map<unknown, unknown> }).__termuijs_instances;

- } catch (err: any) {
-   console.error(err);
-   setError(err.message || String(err));
+ } catch (err: unknown) {
+   console.error(err);
+   setError(err instanceof Error ? err.message : String(err));
🤖 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/Playground.tsx` at line 29, Replace the
`useRef<any>(null)` type parameter in the termuiAppRef declaration with the
proper type `useRef<termuijsCore.App | null>` to provide explicit typing for the
ref instead of bypassing type safety with the any type. This ensures the ref is
properly typed to hold either a termuijsCore.App instance or null value.

Source: Coding guidelines

Comment on lines +127 to +128
const fn = new Function(...Object.keys(scope), termuiTranspiled);
fn(...Object.values(scope));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n website/src/components/Playground.tsx | head -150 | tail -50

Repository: Karanjot786/TermUI

Length of output: 2028


🏁 Script executed:

wc -l website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 104


🏁 Script executed:

cat -n website/src/components/Playground.tsx | head -130 | tail -40

Repository: Karanjot786/TermUI

Length of output: 1590


🏁 Script executed:

rg -n "customRequire" website/src/components/Playground.tsx -B 5 -A 2

Repository: Karanjot786/TermUI

Length of output: 521


🏁 Script executed:

rg -n "code" website/src/components/Playground.tsx | head -20

Repository: Karanjot786/TermUI

Length of output: 496


🏁 Script executed:

cat -n website/src/components/Playground.tsx | head -90

Repository: Karanjot786/TermUI

Length of output: 3486


🏁 Script executed:

rg -n "interface\|type.*Props\|export.*Playground" website/src/components/Playground.tsx

Repository: Karanjot786/TermUI

Length of output: 44


🏁 Script executed:

cat -n website/src/examples.ts 2>/dev/null || cat -n website/src/examples.tsx 2>/dev/null || find website/src -name "*example*" -type f

Repository: Karanjot786/TermUI

Length of output: 7562


🏁 Script executed:

cat -n website/src/components/Playground.tsx | sed -n '240,260p'

Repository: Karanjot786/TermUI

Length of output: 1331


Isolate evaluated code from the website origin.

new Function executes editor input in the main page context, giving evaluated snippets direct access to DOM, storage, and network on the docs origin. While the whitelisted customRequire limits module imports to TermUI libraries and React, it does not prevent access to browser APIs. Use an isolated sandbox boundary (e.g., sandboxed iframe/worker + message bridge) to properly contain executed code.

🧰 Tools
🪛 OpenGrep (1.22.0)

[ERROR] 127-127: new Function() with dynamic input can execute arbitrary code. Avoid dynamic code evaluation entirely, or use a safe alternative.

(coderabbit.code-injection.new-function-js)

🤖 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/Playground.tsx` around lines 127 - 128, The code
execution in the Function constructor at lines where `new Function` is
instantiated and `fn(...Object.values(scope))` is called executes editor input
directly in the main page context, exposing DOM, storage, and network access to
the docs origin. Refactor this by creating an isolated sandbox boundary using a
sandboxed iframe or Web Worker, then establish a message bridge to communicate
between the main Playground component and the sandbox. Move the Function
creation and execution logic to run inside the sandbox instead of the main
context, passing the termuiTranspiled code and scope data through the message
bridge, and receive execution results back through the same bridge to maintain
the component's functionality while preventing access to browser APIs and
sensitive resources.

Source: Linters/SAST tools

Comment thread website/src/components/Playground.tsx
Comment thread website/src/components/Playground.tsx
Comment thread website/src/empty.ts Outdated
Comment thread website/src/main.tsx Outdated
Comment thread website/src/style.css Outdated
Comment thread website/vite.config.ts Outdated
@github-actions github-actions Bot removed the needs-star PR author has not starred the repo. label Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core @termuijs/core area:jsx @termuijs/jsx area:website Docs website. type:feature +10 pts. New feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] interactive playground + component gallery.

1 participant