react-draggable icon indicating copy to clipboard operation
react-draggable copied to clipboard

Z-index bring to front last dragged window

Open lifeofjer opened this issue 6 years ago • 5 comments

Wanted to share this snippet of code I am using to bring the latest dragged window to the front. Any feedback or improvements are welcome for others looking for the same functionality.

Note: This is definitely a clunky implementation and involves a flash due to timing on when the onStop is triggered

<Draggable 
  onStop={onDraggableStop}
/>
export function onDraggableStop(element) {

  var prev_window = document.getElementsByClassName('react-draggable-last');
  var new_window = document.getElementById(element.path[1].id);

  setTimeout(function(){

    var i;
    for (i = 0; i < prev_window.length; i++) {
      prev_window[i].classList.remove('react-draggable-last');
    }
    new_window.classList.add('react-draggable-last');


  }, 0);

}

lifeofjer avatar May 09 '19 18:05 lifeofjer

I'm not sure if I'm solving the same problem as you, here's my approach for bringing forward the window currently being dragged (and leaving it at the top of the z-index — which I think accomplishes the sam thing):

(edit: this is actually buggy, the z-index values on elements can become out of sync, but the approach with a little tweaking seems clean to me)

const DraggableBlock = (props) => {
  const [isDragging, setIsDragging] = useState({status: false, zIndex: 1000})

  return (
    <Draggable
      handle=".draggable-block-container"
      onStart={() => setIsDragging({...isDragging, status: true, zIndex: isDragging.zIndex + 1})}
      onEnd={() => setIsDragging({...isDragging, status: false})}
      >
      <div 
        className={`draggable-block-container`}
        style={{
          zIndex: isDragging.zIndex
        }}  
      >
          ...
      </div>
    </Draggable>
  )
}

devinhalladay avatar Apr 26 '20 20:04 devinhalladay

Dear future developers who are confused...

  1. use onStop instead of onEnd
  2. try position: 'relative' on <div> if it still doesnt work

promet99 avatar Jul 16 '20 07:07 promet99

I was able to find a solution. I was not happy with any approach that I was having, I tried dinamic zindex with useState but it was not being left in order after drag, I tried with classnames, timeout and I was not happy.

The code that I find best is.

const DraggableBlock = (props) => {
  const [currentZIndex, setCurrentZIndex] = useState(31);

  const handleZindex = (element) => {
    element.style.zIndex = currentZIndex;
    setCurrentZIndex((state) => state + 1);
  };

  return (
    <Draggable
      handle=".draggable-block-container"
      onStart={() => handleZindex(blockRef.current)}
      >
      <div 
        className={`draggable-block-container`}
        ref={blockRef}
      >
          ...
      </div>
    </Draggable>
  )
}  

This way each component will remain in order of dragable.

Bonus:

I also needed to made sure that some components would not be able to be dragged on. For example: if we drag a component and the current z index is bigger than the component, it will be on top of the component that we don't want to. In my case, it was a cart slide panel, I handle by passing the zIndex: currentZIndex + 10 on inline style to it.

LucasBoscariole avatar Nov 10 '22 17:11 LucasBoscariole

This worked for me.

"DraggableContext.tsx"

import { createContext } from "react";

export interface DraggableContextInterface {
  index: number;
  setIndex: (index: number) => void;
}

const initialState: DraggableContextInterface = {
  index: 3,
  setIndex: (index: number) => {},
};

export const DraggableContext = createContext(initialState);

"App.tsx"

const [index, setIndex] = useState(3);
return(
<DraggableContext.Provider value={{ index, setIndex }}>
     <App/>
</DraggableContext.Provider>
)

"Draggable Component"

const { index, setIndex }: DraggableContextInterface = useContext(DraggableContext);
const [currentZIndex, setCurrentZIndex] = useState(1);
  const onStart: DraggableEventHandler | undefined = () => {
    if (index != currentZIndex + 1) {
      setCurrentZIndex(index);
      setIndex(index + 1);
    }
  };
return (
    <Draggable onStart={onStart}>
       <div zIndex={currentZIndex}>I'm dragable</div>
    </Draggable>
)

imgopaal avatar Jul 05 '23 17:07 imgopaal