Overview
The File Explorer component provides a comprehensive solution for browsing and displaying hierarchical file structures. It features expandable folders, file content preview with syntax highlighting, image preview, search functionality, and copy-to-clipboard support.
Installation
npx shadcn@latest add https://rigidui.com/r/file-explorer.json
Usage
Basic Example
With Callbacks
Read-Only Mode
Custom Icons
import { FileExplorer } from "@/components/file-explorer";
import { FolderClosed, FolderOpen, FileCode, ImageIcon } from "lucide-react";
const fileSystem = {
id: 'root',
name: 'my-project',
type: 'folder' as const,
expanded: true,
icon: <FolderClosed className="h-4 w-4 text-blue-500" />,
expandedIcon: <FolderOpen className="h-4 w-4 text-blue-500" />,
children: [
{
id: 'src',
name: 'src',
type: 'folder' as const,
children: [
{
id: 'file1',
name: 'example.ts',
type: 'file' as const,
language: 'typescript',
content: 'console.log("Hello world!");',
icon: <FileCode className="h-4 w-4 text-green-500" />
},
{
id: 'images',
name: 'images',
type: 'folder' as const,
icon: <FolderClosed className="h-4 w-4 text-purple-500" />,
expandedIcon: <FolderOpen className="h-4 w-4 text-purple-500" />,
children: [{
id: 'logo.png',
name: 'logo.png',
type: 'file' as const,
isImage: true,
imageUrl: 'https://via.placeholder.com/300x200/3B82F6/FFFFFF?text=Logo',
content: 'Binary image data',
icon: <ImageIcon className="h-4 w-4 text-orange-500" />
}]
}
]
}
]
};
export default function MyComponent() {
return (
<FileExplorer
initialData={fileSystem}
showTitle={true}
height="400px"
className="w-full"
/>
);
}
import { FileExplorer } from "@/components/file-explorer";
import type { FileType } from "@/components/file-explorer";
export default function MyComponent() {
const handleFileSelect = (file: FileType) => {
console.log('Selected file:', file.name);
console.log('Content:', file.content);
};
const handleFolderToggle = (folderId: string, isExpanded: boolean) => {
console.log(`Folder ${folderId} is now ${isExpanded ? 'expanded' : 'collapsed'}`);
};
const handleRefresh = () => {
console.log('Refreshing file explorer...');
// Reload data from API
};
return (
<FileExplorer
initialData={fileSystem}
onFileSelect={handleFileSelect}
onFolderToggle={handleFolderToggle}
onRefresh={handleRefresh}
height="600px"
/>
);
}
import { FileExplorer } from "@/components/file-explorer";
export default function MyComponent() {
return (
<FileExplorer
initialData={fileSystem}
readOnly={true}
showTitle={true}
title="Documentation Files"
height="500px"
/>
);
}
import { FileExplorer } from "@/components/file-explorer";
import { File, Folder, FolderOpen } from "lucide-react";
export default function MyComponent() {
return (
<FileExplorer
initialData={fileSystem}
defaultFileIcon={<File className="h-4 w-4 text-gray-500" />}
defaultFolderIcon={<Folder className="h-4 w-4 text-blue-500" />}
defaultFolderOpenIcon={<FolderOpen className="h-4 w-4 text-blue-600" />}
/>
);
}
Features
The File Explorer component includes built-in error boundaries to gracefully handle any rendering errors.
- Tree Structure: Navigate through a hierarchical file system with expandable folders and files
- File Search: Quickly find files by name with an integrated search functionality
- Copy Content: Easily copy file contents to clipboard with a single click
- Syntax Highlighting: View file contents with language-specific syntax highlighting for better readability
- Image Preview: Preview images directly in the explorer with support for multiple formats
- Accessibility: Full keyboard navigation support and screen reader compatibility
- Performance Optimized: Memoized components and optimized rendering for large file structures
- Error Handling: Robust error boundaries and graceful fallbacks for better user experience
API Reference
FileExplorerProps
initialData
FolderType
default:"defaultFileSystemData"
The initial file system data structure to display. This should be the root folder containing all files and subfolders.
Additional class names for the container element.
Additional class names for the card components (file tree and content viewer).
title
string
default:"'File Explorer'"
Title displayed above the file explorer.
Whether to show the title or not.
height
string
default:"'calc(100vh-200px)'"
Height of the file explorer component. Can be any valid CSS height value.
Height of the file content display area. Useful for controlling syntax highlighter height.
Default icon to use for all files without a custom icon. Defaults to a FileText icon.
Default icon to use for closed folders without a custom icon. Defaults to a yellow Folder icon.
Default icon to use for open folders without a custom icon. Defaults to a yellow FolderOpen icon.
Callback function called when a file is selected. Receives the selected file object.
onFolderToggle
(folderId: string, isExpanded: boolean) => void
Callback function called when a folder is expanded or collapsed. Receives the folder ID and its new expanded state.
Whether the file explorer is in read-only mode. When true, disables any modification actions.
Array of allowed file extensions for filtering. For example: ['.ts', '.tsx', '.js'].
Maximum file size in bytes for validation. Files larger than this will show a warning.
Whether the component is in a loading state. Shows a loading spinner when true.
Callback function for the refresh button. When provided, a refresh button will be displayed in the toolbar.
Types
FileType
type FileType = {
id: string
name: string
type: 'file'
language?: string
content: string
icon?: React.ReactNode
isImage?: boolean
imageUrl?: string
}
FolderType
type FolderType = {
id: string
name: string
type: 'folder'
children: (FileType | FolderType)[]
expanded?: boolean
icon?: React.ReactNode
expandedIcon?: React.ReactNode
}
FileSystemItemType
type FileSystemItemType = FileType | FolderType
Advanced Usage
Lazy Loading File Contents
import { useState } from "react";
import { FileExplorer } from "@/components/file-explorer";
import type { FileType } from "@/components/file-explorer";
export default function MyComponent() {
const [fileSystem, setFileSystem] = useState(initialFileSystem);
const handleFileSelect = async (file: FileType) => {
if (!file.content) {
// Load content from API
const response = await fetch(`/api/files/${file.id}`);
const content = await response.text();
// Update file system with loaded content
setFileSystem(prevSystem => updateFileContent(prevSystem, file.id, content));
}
};
return (
<FileExplorer
initialData={fileSystem}
onFileSelect={handleFileSelect}
/>
);
}
Dynamic File System Loading
import { useState, useEffect } from "react";
import { FileExplorer } from "@/components/file-explorer";
export default function MyComponent() {
const [fileSystem, setFileSystem] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadFileSystem();
}, []);
const loadFileSystem = async () => {
setLoading(true);
try {
const response = await fetch('/api/file-system');
const data = await response.json();
setFileSystem(data);
} catch (error) {
console.error('Failed to load file system:', error);
} finally {
setLoading(false);
}
};
if (!fileSystem) {
return <div>Loading...</div>;
}
return (
<FileExplorer
initialData={fileSystem}
loading={loading}
onRefresh={loadFileSystem}
/>
);
}
Custom File Type Detection
import { FileExplorer } from "@/components/file-explorer";
import { FileJson, FileCode, FileImage } from "lucide-react";
function getFileIcon(filename: string) {
if (filename.endsWith('.json')) {
return <FileJson className="h-4 w-4 text-yellow-500" />;
}
if (filename.match(/\.(ts|tsx|js|jsx)$/)) {
return <FileCode className="h-4 w-4 text-blue-500" />;
}
if (filename.match(/\.(png|jpg|jpeg|gif|svg)$/)) {
return <FileImage className="h-4 w-4 text-green-500" />;
}
return null;
}
const fileSystemWithIcons = {
id: 'root',
name: 'project',
type: 'folder' as const,
children: files.map(file => ({
...file,
icon: getFileIcon(file.name)
}))
};
export default function MyComponent() {
return <FileExplorer initialData={fileSystemWithIcons} />;
}
The File Explorer automatically detects image files by extension (.jpg, .jpeg, .png, .gif, .bmp, .webp, .svg, .ico) and displays them in an image viewer instead of a code editor.
Keyboard Navigation
The File Explorer supports full keyboard navigation:
- Enter/Space: Select file or toggle folder
- Arrow Right: Expand collapsed folder
- Arrow Left: Collapse expanded folder
- Tab: Navigate between interactive elements
Large file structures with hundreds of files may impact performance. Consider implementing lazy loading or pagination for very large directory trees.
Accessibility
The component implements ARIA attributes for screen reader support:
role="tree" for the file tree
role="treeitem" for each file and folder
aria-expanded for folder state
aria-selected for selected files
- Proper focus management for keyboard navigation