diff --git a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-drag-drop.tsx b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-drag-drop.tsx
index 2c2c4516d..a6ae5c317 100644
--- a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-drag-drop.tsx
+++ b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-drag-drop.tsx
@@ -237,6 +237,16 @@ export const EnvelopeEditorFieldDragDrop = ({
[selectedRecipientId, getRecipientColorKey],
);
+ /**
+ * Begin placing a field type. Also clears the current field selection so the
+ * previously placed field's action toolbar can't intercept the next placement
+ * click on the canvas (the renderer mirrors this onto the canvas selection).
+ */
+ const handleStartPlacingField = (type: FieldType) => {
+ setSelectedField(type);
+ editorFields.setSelectedField(null);
+ };
+
return (
<>
@@ -245,8 +255,8 @@ export const EnvelopeEditorFieldDragDrop = ({
disabled={isFieldsDisabled}
key={field.type}
type="button"
- onClick={() => setSelectedField(field.type)}
- onMouseDown={() => setSelectedField(field.type)}
+ onClick={() => handleStartPlacingField(field.type)}
+ onMouseDown={() => handleStartPlacingField(field.type)}
data-selected={selectedField === field.type ? true : undefined}
className={cn(
'group flex h-12 cursor-pointer items-center justify-center rounded-lg border border-border px-4 transition-colors',
diff --git a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx
index db8f6ffbb..23d97ca8d 100644
--- a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx
+++ b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx
@@ -521,11 +521,42 @@ export const EnvelopeEditorFieldsPageRenderer = ({ pageData }: { pageData: PageR
setSelectedFields(liveSelectedFieldGroups);
}
+ // Mirror the editor's single selected field onto the canvas (Konva) selection.
+ //
+ // `addField` already marks a newly created field as the selected field, so this
+ // makes a field placed via the palette (drag-drop) or marquee creation show its
+ // resize handles immediately -- no second click needed. It also clears the canvas
+ // selection when the selected field is cleared (e.g. when the author starts
+ // placing another field), so the floating action toolbar can't intercept the next
+ // placement click. Runs after the render loop above so the field's group exists.
+ const selectedFormId = editorFields.selectedField?.formId ?? null;
+ const isSingleCanvasSelection = selectedKonvaFieldGroups.length === 1;
+
+ if (selectedFormId && localPageFields.some((field) => field.formId === selectedFormId)) {
+ const isAlreadySelected = isSingleCanvasSelection && selectedKonvaFieldGroups[0].id() === selectedFormId;
+
+ if (!isAlreadySelected) {
+ const fieldGroupToSelect = pageLayer.current.findOne(`#${selectedFormId}`);
+
+ if (fieldGroupToSelect instanceof Konva.Group) {
+ setSelectedFields([fieldGroupToSelect]);
+ }
+ }
+ } else if (selectedFormId === null && isSingleCanvasSelection) {
+ setSelectedFields([]);
+ }
+
// Rerender the transformer
interactiveTransformer.current?.forceUpdate();
pageLayer.current.batchDraw();
- }, [localPageFields, selectedKonvaFieldGroups, overlappingFieldFormIds, isFieldChanging]);
+ }, [
+ localPageFields,
+ selectedKonvaFieldGroups,
+ overlappingFieldFormIds,
+ isFieldChanging,
+ editorFields.selectedField?.formId,
+ ]);
const setSelectedFields = (nodes: Konva.Node[]) => {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions