Skip to content

WireframeEditor and WireframePlayground - #3

Merged
individual11 merged 4 commits into
mainfrom
editor-playground
Oct 21, 2026
Merged

individual11 merged 4 commits into
mainfrom
editor-playground

Conversation

@individual11

@individual11 individual11 commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Part 2 of v0.2's plan, React side. Released as 0.3.0 after this.

Imported from @tsquare-js/react/editor (review fix)

The editor and playground are a second entry point, so the main one never loads tsquare/editor (CodeMirror). Measured with esbuild: an app importing only Wireframe went from 617 KB gzipped (CodeMirror included) to 489 KB; the playground is 617 KB. test/package.test.ts checks what each entry reaches, the shared chunk and "use client".

Components

  • <WireframeEditor> (tsquare 0.12's tsquare/editor): highlighting, autocomplete (languageData()), problems underlined ~300 ms after typing stops (with the message on hover), Enter keeps indentation, a pasted model reply is trimmed to its code block. Props: value/defaultValue, onChange, onProblems, autocomplete, lineNumbers, ariaLabel, className, style. A ref (WireframeEditorHandle) gets getText, setText, focus, goToLine. A new value replaces the text unless it's the editor's own change coming back.
  • <WireframePlayground>: editor + viewer on one text. layout "auto" (row ≥ 900px wide, column below, via a container query), "row" or "column". While typing (until 400 ms without a change) the board redraws on the 200 ms streaming throttle and problems wait; then the editor underlines them and the board gets "N problems · showing the last valid board" (dimmed). Also showProblems, chips, zoomControls, autocomplete, lineNumbers, onProblems, and the same ref.
  • Viewer: calls destroy() on unmount (part 1's known leak).

Narrow editors (added after review of a screenshot)

In a 760px playground the editor was 303px wide while the example's lines needed 746px: most of each line was hidden behind sideways scrolling.

  • layout="auto" stacks below 900px (was 640px), and side by side the editor and board share the width half and half (was 2:3).
  • Long lines wrap by default (lineWrapping, tsquare 0.12.1's new editor option), each continuation 4 spaces past its line's indentation; lineWrapping={false} scrolls sideways instead.
  • Checked in Chrome: the 760px playground now stacks with a 758px editor and nothing hidden; forced side by side, the 379px editor wraps every line and doesn't scroll sideways.

Styles

The editor's colors come from the --tsquare-* theme (its highlighting keeps the editor's light/dark defaults unless --tsquare-syntax-* is set); .tsquare-editor 20rem and .tsquare-playground 36rem by default (--tsquare-editor-height, --tsquare-playground-height). All rules stay in :where().

Docs

New docs/editor.md and docs/playground.md (props tables, typing behavior, ref methods, saving the text, bundle size); the overview's "which component" table and styling.md cover them. The site picks the pages up from the package once it pins 0.3.0 (they're linked from the overview's table, so they join the nav and previous/next in order).

Verification

  • npm test: 20 (was 15): editor (text, aria, ref.setText → onChange, unmount removes it; problems underlined only after a pause, onProblems with the list and [] on fix; controlled value; options), playground (board and 4 chips; nothing while typing, then note + underline + dim + onProblems; layout, showProblems={false} keeps underlines), viewer destroy on unmount; docs (examples typecheck, every prop of the two new components documented). Three consecutive runs green.
  • In Chrome (a demo with the playground and an editor): side by side at 1280px; typing buton shows nothing at once, then the underline, the note, the dimmed board and onProblems; autocomplete offers button; hovering the underline shows the message; at 375px it stacks; data-theme="dark" turns the editor and viewer dark; no console errors.
  • Test setup only: jsdom needs its own AbortController and Window globals (the viewer's listeners, CodeMirror's measuring); browsers and Jest/Vitest's jsdom environments provide them.

🤖 Generated with Claude Code

- <WireframeEditor>: tsquare/editor in React. value/defaultValue, onChange,
  onProblems (after a 300 ms pause), autocomplete, lineNumbers, ariaLabel; a
  ref gets getText, setText, focus, goToLine. EditorCore is the shared part.
- <WireframePlayground>: the editor and the viewer on one text, side by side
  (stacked under 640px via a container query, or layout="row"/"column").
  While typing (until 400 ms without a change) the board redraws on the
  streaming throttle and problems wait; then they're underlined and counted
  in a note on the board.
- The viewer calls tsquare's destroy() on unmount.
- styles.css: the editor's colors from the --tsquare-* theme, the playground
  layout, --tsquare-editor-height and --tsquare-playground-height.
- Docs: editor.md, playground.md; the overview table and styling.md.
- Tests (20): editor text/ref/onChange, problems underlined after a pause and
  onProblems, controlled value and options, playground (board, problems held
  while typing then underlined and noted, layout, showProblems), viewer
  destroy on unmount; docs examples typecheck and props documented.
- tsquare ^0.12.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 760px wide (a typical docs or app column) the editor got 303px while the
example's lines needed 746px; most of each line was hidden behind sideways
scrolling. Side by side now starts at 900px, and the two panes share the
space evenly. Wrapping long lines (tsquare 0.12.1) comes next.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI 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.

🟡 Changes recommended

Mount-time ref calls can fail silently, the persistence example can overwrite another sketch, and viewer-only bundles can retain the editor dependency.

3 open issues
What changed in this PR

Adds React editing components alongside the existing wireframe viewer, with live previews and delayed problem reporting.

Changes:

  • Adds WireframeEditor and responsive WireframePlayground.
  • Adds themed styles and viewer cleanup on unmount.
  • Updates tsquare, documentation, and component tests.
File Description
test/​react.test.tsx Tests editors, playground behavior, styles, and cleanup.
test/​docs.test.ts Checks new component prop documentation.
src/​viewer.tsx Destroys the viewer on unmount.
src/​styles.css Adds editor themes and playground layouts.
src/​playground.tsx Combines editing and live preview.
src/​index.ts Exports new components and types.
src/​editor.tsx Wraps the editor with diagnostics and ref methods.
README.md Introduces editing components.
package.json Updates tsquare to 0.12.
package-lock.json Locks the updated dependency.
docs/​styling.md Documents editor and playground styling.
docs/​README.md Extends component selection guidance.
docs/​playground.md Documents playground usage and persistence.
docs/​editor.md Documents editor props and controls.
CHANGELOG.md Records new features and cleanup.

Review effort: Balanced

Comment thread docs/playground.md Resolved
Comment thread src/editor.tsx Resolved
Comment thread src/index.ts Resolved
individual11 and others added 2 commits October 20, 2026 12:50
lineWrapping, default true, on WireframeEditor and WireframePlayground:
long lines wrap instead of scrolling sideways, continuing 4 spaces past their
indentation. tsquare ^0.12.1. Docs and CHANGELOG; a test for the default and
for turning it off. Checked in Chrome: a 379px editor in a side-by-side
playground wraps every line and doesn't scroll sideways.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ample

- The editor and playground move to @tsquare-js/react/editor (a second
  esbuild entry with a shared chunk): the main entry never reaches
  tsquare/editor, so a Wireframe-only app bundles 489 KB gzipped instead of
  617 KB (no CodeMirror). test/package.test.ts checks what each entry
  reaches, the shared chunk and "use client" on every file.
- The editor is created in a layout effect declared before
  useImperativeHandle, so a callback ref or a parent's useLayoutEffect can
  focus it and read its text (before: no-op and ""). useEffect on the server.
  Test added (mutation-checked: it fails with the old useEffect).
- docs/playground.md: the saved-sketch example keys its stateful part by id,
  so switching sketches can't save one's text under another's id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@individual11
individual11 merged commit db08889 into main Oct 21, 2026
3 checks passed
@individual11
individual11 deleted the editor-playground branch October 21, 2026 01:14
@individual11 individual11 mentioned this pull request Oct 21, 2026
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.

2 participants