feat: preview state styles during canvas drags - #684
Open
stravo1 wants to merge 25 commits into
Open
Conversation
When a state variant is active, canvas drag handles now read and write the active style key instead of falling back to the base style. This keeps rotation, resize, spacing, movement and border radius previews aligned with the selected state.
stravo1
marked this pull request as draft
July 20, 2026 11:22
Contributor
Confidence Score: 5/5
Reviews (13): Last reviewed commit: "Revert "feat: add extension SDK bundle"" | Re-trigger Greptile |
# Conflicts: # frontend/src/components/BlockEditor.vue # frontend/src/components/BorderRadiusHandler.vue # frontend/src/components/BuilderBlock.vue # frontend/src/composables/useSpacingHandler.ts
stravo1
marked this pull request as ready for review
August 12, 2026 11:43
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #684 +/- ##
===========================================
+ Coverage 66.05% 66.22% +0.16%
===========================================
Files 37 90 +53
Lines 4982 10015 +5033
===========================================
+ Hits 3291 6632 +3341
- Misses 1691 3383 +1692 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Canvas drag handlers paired a "has a value" guard with getNumberFromPx. getNumberFromPx strips only "px", so a percentage or em value silently became 0 and snapped the block to the origin on the first drag frame. Add getNumberInUnit next to removeDefaultUnit and normalizeValueWithUnits in cssUtils. It applies the same default-unit rule the property controls use: a unitless number takes the given unit, another unit or a value that is not a plain number gives back null. It uses the same anchored regex, so negatives, uppercase units, `auto` and `calc(...)` all read correctly. The three handlers now fall back to the rendered value when the style cannot be read as pixels. This also removes the hasStyleValue copies from BoxResizer and useSpacingHandler. Co-Authored-By: Claude <noreply@anthropic.com>
Picking a state (hover, active, focus) makes the canvas preview it, but nothing said which control drove that preview, and the caret stayed where it was. Move focus into the active state's field, so its focus styling marks the row and the value is ready to type. Leaving the field ends the preview, so the canvas and the panel read normally again. A state picked for a property with no value yet had nothing to show, and the row only rendered for a truthy value, so it never appeared. Track the states the user adds and keep their rows until a value arrives or the user removes the row. Tying the row to focus does not work here, because the field commits its value 100ms after the change event, well after the next click would have dropped the row. The label dropdown returns focus to its trigger as it closes, and that trigger is a span, so focus fell to <body> a few frames after the row appeared. Take focus back while nothing else holds it. The clear button no longer takes focus or marks its state active, so removing a state does not flash the row first. Co-Authored-By: Claude <noreply@anthropic.com>
stravo1
force-pushed
the
variant-preview
branch
from
August 12, 2026 16:59
b3d0141 to
7103968
Compare
The focus-claim guard suppressed every focusout while it ran, including the user clicking another control. The row then kept activeState set with no later event to clear it, so canvas drags wrote to the state style instead of the base style. Focus that goes nowhere is the dropdown closing. Focus that goes to another element is the user leaving, so end the claim and the preview. Reported by Greptile on frappe#684. Co-Authored-By: Claude <noreply@anthropic.com>
The resize edge handles and the radius handle did not prevent the default mousedown, so the browser moved focus off the property field. That ended the state preview mid-drag. The rotation handles and the resize corners already prevent it. Co-Authored-By: Claude <noreply@anthropic.com>
Member
|
@mergify update |
Contributor
✅ Branch has been successfully updated |
An open options list stopped the input from reading a new value. A drag on the label slider or a canvas resize handle changed the block but left the old text in the field. Watch the value and the options apart. Only the options wait for the list to close, because an open list can hold text that the user typed. Co-Authored-By: Claude <noreply@anthropic.com>
A mousedown on a state label moved focus off the field. The row read that as a departure and ended the preview, so the drag cleared the state it set. Co-Authored-By: Claude <noreply@anthropic.com>
Resize and rotation read the base style at drag start and restored it on escape, but the drag writes to the active state key. Escape left the state style at the dragged value. Read and restore through getActiveStyleProperty, as BorderRadiusHandler does. Co-Authored-By: Claude <noreply@anthropic.com>
The key was resolved twice, so a state change during the drag could send the escape restore to a different key than the one the drag wrote to. Co-Authored-By: Claude <noreply@anthropic.com>
A state row keeps its field focused during a drag, and the row stops keydown so builder shortcuts do not fire while typing. Escape died there and the drag never cancelled. Listen in the capture phase, which runs before the target sees the key. Co-Authored-By: Claude <noreply@anthropic.com>
The arrows stopped their mousedown, so the row never heard it and the state stayed inactive. The canvas kept previewing nothing while the state value changed. Let the mousedown reach the row. It sets the state active, and the row then puts focus in its field. Co-Authored-By: Claude <noreply@anthropic.com>
Controls such as Background and Color open a popover from the row. The panel is portalled out of the row and takes the focus with it, so the row read this as a departure and ended the preview. The value went to the state, but the canvas showed the base style. Treat an open popover as the row still being in use. Co-Authored-By: Claude <noreply@anthropic.com>
A closing popover hands focus back to the row, so a click on the canvas could leave the state previewed. Watch for a pointer press outside the row and its popover, which says the user is done whatever the focus does next. Co-Authored-By: Claude <noreply@anthropic.com>
This reverts commit b50d9b4.
A closing popover hands focus back to the row, so focus alone could leave a state previewed after the user went back to the canvas. Clear the state on the canvas mousedown. The drag handles stop that event, so a drag that edits the state still keeps it. Co-Authored-By: Claude <noreply@anthropic.com>
The row skipped the blur while a popover was open, but focusout fires once. After the panel closed, nothing asked again, so the preview never ended. Watch the panel instead. When it leaves the DOM, the focus and the press that closed it decide. Reka gives the focus back to the row when the panel closes on its own. A press inside the row, or one that prevents its default the way the drag handles do, goes on editing the state, so the row takes the focus back. Anything else ends the preview. Drop the canvas mousedown clear. It could not hold, because the focus returning to the row set the state again. Co-Authored-By: Claude <noreply@anthropic.com>
Cut the restatements of what the code already shows. Keep only the reason each block exists: the dropdown returning focus to a span, the panel living outside the row, and what a press means for the preview. Co-Authored-By: Claude <noreply@anthropic.com>
The top and left label placements used two root elements, and each one held the same control block. One root now serves both placements. The root class changes with the placement, and v-if keeps the parts that differ. This drops the second copy of the control component and its slot loop. The rendered output stays the same. The class shrink-1 did nothing, because the parent of the control is not a flex container. The class h-3 w-3 becomes size-3, which the other clear button already uses. The helper panelFor had one caller. Its body now sits in handleFocusOut. Co-Authored-By: Claude <noreply@anthropic.com>
Extract the swatch popover behavior into useStatePopover. The composable owns which state a popover edits, whether a click closes it, and when the canvas preview ends. ColorInput, BackgroundHandler and ShadowHandler now share it. A row lost its canvas preview when the user reopened a picker from the swatch while the field still held focus. Because the field was focused, the isActive watch skipped keepFocus and left claimingFocus false. The opening panel then dropped focus with no relatedTarget, and the row read that as the user leaving. A press inside the row now keeps the preview. An editor also cleared a state that another control had just claimed. endStatePreview now clears only the state it previewed. Co-Authored-By: Claude <noreply@anthropic.com>
This reverts commit f606d5d.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a state variant is active, canvas drag handles now read and write the active style key instead of falling back to the base style. This keeps rotation, resize, spacing, movement and border radius previews aligned with the selected state.
Screen.Recording.2026-07-20.at.4.50.17.PM.mov