Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
add0d35
feat(studio): add manual DOM editing inspector (#466)
miguel-heygen Apr 25, 2026
664c215
fix(studio): improve dom picking and thumbnails
miguel-heygen Apr 28, 2026
767e2e2
fix(studio): copy absolute paths in agent prompts
miguel-heygen Apr 28, 2026
cb81947
fix(studio): prevent timeline track cutoff
miguel-heygen Apr 28, 2026
702cb26
fix: copy Studio agent prompts in Safari
miguel-heygen Apr 28, 2026
368f965
fix(studio): hold canvas movement from inspector
miguel-heygen Apr 28, 2026
e5525a5
feat(studio): add persistent undo redo (#537)
miguel-heygen Apr 30, 2026
c7e10c1
fix: align Studio capture with preview (#595)
miguel-heygen May 2, 2026
62f212a
feat: persist studio manual edits via manifest
vanceingalls May 1, 2026
9098255
fix(studio): stabilize manual edit manifest rendering
vanceingalls May 2, 2026
d9b3be0
fix(studio): allow master canvas layer selection
vanceingalls May 2, 2026
fa20864
fix(studio): scale master edits in source coordinates
vanceingalls May 2, 2026
79b33ac
fix(studio): reapply manual edits during playback
vanceingalls May 2, 2026
7563d26
fix(studio): keep rotation edit base stable
vanceingalls May 2, 2026
dc949f5
feat(studio): highlight hovered canvas target
vanceingalls May 2, 2026
47159e8
fix(studio): drag hovered canvas targets immediately
vanceingalls May 2, 2026
69cf85b
fix(studio): rotate manual edits around center
vanceingalls May 2, 2026
62e1db8
fix(studio): keep rotate handle aligned while dragging
vanceingalls May 2, 2026
9ba1e6e
fix(studio): allow small rotation adjustments
vanceingalls May 2, 2026
2a412fa
fix(studio): match rotate handle size to resize handle
vanceingalls May 2, 2026
6eaa117
fix(studio): connect rotate handle line to selection
vanceingalls May 2, 2026
c3c4998
feat(studio): reset selected manual edits
vanceingalls May 2, 2026
8c6af57
fix(studio): route inspector geometry through manual edits
vanceingalls May 2, 2026
7a736eb
feat: add studio group repositioning
vanceingalls May 2, 2026
83d7061
fix: preserve studio group selections
vanceingalls May 2, 2026
df94d63
fix: seed additive studio selection groups
vanceingalls May 2, 2026
8184dc7
fix: select studio groups on pointerdown
vanceingalls May 2, 2026
42f864e
fix: harden studio group overlay events
vanceingalls May 2, 2026
47dd59f
fix: address studio manual edit review feedback
vanceingalls May 2, 2026
ced335e
fix: apply nested manual edits in drilled previews
vanceingalls May 2, 2026
46df941
fix: commit drag offsets from gesture math
vanceingalls May 2, 2026
4935ac5
fix: persist manual preview edits on refresh
vanceingalls May 3, 2026
8860695
fix: harden manual edit refresh apply
vanceingalls May 4, 2026
073fb74
fix: share manual edit render runtime
vanceingalls May 4, 2026
d4876b4
chore: release v0.5.0-alpha.15
miguel-heygen May 4, 2026
99d3fc8
feat(core): add studio animation preview APIs
miguel-heygen May 8, 2026
defc64e
feat(studio): add alpha editor layer inspector
miguel-heygen May 8, 2026
69c8966
chore: release v0.6.0-alpha.1
miguel-heygen May 8, 2026
e653025
feat(studio): enable inspector panels by default
miguel-heygen May 9, 2026
62ee749
fix(studio): keep motion panel opt-in
miguel-heygen May 9, 2026
79b6948
chore: release v0.6.0-alpha.2
miguel-heygen May 9, 2026
67867ed
feat: auto-open timeline clip layers
miguel-heygen May 9, 2026
a672d82
feat: show composition loading in studio
miguel-heygen May 9, 2026
43734a6
feat: disable Studio timeline while composition loads
miguel-heygen May 9, 2026
70fc563
chore: ignore .claude directory
miguel-heygen May 9, 2026
c147077
chore: release v0.6.0-alpha.3
miguel-heygen May 9, 2026
475754c
feat(studio): simplify inspector selection ux
miguel-heygen May 9, 2026
a5434fb
fix(studio): keep notion preview playback moving
miguel-heygen May 9, 2026
25f60bf
fix(studio): handle raster inspector clicks
miguel-heygen May 9, 2026
52674df
fix(studio): stale selection, rotation control, design panel polish
miguel-heygen May 9, 2026
a886e70
fix(studio): prevent browser launch timeout from crashing dev server
miguel-heygen May 9, 2026
706c799
fix(studio): revert motion panel default to false
miguel-heygen May 9, 2026
5f661b4
fix(studio): prevent read-only property crash in manual edit wrappers
miguel-heygen May 9, 2026
6fb15b4
fix: alpha preview e2e fixes — exports, init templates, EPIPE crash
miguel-heygen May 9, 2026
70bc81f
fix(studio): thumbnail crash, feature defaults, multi-select UX, fps …
miguel-heygen May 9, 2026
d5ee383
chore: release v0.6.0-alpha.4
miguel-heygen May 9, 2026
4126191
fix(runtime): update clock duration when root timeline is late-bound
miguel-heygen May 9, 2026
f379237
fix(studio): block element selection while composition is loading
miguel-heygen May 9, 2026
06c12e7
chore: release v0.6.0-alpha.5
miguel-heygen May 9, 2026
b686584
chore: release v0.6.0-alpha.6
miguel-heygen May 10, 2026
912e981
fix(runtime): remove per-tick timeline.pause() that causes audio stutter
miguel-heygen May 10, 2026
fcf8c17
chore: release v0.6.0-alpha.7
miguel-heygen May 10, 2026
152b80f
fix(studio): restore text field handlers lost in rebase
miguel-heygen May 10, 2026
6ef33be
chore: release v0.6.0-alpha.8
miguel-heygen May 10, 2026
0f48a32
fix(runtime): comprehensive audio stutter fix
miguel-heygen May 10, 2026
8fc3dfb
fix(runtime): skip drift corrections on playing video elements
miguel-heygen May 10, 2026
3b66dc5
Merge pull request #707 from heygen-com/fix/audio-stutter-comprehensive
miguel-heygen May 10, 2026
f57b8cf
chore: release v0.6.0-alpha.9
miguel-heygen May 10, 2026
024467c
feat(studio): consolidate keyboard shortcuts into single handler
miguel-heygen May 11, 2026
ae2957d
fix(studio): sidebar tab overflow + hot-reload double-refresh
miguel-heygen May 11, 2026
d868deb
fix(studio): delete key removes preview-selected elements
miguel-heygen May 11, 2026
b85d572
fix(studio): remove unused deleteInFlightRef from Timeline
miguel-heygen May 11, 2026
a85a92e
fix(studio): forward all keyboard shortcuts to preview iframe
miguel-heygen May 11, 2026
48682f5
fix(core): search inside <template> content when removing elements
miguel-heygen May 11, 2026
9a1f1be
fix(studio): suppress loading overlay on hot-reload
miguel-heygen May 11, 2026
2127a48
fix(studio): reorder design panel, fix stroke height, rename Blending
miguel-heygen May 11, 2026
b7aafbf
fix(studio): prevent panel scroll when wheel-adjusting metric inputs
miguel-heygen May 11, 2026
0d6ac5d
Merge pull request #710 from heygen-com/feat/consolidate-keyboard-sho…
miguel-heygen May 11, 2026
3174848
chore: release v0.6.0-alpha.10
miguel-heygen May 11, 2026
ed56a81
chore: merge main into next
miguel-heygen May 11, 2026
0e0f1dd
chore: release v0.6.0-alpha.11
miguel-heygen May 11, 2026
005e196
fix(studio): clean next alpha inspector artifacts
miguel-heygen May 11, 2026
065be89
Merge pull request #721 from heygen-com/fix/next-alpha-cleanup
miguel-heygen May 11, 2026
fd5fdfd
chore: release v0.6.0-alpha.12
miguel-heygen May 11, 2026
5adb477
fix(studio,player,core): eliminate double audio and manifest polling …
vanceingalls May 12, 2026
b5b8e4d
fix(studio): inspector visibility, undo/redo blinking, and preview ca…
miguel-heygen May 12, 2026
f0f1612
fix(studio): remove timeline inspector buttons, enable manual dragging
miguel-heygen May 12, 2026
7280b94
fix(studio): improve font picker and text property controls (#736)
vanceingalls May 12, 2026
6ea1b5b
Merge pull request #724 from heygen-com/fix/studio-inspector-bugs-and…
miguel-heygen May 12, 2026
1c518db
chore: release v0.6.0-alpha.13
miguel-heygen May 12, 2026
7852c71
fix(studio): add rotation field, inline element drag, fix manifest lo…
vanceingalls May 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ tmp/
packages/core/src/generated/
packages/producer/src/services/fontData.generated.ts

# Test artifacts
# Local proof / test artifacts
qa-artifacts/
my-video/
examples/
packages/studio/data/
Expand Down Expand Up @@ -99,3 +100,5 @@ ab-test/
compositions/
video-6-2-patched/
claude-design-hyperframes-video/
.claude/worktrees/
.claude/
8 changes: 8 additions & 0 deletions docs/contributing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ bun run build # Build all packages
bun run --filter '*' typecheck # Type-check all packages
```

### Studio Editing Work

If you are changing Studio's visual editing surface, read
[Studio Manual DOM Editing](/contributing/studio-manual-dom-editing) before
editing code. The inspector intentionally exposes only interactions it can
persist safely back to HTML, so changes should preserve the capability gates,
source patching model, and documented limitations.

### Running Tests

<CodeGroup>
Expand Down
315 changes: 315 additions & 0 deletions docs/contributing/studio-manual-dom-editing.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,315 @@
---
title: Studio Manual DOM Editing
description: What the Studio manual DOM editing inspector ships today, including capabilities, UX, and constraints.
---

This page documents the current manual DOM editing surface in HyperFrames Studio. It reflects the implementation that ships in the Studio inspector today, not the earlier design draft that explored third-party transform engines.

## What Shipped

Studio now supports a direct DOM editing workflow inside the preview:

- select supported elements directly in the preview
- see an editor-owned overlay around the current selection
- move and resize supported elements on canvas when geometry is safe
- detach eligible layout-controlled layers with an explicit `Make movable` action
- edit style properties from the right-side `Design` inspector
- edit text layers for safe text-bearing selections, including empty text values
- add and remove child text layers for multi-text selections
- edit solid fills, gradients, project-asset image fills, external image fills, opacity, radius, flex metadata, typography, and blend mode
- drill into nested compositions from master view instead of pretending every inner node is editable in place
- generate an element-scoped `Ask agent` prompt bundle from the right inspector

The important rule is conservative: Studio only exposes interactions it can round-trip back to authored HTML with deterministic behavior.

## Current User Experience

### Preview selection

- Single click selects a patchable element in the preview.
- The selection overlay is rendered in Studio chrome, not injected into authored content.
- The overlay is cleared when:
- the `Inspector` panel is closed
- the user clicks an empty area in the preview
- the underlying element disappears after a source refresh

### Overlay behavior

The overlay provides:

- selection bounds
- drag behavior for supported elements
- a resize handle when width and height are safely patchable
- blocked-drag feedback for unsupported movement

The overlay intentionally does not include a floating action toolbar. `Ask agent` lives in the right inspector header, and style controls live in the `Design` panel.

The current implementation uses Studio-owned pointer handling in `DomEditOverlay.tsx`. It does **not** use `Moveable`.

### Inspector behavior

The `Design` panel currently includes:

- `Layout`
- X / Y / W / H fields
- wheel and arrow-key numeric scrubbing
- `Make movable` for block-ish layout-controlled layers that can be detached safely
- `Flex`
- direction, justify, align, gap, clip content
- `Radius`
- slider + live readout
- `Blending`
- opacity slider + live readout
- blend mode
- `Fill`
- solid color
- multi-stop gradient editing
- project asset image fills
- inline image upload into the project assets list
- external image URL fill
- text color
- `Color picker`
- viewport-clamped floating picker
- saturation / brightness crosshair
- hue and alpha sliders
- hex input
- `Text`
- direct text layer editing when the selection is safe to patch
- add / remove text layers for child text selections
- font size, weight, and family controls
- `Selection colors`
- a summary of detected colors for the current selection

The inspector is intentionally split from `Renders` with a `Design / Renders` tab control in the right panel. Switching to `Renders` does not mean the header-level `Inspector` panel is closed.

## What Counts As Editable

Studio builds a `DomEditSelection` and `DomEditCapabilities` object for each selection.

### Selection requirements

A node is only useful to Studio if it can be identified with a stable patch target, for example:

- `id`
- stable selector
- selector index scoped to the correct source file
- composition host mapping when master view is involved

### Move support

Move is allowed only when the selected element:

- has a stable patch target
- is `absolute` or `fixed`
- has `left` and `top` values that resolve to pixel values
- is not transform-driven (`transform: none`)

### Resize support

Resize is allowed only when move is already allowed and Studio can also safely patch pixel `width` and/or `height`.

### Detach from layout support

Some block-ish layers are selectable and style-editable, but cannot be moved directly because flex, grid, or normal document flow owns their position.

For those layers, Studio can expose `Make movable` instead of silently converting on drag. The action measures the current visual rect relative to the composition root and writes conservative inline geometry:

- `position: absolute`
- `left`, `top`, `width`, and `height` in pixels
- `margin: 0`

The UI explains that this detaches the layer from flex/grid flow and preserves the current visual position. Inline text nodes are not detached directly.

### Text editing support

Text editing is allowed only for safe text-bearing selections:

- supported text-bearing tags such as `div`, `span`, `p`, `strong`, and headings
- self text selections or leaf child text layers
- empty text values after a user clears the content
- not a composition host

For multi-text selections, Studio shows a text-layer list. Users can select a specific text layer, edit content live, change size, weight, and font family, add a sibling text layer, or remove the active layer.

### Unsupported examples

Studio intentionally withholds direct geometry editing for:

- flex/grid children whose position is emergent from layout, unless the user chooses `Make movable`
- transform-driven geometry
- nested composition internals while the user is still in master view
- nodes without a stable patch target
- inline text spans as geometry targets

When geometry is blocked but style edits are still safe, the inspector shows the selection and the reason direct geometry editing is unavailable.

If the user tries to drag a blocked layer, Studio shows a toast. Layout-owned layers point users to `Make movable`; transform-driven or unsafe targets explain that direct move/resize is limited to absolute or fixed pixel geometry with no transform-driven layout.

## Nested Composition Rules

Nested compositions are handled explicitly.

### In master view

- clicking content inside a nested composition maps back to the composition host
- supported composition hosts can move as a whole when their host geometry is safe
- Studio does not expose direct inner-node geometry edits from the master preview
- double click drills into the subcomposition

### After drill-down

- Studio resolves selections inside that composition normally
- direct move/resize becomes available again if the selected inner node meets the capability rules
- text, fill, gradient, image, radius, opacity, and typography edits apply to the selected inner node

This keeps Studio honest about what it can patch safely from the current editing context.

## Source Patching Model

Studio still uses authored HTML as the source of truth.

The manual DOM editing flow patches source through the existing patch pipeline in `packages/studio/src/utils/sourcePatcher.ts`.

Current patch types used by the inspector include:

- inline style patches
- attribute patches for timeline-linked editing paths
- text-content patches
- detach-from-layout style patches

The flow is:

1. user selects or manipulates an element in the preview
2. Studio resolves a stable target
3. the preview is updated optimistically for interaction feedback
4. the patch is written back to source
5. the preview refreshes and selection is reattached

## Gradient Editing

The current gradient editor is a structured Studio control, not a raw CSS text field.

It supports:

- `linear`, `radial`, and `conic` gradients
- repeating variants
- multiple stops
- stop insertion by clicking the preview strip
- stop removal
- angle control
- radial shape and size controls
- radial/conic center controls

The editor still serializes back to CSS `background-image`, but the inspector works with a parsed gradient model instead of forcing the user to type raw gradient syntax.

## Image Fill Editing

The image fill editor is no longer just a raw `background-image` input.

It supports:

- selecting an existing project image asset
- uploading an image from the fill panel, which also adds it to the Assets tab
- previewing the selected project asset in the panel
- entering an external URL when the image is not a project asset

Studio serializes project asset selections back to `background-image: url(...)`, and rewrites asset URLs so nested subcomposition previews still resolve the image correctly.

## Color Editing

The color editor is a custom Studio popover instead of the native browser color dialog.

It supports:

- opening from the whole color row
- staying inside the viewport near the clicked color
- saturation / brightness picking with visible crosshair guides
- hue and alpha controls with visible handles
- a current color swatch, readout, and hex input

The picker writes CSS `rgb(...)` or `rgba(...)` values and preserves alpha through edits.

## Numeric Scrubbing

Numeric layout/detail inputs support lightweight design-tool-style nudging:

- mouse wheel over the focused field
- `ArrowUp` / `ArrowDown`
- `Shift` for larger steps
- `Alt` for finer steps

This is currently used across the numeric commit fields in the inspector, including layout metrics and other numeric text inputs that parse cleanly as values plus units.

## Files That Own The Feature

The main implementation lives in:

- `packages/studio/src/App.tsx`
- overall inspector wiring
- selection lifecycle
- preview hit testing
- persistence hooks
- detach-from-layout commit flow
- `packages/studio/src/components/editor/DomEditOverlay.tsx`
- overlay box, drag, resize, blocked-drag feedback
- `packages/studio/src/components/editor/PropertyPanel.tsx`
- right-side inspector UI
- `packages/studio/src/components/editor/domEditing.ts`
- selection resolution
- capability gating
- text field modeling
- prompt generation
- `packages/studio/src/components/editor/colorValue.ts`
- color parsing, HSV conversion, and CSS color serialization
- `packages/studio/src/components/editor/floatingPanel.ts`
- viewport-safe floating panel placement for color picking
- `packages/studio/src/components/editor/fontAssets.ts`
- imported font asset helpers
- `packages/studio/src/components/editor/fontCatalog.ts`
- Google font catalog metadata and stylesheet URLs
- `packages/studio/src/components/editor/gradientValue.ts`
- gradient parsing, serialization, and stop editing helpers
- `packages/studio/src/utils/sourcePatcher.ts`
- source patch persistence

Supporting Studio shell changes also landed in:

- `packages/studio/src/components/nle/NLELayout.tsx`
- `packages/studio/src/components/nle/NLEPreview.tsx`
- `packages/studio/src/components/sidebar/CompositionsTab.tsx`
- `packages/studio/src/components/sidebar/LeftSidebar.tsx`
- `packages/studio/src/player/components/Player.tsx`
- `packages/studio/src/player/components/Timeline.tsx`
- `packages/studio/src/player/components/TimelineClip.tsx`
- `packages/studio/src/player/hooks/useTimelinePlayer.ts`
- `packages/studio/src/utils/mediaTypes.ts`

## Current Constraints

This feature is intentionally **not** a full general-purpose visual builder.

Still out of scope today:

- rotation
- arbitrary transforms
- snapping and alignment guides
- multi-select
- marquee selection
- freeform editing of every DOM node regardless of layout model
- editing nested subcomposition internals directly from the master preview without drill-down
- automatic conversion to absolute positioning on drag without user confirmation
- direct geometry editing of inline text spans

## Bottom Line

Studio manual DOM editing is now a narrow, deterministic visual editing layer over authored HTML.

It does **not** try to make the whole DOM freely editable. Instead it:

- keeps source HTML as the source of truth
- exposes only patchable interactions
- uses a Studio-owned overlay layer for direct manipulation
- gives users a real inspector for safe style and text edits
- treats nested compositions as drill-down boundaries instead of flattening them into an unsafe editing surface

That tradeoff is the reason the current feature feels reliable instead of deceptive.
3 changes: 2 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@
"contributing",
"contributing/catalog",
"contributing/release-channels",
"contributing/testing-local-changes"
"contributing/testing-local-changes",
"contributing/studio-manual-dom-editing"
]
},
{
Expand Down
Loading