Implementation:TobikoData Sqlmesh FileExplorer Directory
| Knowledge Sources | |
|---|---|
| Domains | Web_UI, File_Management |
| Last Updated | 2026-02-07 20:00 GMT |
Overview
Concrete tool for rendering collapsible directory components with drag-and-drop support in the SQLMesh web client file explorer.
Description
This module provides the Directory component that renders a tree view of directories in the file explorer. It supports drag-and-drop for moving files/directories, context menus for file operations, multi-selection with Shift/Cmd modifiers, expand/collapse functionality, and rename operations. The component integrates with React DnD for drag operations and uses the FileExplorer context for state management.
Key features include:
- Recursive directory rendering with proper nesting and indentation
- Drag-and-drop with visual feedback (opacity, background color)
- Long-press detection (50ms) to enable dragging on touch devices
- Context menu with operations: Expand/Collapse, New File, New Folder, Rename, Remove
- Range selection with Shift key for multi-select
- Multi-directory operations (expand all, collapse all, toggle all)
- Drop validation preventing invalid moves (parent to child, self drops)
- Auto-expansion when files are dropped onto closed directories
Usage
This component is used recursively by the FileExplorer to render the project's directory structure. Users interact with it through clicks, context menus, and drag operations. The component manages its own open/closed state while coordinating with the global file explorer context.
Code Reference
Source Location
- Repository: TobikoData_Sqlmesh
- File: web/client/src/library/components/fileExplorer/Directory.tsx
Signature
function Directory({
directory,
className,
style,
}: {
directory: ModelDirectory
className?: string
style?: React.CSSProperties
}): JSX.Element
// Sub-components
function DirectoryDisplay({ directory }: { directory: ModelDirectory }): JSX.Element
function DirectoryIcons({
hasChevron = true,
hasFolder = true,
isOpen = false,
className,
}: {
isOpen?: boolean
hasChevron?: boolean
hasFolder?: boolean
className?: string
}): JSX.Element
// Exported as
Directory.Icons = DirectoryIcons
Directory.Display = DirectoryDisplay
Import
import Directory from '@components/fileExplorer/Directory'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| directory | ModelDirectory | Yes | The directory model to render |
| className | string | No | Additional CSS classes |
| style | React.CSSProperties | No | Inline styles (used for indentation) |
Outputs
| Name | Type | Description |
|---|---|---|
| rendered | JSX.Element | The directory tree with interactive controls |
Usage Examples
import Directory from '@components/fileExplorer/Directory'
import { ModelDirectory } from '~/models/directory'
// Example 1: Basic directory rendering
function FileTree({ root }: { root: ModelDirectory }) {
return (
<div className="file-tree">
<Directory directory={root} />
</div>
)
}
// Example 2: Directory with custom indentation
function NestedDirectory({ dir, level }: { dir: ModelDirectory, level: number }) {
return (
<Directory
directory={dir}
style={{ paddingLeft: `${level * 0.75}rem` }}
/>
)
}
// Example: User Interactions
// 1. Click to expand/collapse
// - Single click on directory
// - Directory.toggle() called
// - Updates isOpen state
// - Shows/hides children
// 2. Multi-select with Shift
// - User clicks Directory A
// - Holds Shift and clicks Directory C
// - selectArtifactsInRange(C) called
// - All directories between A and C selected
// - Background highlighted
// 3. Multi-select with Cmd/Meta
// - User clicks Directory A (selected)
// - Holds Cmd and clicks Directory B
// - Both A and B now in activeRange
// - Cmd+click on B again removes it from selection
// 4. Drag and drop
// - User long-presses directory (50ms)
// - isDraggable set to true
// - Drag starts, opacity changes to 50%
// - Drop on another directory
// - moveArtifacts called
// - Directory moved to new parent
// 5. Context menu - New File
// - Right-click on directory
// - Select "New File"
// - createFile(directory) called
// - API creates file with unique name
// - Directory expands to show new file
// 6. Context menu - Rename
// - Right-click directory
// - Select "Rename"
// - Input field appears inline
// - User types new name and presses Enter
// - renameArtifact called
// - API updates directory path
// 7. Context menu - Remove multiple
// - Select 3 directories (Shift+click)
// - Right-click on one
// - Select "Remove 3"
// - Confirmation dialog appears
// - User confirms
// - removeArtifacts(activeRange) called
// 8. Drop validation
// - Cannot drop directory onto itself
// - Cannot drop parent onto its own child
// - Cannot drop if already in target directory
// - Visual feedback: isOver only true if canDrop
// 9. Expand all in selection
// - Select multiple directories
// - Right-click
// - "Expand All" appears if all closed
// - Recursively expands all selected directories