mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
feat(floorplan-editor): polish height slider + add hand tool for canvas pan
Two related polish improvements after the swatch-column → vertical- slider swap. Slider - Wider track (18 px, was 14 px) for a more comfortable click area with the same on-screen footprint. - Min / max chips above and below the rail (HEIGHT_BRUSH_MIN / _MAX) so users know which end is high and which is low without hovering to discover. - Thumb now uses a warm amber radial gradient (#fff7c4 → #facc15 → #ca8a04) on a dark brown border with a soft drop shadow + inset highlight, instead of the flat yellow disc. Hover adds a white ring; drag swaps it for a darker ring — clear gesture feedback. - Track gains a hover/drag glow (inset white seam + amber outline via boxShadow) so you can tell the slider has focus before you even click. Hand tool (canvas pan) - New FloorplanToolbar button (FaHandPaper, sticky toggle, emerald fill when active) ties to a new state lifted into FloorplanEditorView. When the hand is active, plain left-click + drag pans the canvas instead of brushing tiles. Cursor flips to grab / grabbing accordingly. - FloorplanCanvasSVG's isPanGesture predicate becomes: middle-mouse OR Shift+left-click OR (panMode && left-click). Shift / middle still work whether or not the hand is on so power users keep their muscle memory. - No change to the reducer (panMode is a canvas-level UI flag, not a brush action — keeps state/types tight).
This commit is contained in:
@@ -9,6 +9,13 @@ import { TILE_SIZE, MAX_NUM_TILE_PER_AXIS } from '../state/constants';
|
||||
type Props = {
|
||||
state: FloorplanState;
|
||||
dispatch: Dispatch<FloorplanAction>;
|
||||
/**
|
||||
* When true, left-click + drag pans the canvas instead of
|
||||
* brushing. Driven by the hand-tool toggle in the toolbar.
|
||||
* Shift+drag and middle-mouse drag always pan regardless of
|
||||
* this flag.
|
||||
*/
|
||||
panMode?: boolean;
|
||||
};
|
||||
|
||||
const VIEWBOX_W = 2048;
|
||||
@@ -76,7 +83,7 @@ const computeRoomBounds = (state: FloorplanState): { x: number; y: number; w: nu
|
||||
};
|
||||
};
|
||||
|
||||
export const FloorplanCanvasSVG: FC<Props> = ({ state, dispatch }) =>
|
||||
export const FloorplanCanvasSVG: FC<Props> = ({ state, dispatch, panMode }) =>
|
||||
{
|
||||
const svgRef = useRef<SVGSVGElement | null>(null);
|
||||
const [ zoom, setZoom ] = useState(1);
|
||||
@@ -204,14 +211,24 @@ export const FloorplanCanvasSVG: FC<Props> = ({ state, dispatch }) =>
|
||||
};
|
||||
}, [ visW ]);
|
||||
|
||||
const isPanGesture = (e: ReactPointerEvent): boolean => e.button === 1 || (e.button === 0 && e.shiftKey);
|
||||
// Pan gestures: middle-mouse, Shift+left-click, and (when the
|
||||
// hand-tool is active) plain left-click. The hand-tool toggle
|
||||
// is the toolbar affordance — Shift / middle still work even
|
||||
// when the hand isn't on, so power users keep their muscle
|
||||
// memory.
|
||||
const isPanGesture = (e: ReactPointerEvent): boolean =>
|
||||
e.button === 1
|
||||
|| (e.button === 0 && e.shiftKey)
|
||||
|| (e.button === 0 && Boolean(panMode));
|
||||
|
||||
const cursorClass = isPanning ? 'cursor-grabbing' : panMode ? 'cursor-grab' : '';
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-full">
|
||||
<svg
|
||||
ref={ svgRef }
|
||||
viewBox={ viewBox }
|
||||
className={ `w-full h-full select-none rounded-md border border-zinc-300 bg-[url('@/assets/images/floorplaneditor/canvas_floor_pattern.png')] bg-repeat [image-rendering:pixelated] ${ isPanning ? 'cursor-grabbing' : '' }` }
|
||||
className={ `w-full h-full select-none rounded-md border border-zinc-300 bg-[url('@/assets/images/floorplaneditor/canvas_floor_pattern.png')] bg-repeat [image-rendering:pixelated] ${ cursorClass }` }
|
||||
onWheel={ onWheel }
|
||||
onPointerDown={ e =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user