File Explorer
The FileExplorer component is used to display file and folder hierarchies in a collapsible/expandable structure. It supports features like active states, links, nested levels, and tooltips.
Variations
Basic file explorer
Create a simple file explorer with folders and files. The explorer automatically handles expand/collapse interactions.
Nested folders
You can nest folders within folders to create deep hierarchies.
Active file
Highlight the currently active file or folder using the isActive prop.
Links
Make files and folders navigable by providing the link prop.
Tooltips
Add tooltips to files for additional information.
Active folder
You can also highlight folders using the isActive prop.
Full project structure
This comprehensive example demonstrates all features of the FileExplorer component including:
- Multiple nested folder levels
- Active file highlighting
- Links for navigation
- Tooltips for additional context
- Mixed file and folder structures
- Click handlers for file selection
Custom content
The FileExplorer.CustomItem component allows you to add custom, non-interactive content to your file explorer. Use it when you need to display informational content, placeholders, or any custom elements that don’t require file/folder interactive behavior.
Installation
import { FileExplorer } from '@harnessio/ui/components'
//...
const [expandedFolders, setExpandedFolders] = useState(['src']);
return ( <FileExplorer.Root value={expandedFolders} onValueChange={setExpandedFolders}> <FileExplorer.FolderItem value="src" level={0} content={ <FileExplorer.Root value={expandedFolders} onValueChange={setExpandedFolders}> <FileExplorer.FileItem level={1}>index.ts</FileExplorer.FileItem> <FileExplorer.FileItem level={1}>App.tsx</FileExplorer.FileItem> {/* Use CustomItem for custom non-interactive content */} <FileExplorer.CustomItem className="text-cn-3 pl-cn-lg"> 2 files total </FileExplorer.CustomItem> </FileExplorer.Root> } > src </FileExplorer.FolderItem> </FileExplorer.Root>)Anatomy
FileExplorer is a compound component built on top of the Accordion primitive. You compose a tree by nesting a Root inside each folder’s content.
<FileExplorer.Root value={expanded} onValueChange={setExpanded}> <FileExplorer.FolderItem value="src" level={0} content={ <FileExplorer.Root value={expanded} onValueChange={setExpanded}> <FileExplorer.FileItem level={1}>index.ts</FileExplorer.FileItem> <FileExplorer.CustomItem>2 files total</FileExplorer.CustomItem> </FileExplorer.Root> } > src </FileExplorer.FolderItem></FileExplorer.Root>- Root — an accordion (
type="multiple") whosevalueis the array of expanded folder ids andonValueChangeupdates it. Every level of the tree is its ownRoot, wrapping the children of the folder above. - FolderItem — a folder row: an expand/collapse trigger plus a folder icon and label. Its
content(usually a nestedRoot) renders when the folder’svalueis in the expanded list. Folders can be links and can show an active state. - FileItem — a leaf row rendered as a button (or a link when
linkis set), with a file icon and label. It supportsisActive,onClick, atooltip, andactionButtonsshown at the end of the row. - CustomItem — a non-interactive wrapper for arbitrary content (counts, hints, empty states) that should sit in the tree without file/folder behavior.
- level — every item takes a
levelnumber that sets its indentation. Folders start at0; files directly under a root folder start at1, incrementing by one per nesting level.
Best practices
Do
- Keep
levelconsistent with the nesting depth so indentation matches the hierarchy — folders from0, their files from1, and so on. - Give each
FolderItema uniquevalue; it’s the key the accordion uses to track expand/collapse state. - Track the active file in your own state and pass
isActiveso the current selection stays highlighted. - Use
CustomItemfor supplementary, non-interactive rows rather than styling aFileItemyou don’t want to be clickable.
Don’t
- Don’t rely on tooltips to carry essential information — treat them as supplementary context on top of a clear file name.
- Don’t render very large trees eagerly if you can avoid it; consider memoizing rows or loading folder contents on expand.
Content
- Show real file and folder names; they’re the primary way people scan a tree.
- Keep tooltips short — a phrase describing the file’s purpose (“Main configuration file”), not a sentence.
Accessibility
The tree is built on the Accordion primitive, so folders come with the accordion’s expand/collapse semantics, and rows are real buttons or links.
Keyboard
- Folder triggers are buttons: Enter or Space expands and collapses them. Tab / Shift+Tab move between the interactive rows.
- File items are buttons (or links when
linkis set), so they’re focusable and activate with Enter.
Labeling
- Each row shows an icon plus its label; the label text is what’s announced. Tooltips add supplementary context on hover and focus.
- Action buttons on a row are Buttons — give icon-only ones a title or accessible label so their purpose is announced.
Focus & states
- The active row is highlighted via
isActive; keep it in sync with your selection state so the highlight and focus tell the same story.
Known limitations
- Expansion is fully controlled. The tree doesn’t track its own open state — you own the
valuearray and must update it fromonValueChange, or folders won’t expand.
Properties
Root
Prop | Required | Default | Type |
|---|---|---|---|
| value | true | string[] | |
| onValueChange | true | (value: string | string[]) => void | |
| children | true | React.ReactNode |
FolderItem
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | React.ReactNode | |
| level | true | number | |
| value | false | '' | string |
| isActive | false | boolean | |
| content | false | React.ReactNode | |
| link | false | string | |
| icon | false | 'folder' | IconV2NamesType |
| onClick | false | (value: string) => void |
FileItem
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | React.ReactNode | |
| level | true | number | |
| isActive | false | boolean | |
| link | false | string | |
| onClick | false | (value: string) => void | |
| tooltip | false | React.ReactNode | |
| actionButtons | false | ActionButton[] |
CustomItem
The FileExplorer.CustomItem component is a simple wrapper for custom, non-interactive content within the file explorer structure. Use it when you need full control over the content and styling without the standard file/folder behavior.
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | React.ReactNode | |
| className | false | string | |
| ref | false | React.Ref<HTMLDivElement> |