Implementation:TobikoData Sqlmesh FileExplorer DragLayer
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, File_Explorer, Drag_and_Drop |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
A React component that provides a custom drag preview layer for dragging files and directories in the file explorer.
Description
FileExplorer_DragLayer is a React component that implements a custom drag preview for file and directory drag operations using react-dnd's useDragLayer hook. Instead of using the browser's default drag preview, it creates a fixed-position overlay that follows the mouse cursor with styled previews of the items being dragged. The component handles multi-select dragging, showing all selected items when dragging from a selection, or just the single item when dragging an unselected item.
The drag layer creates visually appealing drag previews with drop shadows and themed backgrounds, displaying the appropriate icons and labels for each file or directory. It tracks the drag state (isDragging, currentOffset, artifact) and automatically shows/hides based on the drag operation. The component integrates with the project context to determine which items are in the active selection range.
Usage
Use this component as a global overlay in the file explorer to provide enhanced drag previews. It should be rendered once at the root level of the file explorer, not within individual draggable items.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/library/components/fileExplorer/DragLayer.tsx
Signature
export default function DragLayer(): JSX.Element
function getItemStyles(currentOffset: XYCoord | null): React.CSSProperties
Import
import DragLayer from '@components/fileExplorer/DragLayer'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| N/A | N/A | N/A | Component reads drag state from react-dnd and project context |
Outputs
| Name | Type | Description |
|---|---|---|
| JSX.Element | JSX.Element | The rendered drag preview layer (empty when not dragging) |
Drag Layer Hook
The component uses react-dnd's useDragLayer hook:
const { isDragging, currentOffset, artifact } = useDragLayer(monitor => ({
artifact: monitor.getItem(),
isDragging: monitor.isDragging(),
currentOffset: monitor.getSourceClientOffset(),
}))
Monitored Values
| Property | Type | Description |
|---|---|---|
| artifact | ModelFile or ModelDirectory | The item being dragged |
| isDragging | boolean | Whether a drag operation is in progress |
| currentOffset | XYCoord or null | Current mouse position relative to viewport |
Multi-Select Logic
The component determines which items to show:
const artifacts = useMemo(
() =>
Array.from(
inActiveRange(artifact) ? activeRange : new Set([artifact]),
).filter(Boolean),
[activeRange, artifact],
)
Logic:
- If dragged item is in active selection: Show all items in activeRange
- Otherwise: Show only the dragged item
- Filter out null/undefined values
Layer Styles
The drag layer uses fixed positioning:
const layerStyles: CSSProperties = {
position: 'fixed',
pointerEvents: 'none',
zIndex: 100,
left: 0,
top: 0,
width: '100%',
height: '100%',
}
Style Properties
- position: fixed: Overlay covers entire viewport
- pointerEvents: none: Doesn't interfere with drop targets
- zIndex: 100: Appears above file explorer content
- Full viewport coverage: 100% width and height
Item Positioning
Each dragged item follows the cursor:
function getItemStyles(currentOffset: XYCoord | null): React.CSSProperties {
if (currentOffset == null) {
return {
display: 'none',
}
}
const { x, y } = currentOffset
return {
display: 'inline-block',
transform: `translate(${x}px, ${y}px)`,
filter: 'drop-shadow(0 2px 12px rgba(0,0,0,0.45))',
}
}
Transform Translation
- Uses CSS transform for smooth, GPU-accelerated movement
- Directly follows mouse coordinates from react-dnd
- Hidden when currentOffset is null
Visual Effects
- Drop shadow: 2px offset, 12px blur, 45% opacity black
- Rounded corners: Applied via className
- Themed background: Uses 'bg-theme' class
Rendering Drag Items
Directory Preview
{artifact instanceof ModelDirectory && (
<FileExplorer.Container
key={artifact.path}
artifact={artifact}
className="bg-theme"
>
<Directory.Icons hasChevron={false} />
<Directory.Display directory={artifact} />
</FileExplorer.Container>
)}
Features:
- No chevron icon (hasChevron={false})
- Shows directory icon and name
- Wrapped in FileExplorer.Container
File Preview
{artifact instanceof ModelFile && (
<FileExplorer.Container
key={artifact.path}
artifact={artifact}
className="bg-theme"
>
<File.Icons />
<File.Display file={artifact} />
</FileExplorer.Container>
)}
Features:
- Shows file type icon
- Shows file name
- Wrapped in FileExplorer.Container
Component Structure
return (
<>
{isDragging && (
<div style={layerStyles}>
<div
style={getItemStyles(currentOffset)}
className="!cursor-grabbing !rounded-lg overflow-hidden"
>
{artifacts.map(artifact => (
<span key={artifact.id}>
{/* Directory or File preview */}
</span>
))}
</div>
</div>
)}
</>
)
Conditional Rendering
- Outer layer only renders when isDragging is true
- Inner previews map over artifacts array
- Each artifact keyed by unique ID
Cursor Style
- cursor-grabbing: Shows closed hand cursor during drag
- Uses !important override to ensure visibility
Performance Optimization
The component uses useMemo for artifacts calculation:
const artifacts = useMemo(
() =>
Array.from(
inActiveRange(artifact) ? activeRange : new Set([artifact]),
).filter(Boolean),
[activeRange, artifact],
)
This prevents unnecessary recalculation on every render.
Integration Points
The component integrates with:
- react-dnd: Drag layer monitoring
- Project context: Active range and selection state
- FileExplorer.Container: Consistent item styling
- Directory and File components: Icon and display rendering
Usage Example
import DragLayer from '@components/fileExplorer/DragLayer'
import { DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
function FileExplorerApp() {
return (
<DndProvider backend={HTML5Backend}>
<FileExplorer>
{/* File tree content */}
</FileExplorer>
{/* Drag layer renders at root level */}
<DragLayer />
</DndProvider>
)
}
Styling Classes
Applied classes:
- !cursor-grabbing: Override cursor to grabbing
- !rounded-lg: Large border radius (override)
- overflow-hidden: Clip content to rounded corners
- bg-theme: Themed background color
The ! prefix forces override of conflicting styles.