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:
simoleo89
2026-05-24 21:32:49 +02:00
committed by simoleo89
parent abf43d86c3
commit 12d24719cf
4 changed files with 97 additions and 49 deletions
@@ -1,5 +1,5 @@
import { Dispatch, FC } from 'react';
import { FaRedo, FaUndo } from 'react-icons/fa';
import { FaHandPaper, FaRedo, FaUndo } from 'react-icons/fa';
import { LocalizeText } from '../../../api';
import { Base, Flex, Text } from '../../../common';
import { FloorplanAction, FloorActionMode, FloorplanState } from '../state/types';
@@ -11,6 +11,8 @@ type Props = {
canRedo?: boolean;
onUndo?: () => void;
onRedo?: () => void;
panMode?: boolean;
onTogglePanMode?: () => void;
};
const BRUSH_BUTTONS: { id: string; mode: FloorActionMode; iconClass: string }[] = [
@@ -21,7 +23,7 @@ const BRUSH_BUTTONS: { id: string; mode: FloorActionMode; iconClass: string }[]
{ id: 'tool-door', mode: 'DOOR', iconClass: 'icon-set-door' }
];
export const FloorplanToolbar: FC<Props> = ({ state, dispatch, canUndo, canRedo, onUndo, onRedo }) =>
export const FloorplanToolbar: FC<Props> = ({ state, dispatch, canUndo, canRedo, onUndo, onRedo, panMode, onTogglePanMode }) =>
{
return (
<Flex gap={ 1 } alignItems="center">
@@ -48,6 +50,18 @@ export const FloorplanToolbar: FC<Props> = ({ state, dispatch, canUndo, canRedo,
className={ `nitro-icon icon-set-squaresselect ${ state.squareSelect ? 'border border-primary' : '' }` }
onClick={ () => dispatch({ type: 'SQUARE_SELECT_TOGGLE' }) }
/>
{ onTogglePanMode && (
<Base
pointer
data-testid="tool-pan"
data-active={ panMode ? 'true' : 'false' }
title={ panMode ? 'Modalità mano attiva — trascina per spostare la vista (Spazio per uscire)' : 'Modalità mano — trascina per spostare la vista' }
className={ `ml-1 w-7 h-7 flex items-center justify-center rounded border ${ panMode ? 'bg-emerald-500 border-emerald-700 text-white shadow-inner' : 'border-zinc-300 bg-white hover:bg-zinc-50 text-zinc-700' }` }
onClick={ onTogglePanMode }
>
<FaHandPaper size={ 12 } />
</Base>
) }
{ (onUndo || onRedo) && (
<Flex gap={ 1 } alignItems="center" className="ml-2 pl-2 border-l border-zinc-300">
<Base