From f2263a287882fdaf8f4dbe8e13262db4bf4dce45 Mon Sep 17 00:00:00 2001 From: varadaraj772 Date: Tue, 28 Apr 2026 14:42:52 +0530 Subject: [PATCH] fix: improve UI consistency (cursor, drag state, border radius, layer styling) --- frontend/src/components/editor-layers-panel.tsx | 7 ++++--- .../src/components/floating-toolbar-shell.tsx | 4 ++-- frontend/src/components/scene-editor.tsx | 7 +++++-- .../components/scene-editor/canvas-stage.tsx | 3 ++- .../scene-editor/editor-bottom-tools.tsx | 17 ++++++++++++----- .../components/scene-editor/editor-store.tsx | 5 +++++ .../src/components/scene-editor/object-view.tsx | 10 +++++++++- .../src/components/shape-options-toolbar.tsx | 2 +- frontend/src/styles.css | 10 ++++++++++ 9 files changed, 50 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/editor-layers-panel.tsx b/frontend/src/components/editor-layers-panel.tsx index 466a292..6b00a20 100644 --- a/frontend/src/components/editor-layers-panel.tsx +++ b/frontend/src/components/editor-layers-panel.tsx @@ -104,9 +104,10 @@ function LayerRowLabelControl({ function layerRowClass(selected: boolean) { return [ - 'flex items-center gap-0.5 rounded-lg py-0.5', - selected ? 'bg-[var(--accent)]/20' : 'hover:bg-black/[0.04]', - ].join(' ') + "flex items-center gap-0.5 py-0.5", + selected ? "bg-[var(--accent)]/20" : "hover:bg-black/[0.04]", + "last:rounded-b-2xl rounded-lg", + ].join(" "); } function LayerReorderRow({ diff --git a/frontend/src/components/floating-toolbar-shell.tsx b/frontend/src/components/floating-toolbar-shell.tsx index 4ba0f12..e1111ad 100644 --- a/frontend/src/components/floating-toolbar-shell.tsx +++ b/frontend/src/components/floating-toolbar-shell.tsx @@ -44,8 +44,8 @@ export function floatingToolbarIconButton( opts?: { wide?: boolean }, ): string { const base = opts?.wide - ? 'flex h-8 min-w-[2.75rem] shrink-0 items-center justify-center gap-0.5 rounded-lg px-1.5 text-neutral-600 outline-none transition-colors hover:bg-black/[0.06]' - : 'flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-neutral-600 outline-none transition-colors hover:bg-black/[0.06]' + ? 'flex h-8 min-w-[2.75rem] shrink-0 items-center justify-center gap-0.5 rounded-full px-1.5 text-neutral-600 outline-none transition-colors hover:bg-black/[0.06]' + : 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-neutral-600 outline-none transition-colors hover:bg-black/[0.06]' return active ? `${base} bg-black/[0.08] text-neutral-900` : base } diff --git a/frontend/src/components/scene-editor.tsx b/frontend/src/components/scene-editor.tsx index 0612ccb..6de93de 100644 --- a/frontend/src/components/scene-editor.tsx +++ b/frontend/src/components/scene-editor.tsx @@ -90,6 +90,7 @@ import { EditorSelectionToolbar } from './scene-editor/editor-selection-toolbar' import { createEditorStore, EditorStoreProvider, + useEditorStore, type EditorStoreApi, } from './scene-editor/editor-store' import { @@ -246,6 +247,7 @@ const SceneEditor = forwardRef( const selectedIds = useStore(editorStore, (state) => state.selectedIds) const setSelectedIds = useStore(editorStore, (state) => state.setSelectedIds) const setHoveredId = useStore(editorStore, (state) => state.setHoveredId) + const setIsDragging = useStore(editorStore, (state) => state.setIsDragging) const [ready, setReady] = useState(false) const [zoomPercent, setZoomPercent] = useState(null) @@ -294,7 +296,6 @@ const SceneEditor = forwardRef( pickBackgroundPopoverPanel, 'center', ) - useEffect(() => { if (!bgPopoverOpen) return const onDown = (e: MouseEvent) => { @@ -1533,6 +1534,7 @@ const SceneEditor = forwardRef( const onUp = () => { dragStateRef.current = null + setIsDragging(false) setMarqueeRect(null) snapGuideXRef.current = null snapGuideYRef.current = null @@ -1547,7 +1549,7 @@ const SceneEditor = forwardRef( window.addEventListener('pointerup', onUp) window.addEventListener('pointercancel', onUp) }, - [artboardH, artboardW, pointerToScene], + [artboardH, artboardW, pointerToScene,setIsDragging], ) const onObjectPointerDown = useCallback( @@ -1590,6 +1592,7 @@ const SceneEditor = forwardRef( const snapTargets = doc.objects .filter((row) => row.visible && !sourceIds.includes(row.id)) .map((row) => getObjectRotatedBounds(row)) + setIsDragging(true) startWindowDrag({ kind: 'move', ids, diff --git a/frontend/src/components/scene-editor/canvas-stage.tsx b/frontend/src/components/scene-editor/canvas-stage.tsx index 29d8719..d7ae1b7 100644 --- a/frontend/src/components/scene-editor/canvas-stage.tsx +++ b/frontend/src/components/scene-editor/canvas-stage.tsx @@ -79,6 +79,7 @@ export function CanvasStage() { const objects = useEditorStore((state) => state.doc.objects) const selectedIds = useEditorStore((state) => state.selectedIds) const hoveredId = useEditorStore((state) => state.hoveredId) + const isDragging = useEditorStore((state) => state.isDragging) const { boardDocs } = useVectorBoardControlsContext() const artboardW = artboard.width const artboardH = artboard.height @@ -89,7 +90,6 @@ export function CanvasStage() { : null, [hoveredId, objects], ) - return (
@@ -138,6 +138,7 @@ export function CanvasStage() { transform: `scale(${scale})`, transformOrigin: 'top left', background: bg.type === 'solid' ? bg.color : bg.css, + cursor: isDragging ? 'grabbing' : 'grab', }} onPointerEnter={onArtboardPointerEnter} onPointerMove={onArtboardPointerMove} diff --git a/frontend/src/components/scene-editor/editor-bottom-tools.tsx b/frontend/src/components/scene-editor/editor-bottom-tools.tsx index 2a85d91..7751725 100644 --- a/frontend/src/components/scene-editor/editor-bottom-tools.tsx +++ b/frontend/src/components/scene-editor/editor-bottom-tools.tsx @@ -20,7 +20,7 @@ import ShapesPopover, { function toolbarIconBtn(disabled?: boolean) { const base = - 'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-neutral-600 outline-none transition-colors hover:bg-black/[0.06]' + 'flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-neutral-600 outline-none transition-colors hover:bg-black/[0.06]' if (disabled) return `${base} pointer-events-none cursor-not-allowed opacity-35` return base } @@ -80,12 +80,12 @@ export function EditorBottomTools({ >
) => void setHoveredId: (next: EditorSetter) => void setSelectedIds: (next: EditorSetter) => void + setIsDragging: (next: EditorSetter) => void } export type EditorStoreApi = StoreApi @@ -36,11 +38,14 @@ export function createEditorStore(initialDoc: AvnacDocument): EditorStoreApi { doc: initialDoc, hoveredId: null, selectedIds: [], + isDragging: false, setDoc: (next) => set((state) => ({ doc: applySetter(next, state.doc) })), setHoveredId: (next) => set((state) => ({ hoveredId: applySetter(next, state.hoveredId) })), setSelectedIds: (next) => set((state) => ({ selectedIds: applySetter(next, state.selectedIds) })), + setIsDragging: (next) => + set((state) => ({ isDragging: applySetter(next, state.isDragging) })), })) } diff --git a/frontend/src/components/scene-editor/object-view.tsx b/frontend/src/components/scene-editor/object-view.tsx index fef2975..fee539d 100644 --- a/frontend/src/components/scene-editor/object-view.tsx +++ b/frontend/src/components/scene-editor/object-view.tsx @@ -310,12 +310,20 @@ export function SceneObjectView({ if (obj.type === 'rect') { const inset = strokeWidth > 0 ? strokeWidth / 2 : 0 + const isLocked = obj.locked; + const cursorStyle = isLocked + ? 'not-allowed' + : 'grab'; return (
onObjectPointerDown(e, obj)} {...hoverProps} title={obj.locked ? 'Locked shape' : undefined} + > diff --git a/frontend/src/components/shape-options-toolbar.tsx b/frontend/src/components/shape-options-toolbar.tsx index 8b65aac..4ec82db 100644 --- a/frontend/src/components/shape-options-toolbar.tsx +++ b/frontend/src/components/shape-options-toolbar.tsx @@ -159,7 +159,7 @@ export default function ShapeOptionsToolbar({ if (meta.kind === 'ellipse') { return ( -
+