11import { useFile } from "@/context/file"
22import { encodeFilePath } from "@/context/file/path"
3+ import { useLanguage } from "@/context/language"
34import { Collapsible } from "@opencode-ai/ui/collapsible"
5+ import { ContextMenu } from "@opencode-ai/ui/context-menu"
46import { FileIcon } from "@opencode-ai/ui/file-icon"
57import { Icon } from "@opencode-ai/ui/icon"
68import {
@@ -108,9 +110,7 @@ const withFileDragImage = (event: DragEvent) => {
108110}
109111
110112const FileTreeNode = (
111- p : ParentProps &
112- ComponentProps < "div" > &
113- ComponentProps < "button" > & {
113+ p : ParentProps & {
114114 node : FileNode
115115 level : number
116116 active ?: string
@@ -119,8 +119,13 @@ const FileTreeNode = (
119119 kinds ?: ReadonlyMap < string , Kind >
120120 marks ?: Set < string >
121121 as ?: "div" | "button"
122+ type ?: "button"
123+ onClick ?: ( e : MouseEvent ) => void
124+ class ?: string
125+ classList ?: Record < string , boolean | undefined >
122126 } ,
123127) => {
128+ const language = useLanguage ( )
124129 const [ local , rest ] = splitProps ( p , [
125130 "node" ,
126131 "level" ,
@@ -142,9 +147,18 @@ const FileTreeNode = (
142147 return kindTextColor ( value )
143148 }
144149
150+ const handleCopyAbsolutePath = ( ) => {
151+ navigator . clipboard . writeText ( local . node . absolute ) . catch ( ( ) => { } )
152+ }
153+
154+ const handleCopyRelativePath = ( ) => {
155+ navigator . clipboard . writeText ( local . node . path ) . catch ( ( ) => { } )
156+ }
157+
145158 return (
146- < Dynamic
147- component = { local . as ?? "div" }
159+ < ContextMenu modal = { false } preventScroll = { true } >
160+ < ContextMenu . Trigger
161+ as = { local . as ?? "div" }
148162 classList = { {
149163 "w-full min-w-0 h-6 flex items-center justify-start gap-x-1.5 rounded-md px-1.5 py-0 text-left hover:bg-surface-raised-base-hover active:bg-surface-base-active transition-colors cursor-pointer" : true ,
150164 "bg-surface-base-active" : local . node . path === local . active ,
@@ -186,7 +200,18 @@ const FileTreeNode = (
186200 }
187201 return < div class = "shrink-0 size-1.5 mr-1.5 rounded-full" style = { kindDotColor ( value ) } />
188202 } ) ( ) }
189- </ Dynamic >
203+ </ ContextMenu . Trigger >
204+ < ContextMenu . Portal >
205+ < ContextMenu . Content >
206+ < ContextMenu . Item onSelect = { handleCopyAbsolutePath } >
207+ < ContextMenu . ItemLabel > { language . t ( "filetree.contextMenu.copyPath" ) } </ ContextMenu . ItemLabel >
208+ </ ContextMenu . Item >
209+ < ContextMenu . Item onSelect = { handleCopyRelativePath } >
210+ < ContextMenu . ItemLabel > { language . t ( "filetree.contextMenu.copyRelativePath" ) } </ ContextMenu . ItemLabel >
211+ </ ContextMenu . Item >
212+ </ ContextMenu . Content >
213+ </ ContextMenu . Portal >
214+ </ ContextMenu >
190215 )
191216}
192217
0 commit comments