Commit graph

13 commits

Author SHA1 Message Date
ziyan2006
071db7ca1b
[codex] Stabilize HTML deck navigation state (#3142)
* fix: stabilize html deck navigation state

* fix: avoid misclassifying transform decks as scroll decks

* fix: detect default root-scroller decks

---------

Co-authored-by: Nongzi <3051966228@qq.com>
2026-05-29 07:41:10 +00:00
chaoxiaoche
831208b823
Refine Studio preview interactions (#3000)
* Refine studio preview interactions

* Fix deck toolbar navigation for transform tracks

* Fix manual edit preview close

* Fix Simple Deck toolbar scrolling

* Fix preview screenshot capture

* Fix deck preview progress sync

* Refine edit target selection for grouped elements (#3068)

* Prefer child edit targets over grouped parents

* Keep edit inspector header and footer fixed

* Shorten floating edit inspector

* Show readable edit target names

* Allow dragging the floating edit inspector

* Add explicit edit inspector actions

* Show preview comment count in toolbar

* Separate annotation and comment toolbar groups

* Remove annotation toolbar divider

* Close edit inspector from footer actions

* Hide edit inspector until target hover

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>

* Fix manual edit iframe regression test

* Fix Studio interaction review feedback

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

* Fix saved comment link classification

Generated-By: looper 0.9.2 (runner=fixer, agent=codex)

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-05-28 12:52:37 +00:00
zqyaym
b22c7713db
fix(web): prevent preview iframe from stealing focus on load (#2792)
* Fix preview iframe focus stealing

* Fix preview focus guard for URL-loaded HTML previews

Focus guard was only injected via the srcdoc path, but the default
URL-load path bypasses buildSrcdoc entirely. Add htmlNeedsFocusGuard
detection so focus-stealing HTML is routed through srcdoc where the
guard can suppress window.focus/element.focus calls.

* Widen focus guard detector to cover all .focus() call patterns

The previous regex only matched window.focus() and document.focus(),
missing document.body.focus(), querySelector().focus(), and other
chained focus calls. Broaden to match any `.focus(` so the default
URL-loaded preview path is forced to srcDoc for all focus-stealing HTML.

* Conservatively force srcDoc for HTML with external script references

When the HTML contains <script src=...>, we cannot inspect the linked
file for focus-stealing calls. Force the srcDoc path so the focus guard
intercepts any .focus() calls from external scripts.

---------

Co-authored-by: JoeyZhu <15500388+acthenknow@user.noreply.gitee.com>
2026-05-24 14:37:08 +00:00
Neha Prasad
716f06cb73
fix(web): allow Comment/Inspect picker to select iframe-backed components (#2254) 2026-05-19 19:26:11 +08:00
Yuhao Chen
2f553941d3
fix(runtime): auto-annotate imported HTML elements for Tweaks selection (#892) (#1169)
* fix(runtime): auto-annotate imported HTML elements for Tweaks selection (#892)

* fix(runtime): always annotate missing od-ids and broaden selector (#892)

- Remove the conditional gate so annotateMissingOdIds runs for every
  srcdoc, not just comment/inspect bridges. This fixes the persistence
  regression where saved Inspect tweaks reference synthesized data-od-id
  selectors that vanish when the bridge is rebuilt without annotations.

- Expand the selector to cover div-based imported HTML (div[class],
  div[id]), headings, buttons, and links so Picker/Pods work on
  common anonymous wrapper markup.

Addresses review feedback from lefarcen and mrcfps.

* fix(runtime): narrow div selector, skip iframe/object/embed, add tests (#892)

- Replace broad div[class] with direct-child combinators only under
  semantic containers, body, and [id] elements to avoid layout noise
- Add iframe, object, embed to the skip list alongside script/style
- Add tests for: direct-child divs, nested div skip, always-on behavior,
  skip list with id attributes, div children of [id] elements
- Format selector as array join and skip tags as Set for readability

* fix(runtime): let annotateManualEditSourcePaths coexist with data-od-id (#892)

annotateMissingOdIds now runs unconditionally, so elements like main/h1
get data-od-id before annotateManualEditSourcePaths runs. The old skip
condition (has data-od-id) incorrectly prevented source-path marking on
those elements. Change the guard to skip only when the element already
has data-od-source-path, allowing both attributes to coexist.
2026-05-16 16:17:36 +08:00
leessju
4e19c3f4f3
Prevent imported Claude canvases from zooming on scroll (#1726)
* Preserve HTML preview state across mode toggles

HTML previews could rebuild their iframe when switching into Edit or Comment, which reset scroll/canvas state and caused visible churn for multi-file artifacts. The viewer now keeps URL-loaded previews mounted when the artifact owns the mode bridge, relays file-refreshes through frame navigation, and restores preview scroll/viewport state across bridge mode changes.

Constraint: Generic srcdoc-only bridges are still required for unbridged artifacts, inspect mode, palette tweaks, decks, draw overlays, and forceInline.

Rejected: Keep all Edit/Comment previews on srcdoc | causes unnecessary iframe replacement for bridge-capable URL-loaded artifacts.

Confidence: high

Scope-risk: moderate

Directive: Do not enable URL-load for bridge-dependent modes unless the artifact has an owned postMessage bridge.

Tested: pnpm guard

Tested: pnpm --filter @open-design/web typecheck

Tested: pnpm --filter @open-design/web test

Tested: Playwright verified Edit and Comment toggles preserve iframe src and DOM node while receiving comment targets.

* Prevent preview wheel gestures from escaping into zoom

Trackpad pinch-like wheel events arrive with ctrl/meta modifiers on some platforms, which can make a normal vertical scroll feel like the preview zoomed. The preview now consumes those modified wheel events inside the host preview shell and in injected srcdoc previews, then maps the delta back to scroll where a scroll target exists.

Constraint: URL-loaded sandbox iframes cannot always be inspected by the host, so srcdoc previews need their own in-frame guard.

Rejected: Add allow-same-origin to preview iframes | weakens the sandbox boundary for generated artifacts.

Confidence: medium

Scope-risk: narrow

Directive: Do not broaden iframe sandbox permissions to fix gesture handling without a security review.

Tested: pnpm guard

Tested: pnpm --filter @open-design/web typecheck

Tested: pnpm --filter @open-design/web exec vitest run tests/components/FileViewer.test.tsx tests/runtime/srcdoc.test.ts

Tested: playwright-cli verified ctrl-wheel in preview keeps app zoom at 100% and prevents default in the iframe context

* Revert "Prevent preview wheel gestures from escaping into zoom"

This reverts commit 976407ab4c.

* Prevent imported Claude canvases from zooming on scroll

Claude Design exports can classify ordinary macOS two-finger vertical wheel events as mouse-wheel zoom clicks inside design-canvas.jsx. Normalize that imported canvas code so plain wheel input pans, while Cmd+wheel remains the explicit zoom gesture.

Constraint: The offending canvas code lives inside imported user artifacts rather than a tracked runtime component, so the fix belongs in the Claude Design zip import normalization path.\nRejected: Host-side wheel interception | wheel events inside the sandboxed iframe are handled by the artifact before the host can reliably classify them.\nRejected: Disable all wheel zoom | users still need Cmd+wheel as an explicit zoom control.\nConfidence: high\nScope-risk: narrow\nDirective: Keep plain wheel as pan-only for imported design-canvas.jsx unless a future bridge provides an explicit wheel-mode handshake.\nTested: pnpm --filter @open-design/daemon exec vitest run tests/claude-design-import.test.ts\nTested: pnpm --filter @open-design/daemon typecheck\nTested: pnpm guard

---------

Co-authored-by: nicejames <nicejames@gmail.com>
Co-authored-by: lefarcen <935902669@qq.com>
2026-05-15 16:37:57 +08:00
Eli
49ea2499ac
[codex] Add draw annotation workflow (#1435)
* feat(web): tweaks palette popover with HSL hue-shift recoloring

Adds a Tweaks color-palette popover to the HTML preview toolbar.
Selecting a palette re-skins the iframe in place via a srcDoc-side
bridge that walks the DOM and shifts every chromatic paint to the
target hue while preserving each color's saturation and lightness —
pale tints stay pale, bold CTAs stay bold, just in the new color
family. Mono-noir desaturates instead of shifting.

- runtime/srcdoc: new injectPaletteBridge + paletteBridge / initialPalette options
- file-viewer-render-mode: paletteActive flips URL-load back to srcDoc so the bridge can be injected
- FileViewer: state, popover, postMessage wiring, srcDoc + useUrlLoadPreview integration
- PaletteTweaks: popover UI with Original + Coral / Electric / Acid forest / Risograph / Mono noir
- PreviewDrawOverlay: stub pass-through until the draw branch lands

* feat(web): hide finalize-design toolbar from project header

* test(e2e): skip project actions toolbar flow after toolbar removal

* Add draw annotation workflow

* Restore project actions toolbar
2026-05-12 21:54:59 +08:00
Eli
77f69257a7
feat(web): in-context comment thread for the artifact preview (#1276)
* feat(web): free-pin fallback in comment mode for unannotated artifacts

When the artifact has no data-od-id annotations, clicking in Comment
mode now posts a synthetic position-based target so the host opens a
popover at the click location. Daemon upsert validation requires a
non-empty selector/label, so the pin uses [data-od-pin=ID] and label
'pin'. Coordinates are document-space (viewport + scrollY) so pins
stay anchored after scroll/reload. Clicks on interactive elements
(a/button/input/textarea/select/label/contenteditable) keep their
native behavior and are not pinned.

* feat(web): tighten comment popover layout for free-pin and element targets

The popover header used to dump the raw elementId verbatim — fine for
data-od-id targets like 'hero-cta' but jarring for free-pins where
elementId is a synthetic 'pin-...' string. Branch on the prefix and
show 'Pin · at X, Y' for free-pins; keep the label + selection kind
for real element / pod targets. Replace the text 'Close' button with
an icon-only close affordance to match the popover-as-card visual.

Action row is now two right-aligned buttons (Comment + Send to
Claude) for element targets and (Add note + Send to Claude) for pod
targets, eliminating the three-button row that wrapped onto two
lines at narrow widths. The 'Remove' affordance for existing
comments stays left-aligned.

* feat(web): drop comments tab from chat sidebar

The chat sidebar's 'Comments' tab listed saved/attached preview
comments but duplicates the per-element popover already shown in the
artifact viewer. Hide the tab and its content while the right-side
comment thread panel takes over the same surface in-context. The
CommentsPanel / CommentSection components stay defined as dead code
for the moment so callers and translation keys remain valid; a later
pass can delete them.

* feat(web): right-side comment thread panel in board mode

Render a 320px CommentSidePanel anchored to the right of the
artifact preview whenever board (comment) mode is on. The panel
lists every saved preview comment for the current file with an
avatar initial, the element label (or 'Pin' for free-pin synthetic
ids), an Xd/Xh/Xm-ago timestamp, the note body, a Reply link, and
a checkbox.

Reply focuses the comment's element via liveSnapshotForComment so
the popover opens at the right anchor. Selecting one or more
comments via the checkboxes surfaces a 'N selected · Clear · Send
to Claude' action bar above the list; Send to Claude reuses the
existing onSendBoardCommentAttachments pipeline via
commentsToAttachments. The panel takes the place of the chat
sidebar's removed Comments tab so the thread lives next to the
artifact instead of behind a tab switch.

* feat(web): styles for right-side comment thread panel

Floating 320px panel anchored to the right edge of the artifact
preview with a scrollable comment list and a coral selection bar
that appears when one or more comments are checked. Selected items
get a coral tint; the reply / check / send-to-claude controls
match the popover's coral primary tone.

* feat(web): toast confirmation on comment save, close popover

After savePersistentComment succeeds, close the popover via
clearBoardComposer and surface a transient 'Comment saved' (or
'Pin saved' for free-pin targets) toast for 2.2s. Replaces the
previous behavior where the popover stayed open with an empty
draft after save, which left users uncertain whether the save
landed and forced an extra click to dismiss.

* feat(web): position the comment-save toast at the top of the preview

* feat(web): allow editing saved comment notes via the side panel

Rename the per-item 'Reply' affordance to 'Edit' (no thread model
exists yet, so reply was misleading) and pre-fill the popover with
the existing note when clicked. The save path goes through
onSavePreviewComment which the daemon implements as an upsert keyed
on (project, conversation, filePath, elementId), so the edit
overwrites the existing row's note without spawning a duplicate.

Also fall back to a snapshot synthesized from the saved comment's
own fields when the corresponding live target is no longer in the
iframe DOM (e.g. free-pin parents that were re-rendered), so the
edit path still works after artifact reloads.

* feat(web): hide already-sent comments from the side panel

After Send to Claude, the daemon flips the comment status from
'open' to 'applying' (and then 'needs_review' / 'resolved' /
'failed' depending on the run). Filter the side panel to status
=== 'open' so sent comments visibly leave the list — the user
gets clear feedback that the send landed and the panel stays
focused on actionable, un-sent items.

* feat(web): drop single-tab bar and conversation count badge

After the Comments tab was removed the chat header still rendered
a one-tab 'tablist' just for the Chat tab, which read as visual
noise without a sibling to switch between. Drop the tabs wrapper
entirely; the chat content stays mounted and the header now hosts
only the conversation-history affordance.

Also drop the numeric badge that overlaid the conversation history
button: counting open conversations next to a generic history icon
was easy to mistake for an unread / notification count. The dropdown
itself remains the canonical place to see and switch between past
conversations.

* feat(web): right-align chat header actions after tab bar removal

With the tabs wrapper gone, chat-header-actions sat flush left
because nothing was pushing it across the header. Add margin-left:
auto so the history / new-conversation / collapse buttons land at
the right edge, matching the design files / index.html tab row's
own right-aligned controls.

* feat(web): rename board-mode toggle to Comment with comment icon

The artifact preview toolbar's board-mode entry was labeled 'Tweaks'
with the tweaks icon, which collided with the palette Tweaks button
next to it and hid the comment capability behind a generic label.
Rename to 'Comment' with the comment icon and switch to the
viewer-action class so the button matches the surrounding toolbar
items (Edit/Draw) and the coral active state lands on the right
surface.

* fix(web): pass designTemplates to ProjectView in api-empty-response test

The test props for ProjectView were missing the designTemplates
prop that was added to Props in #955 (generic skills split). CI's
strict typecheck (tsc -b --noEmit) caught it; local runs that hit
project references differently did not. Pass an empty SkillSummary
array — matches the empty skills fixture for the same reason.
2026-05-12 15:05:08 +08:00
shangxinyu1
10802bb0b0
test: expand nightly UI and desktop regression coverage (#1256)
* e2e(ui): cover examples preview flows

* e2e(ui): cover Codex local CLI fallback UX

* test: expand desktop and connector regression coverage

* e2e(ui): cover workspace restoration flows

* e2e(ui): cover retry recovery workspace flow

* test: cover artifact and connector recovery flows

* e2e(ui): cover Continue in CLI stale provenance flow

* e2e(ui): cover BYOK model fetch caching

* test: expand Orbit and desktop connector coverage

* e2e(ui): cover workspace quick switcher recovery flows

* e2e(ui): cover connector pending authorization recovery

* e2e(ui): cover workspace and conversation restoration routes

* e2e(ui): cover conversation draft and attachment restoration

* e2e(ui): cover conversation history selection recovery

* e2e(ui): cover workspace surface conversation selection

* test: cover artifact presentation and orbit link behavior

* test: cover artifact external link restoration

* e2e(ui): cover root-route deep-link restoration

* e2e(specs): cover Orbit open-artifact desktop click

* e2e(specs): cover desktop artifact open link

* test: fix Orbit settings fixture type drift

* test: split Playwright critical and extended suites

* test: fix ProjectView design template fixtures

* ci: split workspace test stages

* guard: allow split Playwright suite scripts

* test: shrink Playwright critical suite

* test: restore omitted Playwright suites
2026-05-11 19:23:13 +08:00
Tom Huang
38eb78a382
feat(web): add Inspect mode for live per-element style tuning 2026-05-07 16:40:30 +08:00
Caprika
8eb9b1b506
Implement manual edit mode (#620) 2026-05-06 16:13:52 +08:00
Martin Atrin
79fcaef129
Add Tweaks mode for HTML previews with picker, pod selection, and batched chat attachments (#513)
* Add tweaks mode for HTML preview comments

* Fix tweaks geometry and restore critique migration

* Harden tweaks mode reload sync

* Guard tweaks batch sends during active runs

---------

Co-authored-by: puma <puma@pumas-MacBook-Air.local>
2026-05-05 21:09:20 +08:00
PerishFire
bbdd4e84b5
chore: enforce test directory conventions (#496)
* chore: enforce test directory conventions

Move package, app, and tool tests out of src and add guard enforcement so source directories stay source-only.

* ci: use guard and package-scoped tests

Run the new repository guard in CI and keep test execution aligned with package-scoped commands after removing root aliases.

* ci: align stable release guard check

Use the new repository guard in stable release verification after replacing the residual-JS-only script.

* chore: tighten test layout enforcement

Enforce sibling tests directories, typecheck moved test suites with dedicated configs, and refresh remaining guidance that pointed at src-based tests.

* chore: clarify no-emit test tsconfigs

Explicitly disable declaration-only emit in test tsconfigs so review tooling sees they are no-emit typecheck configs.
2026-05-05 15:34:22 +08:00
Renamed from apps/web/src/runtime/srcdoc.test.ts (Browse further)