diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-draggable-preview-layer.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-draggable-preview-layer.jsx
index e335004faf..e3b0c97117 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-draggable-preview-layer.jsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-draggable-preview-layer.jsx
@@ -1,6 +1,5 @@
import { useRef } from 'react'
import PropTypes from 'prop-types'
-import { useDragLayer } from 'react-dnd'
import classNames from 'classnames'
// a custom component rendered on top of a draggable area that renders the
@@ -8,12 +7,12 @@ import classNames from 'classnames'
// https://react-dnd.github.io/react-dnd/examples/drag-around/custom-drag-layer
// for more details.
// Also used to display a container border when hovered.
-function FileTreeDraggablePreviewLayer({ isOver }) {
- const { isDragging, item, clientOffset } = useDragLayer(monitor => ({
- isDragging: monitor.isDragging(),
- item: monitor.getItem(),
- clientOffset: monitor.getClientOffset(),
- }))
+function FileTreeDraggablePreviewLayer({
+ isOver,
+ isDragging,
+ item,
+ clientOffset,
+}) {
const ref = useRef()
return (
@@ -39,6 +38,11 @@ function FileTreeDraggablePreviewLayer({ isOver }) {
FileTreeDraggablePreviewLayer.propTypes = {
isOver: PropTypes.bool.isRequired,
+ isDragging: PropTypes.bool.isRequired,
+ item: PropTypes.shape({
+ title: PropTypes.string.isRequired,
+ }),
+ clientOffset: PropTypes.number,
}
function DraggablePreviewItem({ title }) {
diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner.jsx b/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner.jsx
index 6f8db60910..ce497963ab 100644
--- a/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner.jsx
+++ b/services/web/frontend/js/features/file-tree/components/file-tree-item/file-tree-item-inner.jsx
@@ -11,6 +11,7 @@ import FileTreeItemName from './file-tree-item-name'
import FileTreeItemMenu from './file-tree-item-menu'
import { useFileTreeSelectable } from '../../contexts/file-tree-selectable'
import { useFileTreeActionable } from '../../contexts/file-tree-actionable'
+import { useDragDropManager } from 'react-dnd'
function FileTreeItemInner({ id, name, isSelected, icons }) {
const { permissionsLevel } = useEditorContext(editorContextPropTypes)
@@ -24,7 +25,9 @@ function FileTreeItemInner({ id, name, isSelected, icons }) {
isSelected &&
selectedEntityIds.size === 1
- const { isDragging, dragRef, setIsDraggable } = useDraggable(id)
+ const { dragRef, setIsDraggable } = useDraggable(id)
+
+ const dragDropItem = useDragDropManager().getMonitor().getItem()
const itemRef = useRef()
@@ -58,7 +61,7 @@ function FileTreeItemInner({ id, name, isSelected, icons }) {
return (
({
+ isDragging: monitor.isDragging(),
+ item: monitor.getItem(),
+ clientOffset: monitor.getClientOffset(),
+ }))
+
return (
<>
-
+
diff --git a/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.jsx b/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.jsx
index b9d81e57a2..c92a0ef335 100644
--- a/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.jsx
+++ b/services/web/frontend/js/features/file-tree/contexts/file-tree-draggable.jsx
@@ -88,7 +88,7 @@ export function useDraggable(draggedEntityId) {
const [isDraggable, setIsDraggable] = useState(true)
const item = { type: DRAGGABLE_TYPE }
- const [{ isDragging }, dragRef, preview] = useDrag({
+ const [{ isDragging, draggedEntityIds }, dragRef, preview] = useDrag({
item, // required, but overwritten by the return value of `begin`
begin: () => {
const draggedEntityIds = getDraggedEntityIds(
@@ -104,6 +104,7 @@ export function useDraggable(draggedEntityId) {
isDragging: !!monitor.isDragging(),
}),
canDrag: () => permissionsLevel !== 'readOnly' && isDraggable,
+ end: () => item,
})
// remove the automatic preview as we're using a custom preview via
@@ -116,6 +117,7 @@ export function useDraggable(draggedEntityId) {
dragRef,
isDragging,
setIsDraggable,
+ draggedEntityIds,
}
}
diff --git a/services/web/frontend/stylesheets/app/editor/file-tree.less b/services/web/frontend/stylesheets/app/editor/file-tree.less
index 689f456bc5..cea955c581 100644
--- a/services/web/frontend/stylesheets/app/editor/file-tree.less
+++ b/services/web/frontend/stylesheets/app/editor/file-tree.less
@@ -67,22 +67,6 @@
}
}
- li.dnd-droppable-hover .entity-name,
- li .entity-name.droppable-hover {
- font-weight: bold;
- background-color: @file-tree-item-hover-bg;
- .fake-full-width-bg(@file-tree-item-hover-bg);
- }
-
- ul.droppable-hover li div.entity-name:hover {
- background-color: transparent;
- .fake-full-width-bg(transparent);
- &.droppable-hover {
- background-color: @file-tree-item-hover-bg;
- .fake-full-width-bg(@file-tree-item-hover-bg);
- }
- }
-
ul.file-tree-list {
margin: 0;
overflow-x: hidden;
@@ -144,10 +128,10 @@
&:focus {
outline: none;
}
+ background-color: transparent;
&:hover {
background-color: @file-tree-item-hover-bg;
- }
- &:hover {
+
// When the entity is a subfolder, the DOM element is "indented" via margin-left. This makes the
// element not fill the entire file-tree width (as it's spaced from the left-hand side via margin)
// and, in consequence, the background gets clipped. The ::before pseudo-selector is used to fill
@@ -163,13 +147,6 @@
}
}
- .entity.dnd-draggable-dragging {
- .entity-name:hover {
- background-color: transparent;
- .fake-full-width-bg(transparent);
- }
- }
-
i.fa {
color: @file-tree-item-icon-color;
font-size: 14px;
@@ -309,15 +286,18 @@
> .entity {
> .entity-name {
color: @file-tree-item-selected-color;
+
> div > i.fa,
> button > i.fa,
> i.fa,
.entity-menu-toggle i.fa {
color: @file-tree-item-selected-color;
}
+
> i.linked-file-highlight {
color: @blue;
}
+
background-color: @file-tree-item-selected-bg;
font-weight: bold;
padding-right: 32px;
@@ -332,13 +312,43 @@
}
}
}
- ul.file-tree-list li.selected.dnd-droppable-hover {
- > .entity {
- > .entity-name {
- background-color: @file-tree-item-hover-bg;
- .fake-full-width-bg(@file-tree-item-hover-bg);
- }
- }
+ }
+
+ // while dragging, the previously selected item gets no highlight
+ ul.file-tree-list.file-tree-dragging li.selected .entity .entity-name {
+ font-weight: normal;
+
+ background-color: transparent;
+ .fake-full-width-bg(transparent);
+ color: @file-tree-item-color;
+ i.fa {
+ color: @file-tree-item-icon-color !important;
+ }
+ }
+
+ // the items being dragged get the full "hover" colour
+ ul.file-tree-list.file-tree-dragging
+ li
+ .entity.file-tree-entity-dragging
+ .entity-name {
+ background-color: fade(@file-tree-item-hover-bg, 90%);
+ .fake-full-width-bg(fade(@file-tree-item-hover-bg, 90%));
+ color: @file-tree-item-color;
+ i.fa {
+ color: @file-tree-item-icon-color !important;
+ }
+ }
+
+ // the drop target gets the "selected" colour
+ ul.file-tree-list.file-tree-dragging
+ li.dnd-droppable-hover
+ .entity
+ .entity-name {
+ background-color: @file-tree-item-selected-bg;
+ .fake-full-width-bg(@file-tree-item-selected-bg);
+ color: @file-tree-item-selected-color;
+ i.fa {
+ color: @file-tree-item-selected-color !important;
}
}
@@ -355,8 +365,7 @@
}
}
- .dnd-draggable-preview-item,
- .ui-draggable-dragging {
+ .dnd-draggable-preview-item {
background-color: fade(@file-tree-item-selected-bg, 60%);
color: @file-tree-item-selected-color;
width: 75%;