From 47d807b9424f33fe2ade70151023e1d3d10f63f6 Mon Sep 17 00:00:00 2001
From: Quang Tran <16215255+trmquang93@users.noreply.github.com>
Date: Mon, 16 Mar 2026 06:06:22 +0700
Subject: [PATCH 1/2] fix: hide ToolBar when batch selection bar is visible
BatchSelectionBar and BatchHotspotBar render at position:fixed bottom-center
at zIndex 900, directly overlapping the ToolBar at the same position. Hide
ToolBar when canvasSelection or selectedHotspots are non-empty so the batch
bar has clean screen space with no stale toolbar artifact beneath it.
---
src/Drawd.jsx | 1 +
src/components/ToolBar.jsx | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Drawd.jsx b/src/Drawd.jsx
index 05d1664..14ef7aa 100644
--- a/src/Drawd.jsx
+++ b/src/Drawd.jsx
@@ -818,6 +818,7 @@ export default function Drawd() {
onToolChange={setActiveTool}
onUpload={handleImageUpload}
onAddBlank={() => addScreenAtCenter()}
+ hidden={canvasSelection.length > 0 || selectedHotspots.length > 0}
onAddStickyNote={() => {
if (!canvasRef.current) return;
const rect = canvasRef.current.getBoundingClientRect();
diff --git a/src/components/ToolBar.jsx b/src/components/ToolBar.jsx
index 09a9d04..b2590ce 100644
--- a/src/components/ToolBar.jsx
+++ b/src/components/ToolBar.jsx
@@ -89,7 +89,8 @@ function ActionButton({ icon: Icon, label, shortcutKey, onClick }) {
);
}
-export function ToolBar({ activeTool, onToolChange, onUpload, onAddBlank, onAddStickyNote }) {
+export function ToolBar({ activeTool, onToolChange, onUpload, onAddBlank, onAddStickyNote, hidden }) {
+ if (hidden) return null;
return (
Date: Mon, 16 Mar 2026 09:40:36 +0700
Subject: [PATCH 2/2] refactor: remove BatchSelectionBar and BatchHotspotBar
overlays
All actions provided by these floating bars (delete, group, escape) are
already accessible via keyboard shortcuts, making the bars redundant.
Removing them eliminates the visual conflict with the persistent ToolBar.
---
src/Drawd.jsx | 56 +----------------------
src/components/BatchHotspotBar.jsx | 67 ----------------------------
src/components/BatchSelectionBar.jsx | 58 ------------------------
src/components/ToolBar.jsx | 3 +-
src/hooks/useHotspotInteraction.js | 4 +-
5 files changed, 3 insertions(+), 185 deletions(-)
delete mode 100644 src/components/BatchHotspotBar.jsx
delete mode 100644 src/components/BatchSelectionBar.jsx
diff --git a/src/Drawd.jsx b/src/Drawd.jsx
index 14ef7aa..456bb41 100644
--- a/src/Drawd.jsx
+++ b/src/Drawd.jsx
@@ -28,8 +28,6 @@ import { ConditionalPrompt } from "./components/ConditionalPrompt";
import { InlineConditionLabels } from "./components/InlineConditionLabels";
import { ShortcutsPanel } from "./components/ShortcutsPanel";
import { ScreensPanel } from "./components/ScreensPanel";
-import { BatchHotspotBar } from "./components/BatchHotspotBar";
-import { BatchSelectionBar } from "./components/BatchSelectionBar";
import { SelectionOverlay } from "./components/SelectionOverlay";
import { ToolBar } from "./components/ToolBar";
import { StickyNote } from "./components/StickyNote";
@@ -53,7 +51,7 @@ export default function Drawd() {
handleImageUpload, onFileChange, handlePaste, handleCanvasDrop,
saveHotspot, deleteHotspot, deleteHotspots, moveHotspot, resizeHotspot, updateScreenDimensions,
updateScreenDescription, updateScreenNotes, updateScreenTbd, updateScreenRoles, updateScreenCodeRef, updateScreenCriteria, assignScreenImage, quickConnectHotspot,
- updateConnection, deleteConnection, pasteHotspots,
+ updateConnection, deleteConnection,
addConnection, convertToConditionalGroup, addToConditionalGroup, saveConnectionGroup, deleteConnectionGroup,
addState, updateStateName, addDocument, updateDocument, deleteDocument,
replaceAll, mergeAll,
@@ -238,7 +236,6 @@ export default function Drawd() {
const {
hotspotInteraction, setHotspotInteraction,
selectedHotspots, setSelectedHotspots,
- hotspotClipboard,
cancelHotspotInteraction,
onHotspotMouseDown, onImageAreaMouseDown,
onResizeHandleMouseDown, onHotspotDragHandleMouseDown,
@@ -390,21 +387,6 @@ export default function Drawd() {
handleMultiDragStart(e, canvasSelection, screens, stickyNotes);
}, [activeTool, captureDragSnapshot, handleMultiDragStart, canvasSelection, screens, stickyNotes]);
- const onGroupSelection = useCallback(() => {
- const selectedScreenIds = canvasSelection.filter((i) => i.type === "screen").map((i) => i.id);
- if (selectedScreenIds.length === 0) return;
- addScreenGroup("Group", selectedScreenIds);
- clearSelection();
- }, [canvasSelection, addScreenGroup, clearSelection]);
-
- const onDeleteSelection = useCallback(() => {
- const screenIds = canvasSelection.filter((i) => i.type === "screen").map((i) => i.id);
- const stickyIds = canvasSelection.filter((i) => i.type === "sticky").map((i) => i.id);
- if (screenIds.length > 0) removeScreens(screenIds);
- stickyIds.forEach((id) => deleteStickyNote(id));
- clearSelection();
- }, [canvasSelection, removeScreens, deleteStickyNote, clearSelection]);
-
const addHotspot = useCallback((screenId) => {
const screen = screens.find((s) => s.id === screenId);
setHotspotModal({ screen, hotspot: null });
@@ -818,7 +800,6 @@ export default function Drawd() {
onToolChange={setActiveTool}
onUpload={handleImageUpload}
onAddBlank={() => addScreenAtCenter()}
- hidden={canvasSelection.length > 0 || selectedHotspots.length > 0}
onAddStickyNote={() => {
if (!canvasRef.current) return;
const rect = canvasRef.current.getBoundingClientRect();
@@ -950,41 +931,6 @@ export default function Drawd() {
)}
{showShortcuts && setShowShortcuts(false)} />}
-
- {canvasSelection.length > 0 && (
-
- )}
-
- {selectedHotspots.length > 0 && canvasSelection.length === 0 && (
- {
- const screenId = selectedHotspots[0].screenId;
- const screen = screens.find((s) => s.id === screenId);
- if (!screen) return;
- const ids = new Set(selectedHotspots.map((h) => h.hotspotId));
- hotspotClipboard.current = screen.hotspots.filter((h) => ids.has(h.id));
- }}
- onPaste={() => {
- if (!hotspotClipboard.current || !selectedScreen) return;
- pasteHotspots(selectedScreen, hotspotClipboard.current);
- setSelectedHotspots([]);
- }}
- onDelete={() => {
- const screenId = selectedHotspots[0].screenId;
- const ids = selectedHotspots.map((h) => h.hotspotId);
- deleteHotspots(screenId, ids);
- setSelectedHotspots([]);
- }}
- onCancel={() => setSelectedHotspots([])}
- />
- )}
);
}
diff --git a/src/components/BatchHotspotBar.jsx b/src/components/BatchHotspotBar.jsx
deleted file mode 100644
index 79cf2dd..0000000
--- a/src/components/BatchHotspotBar.jsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import { COLORS, FONTS, Z_INDEX } from "../styles/theme";
-
-const barBtn = {
- padding: "6px 14px",
- border: "none",
- borderRadius: 6,
- fontSize: 12,
- fontWeight: 600,
- cursor: "pointer",
- fontFamily: FONTS.mono,
-};
-
-export function BatchHotspotBar({ count, hasClipboard, onCopy, onPaste, onDelete, onCancel }) {
- return (
-
-
- {count} selected
-
-
-
-
- {hasClipboard && (
-
- )}
-
-
-
-
-
- );
-}
diff --git a/src/components/BatchSelectionBar.jsx b/src/components/BatchSelectionBar.jsx
deleted file mode 100644
index 6909797..0000000
--- a/src/components/BatchSelectionBar.jsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import { COLORS, FONTS, Z_INDEX } from "../styles/theme";
-
-const barBtn = {
- padding: "6px 14px",
- border: "none",
- borderRadius: 6,
- fontSize: 12,
- fontWeight: 600,
- cursor: "pointer",
- fontFamily: FONTS.mono,
-};
-
-export function BatchSelectionBar({ count, onDelete, onGroup, onCancel }) {
- return (
-
-
- {count} selected
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/components/ToolBar.jsx b/src/components/ToolBar.jsx
index b2590ce..09a9d04 100644
--- a/src/components/ToolBar.jsx
+++ b/src/components/ToolBar.jsx
@@ -89,8 +89,7 @@ function ActionButton({ icon: Icon, label, shortcutKey, onClick }) {
);
}
-export function ToolBar({ activeTool, onToolChange, onUpload, onAddBlank, onAddStickyNote, hidden }) {
- if (hidden) return null;
+export function ToolBar({ activeTool, onToolChange, onUpload, onAddBlank, onAddStickyNote }) {
return (
{
setHotspotInteraction(null);
@@ -143,7 +142,6 @@ export function useHotspotInteraction({
return {
hotspotInteraction, setHotspotInteraction,
selectedHotspots, setSelectedHotspots,
- hotspotClipboard,
cancelHotspotInteraction,
onHotspotMouseDown,
onImageAreaMouseDown,