Rob Koch commited on
Commit
eb36ec6
·
1 Parent(s): 12e1c1a

basic context menu for folders

Browse files
app/components/workbench/FileTree.tsx CHANGED
@@ -2,6 +2,7 @@ import { memo, useEffect, useMemo, useState, type ReactNode } from 'react';
2
  import type { FileMap } from '~/lib/stores/files';
3
  import { classNames } from '~/utils/classNames';
4
  import { createScopedLogger, renderLogger } from '~/utils/logger';
 
5
 
6
  const logger = createScopedLogger('FileTree');
7
 
@@ -159,23 +160,65 @@ interface FolderProps {
159
  onClick: () => void;
160
  }
161
 
162
- function Folder({ folder: { depth, name }, collapsed, selected = false, onClick }: FolderProps) {
 
 
 
 
163
  return (
164
- <NodeButton
165
- className={classNames('group', {
166
- 'bg-transparent text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive hover:bg-bolt-elements-item-backgroundActive':
167
- !selected,
168
- 'bg-bolt-elements-item-backgroundAccent text-bolt-elements-item-contentAccent': selected,
169
- })}
170
- depth={depth}
171
- iconClasses={classNames({
172
- 'i-ph:caret-right scale-98': collapsed,
173
- 'i-ph:caret-down scale-98': !collapsed,
174
- })}
175
- onClick={onClick}
176
- >
177
- {name}
178
- </NodeButton>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  );
180
  }
181
 
 
2
  import type { FileMap } from '~/lib/stores/files';
3
  import { classNames } from '~/utils/classNames';
4
  import { createScopedLogger, renderLogger } from '~/utils/logger';
5
+ import * as ContextMenu from '@radix-ui/react-context-menu';
6
 
7
  const logger = createScopedLogger('FileTree');
8
 
 
160
  onClick: () => void;
161
  }
162
 
163
+ interface FolderContextMenuProps {
164
+ children: ReactNode;
165
+ }
166
+
167
+ function ContextMenuItem({ children }: { children: ReactNode }) {
168
  return (
169
+ <ContextMenu.Item className="flex items-center gap-2 px-2 py-1.5 outline-0 text-sm text-bolt-elements-textPrimary cursor-pointer ws-nowrap text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive hover:bg-bolt-elements-item-backgroundActive rounded-md">
170
+ <span className="size-4 shrink-0"></span>
171
+ <span>{children}</span>
172
+ </ContextMenu.Item>
173
+ );
174
+ }
175
+
176
+ function FolderContextMenu({ children }: FolderContextMenuProps) {
177
+ return (
178
+ <ContextMenu.Root>
179
+ <ContextMenu.Trigger>{children}</ContextMenu.Trigger>
180
+ <ContextMenu.Portal>
181
+ <ContextMenu.Content
182
+ style={{ zIndex: 998 }}
183
+ className="border border-bolt-elements-borderColor rounded-md z-context-menu bg-bolt-elements-background-depth-1 dark:bg-bolt-elements-background-depth-2 data-[state=open]:animate-in animate-duration-100 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-98 w-56"
184
+ >
185
+ <ContextMenu.Group className="p-1 border-b-px border-solid border-bolt-elements-borderColor">
186
+ <ContextMenuItem>New file...</ContextMenuItem>
187
+ <ContextMenuItem>New folder...</ContextMenuItem>
188
+ </ContextMenu.Group>
189
+ <ContextMenu.Group className="p-1 border-b-px border-solid border-bolt-elements-borderColor">
190
+ <ContextMenuItem>Copy path</ContextMenuItem>
191
+ <ContextMenuItem>Copy relative path</ContextMenuItem>
192
+ </ContextMenu.Group>
193
+ <ContextMenu.Group className="p-1 border-b-px border-solid border-bolt-elements-borderColor">
194
+ <ContextMenuItem>Rename...</ContextMenuItem>
195
+ <ContextMenuItem>Delete</ContextMenuItem>
196
+ </ContextMenu.Group>
197
+ </ContextMenu.Content>
198
+ </ContextMenu.Portal>
199
+ </ContextMenu.Root>
200
+ );
201
+ }
202
+
203
+ function Folder({ folder, collapsed, selected = false, onClick }: FolderProps) {
204
+ return (
205
+ <FolderContextMenu>
206
+ <NodeButton
207
+ className={classNames('group', {
208
+ 'bg-transparent text-bolt-elements-item-contentDefault hover:text-bolt-elements-item-contentActive hover:bg-bolt-elements-item-backgroundActive':
209
+ !selected,
210
+ 'bg-bolt-elements-item-backgroundAccent text-bolt-elements-item-contentAccent': selected,
211
+ })}
212
+ depth={folder.depth}
213
+ iconClasses={classNames({
214
+ 'i-ph:caret-right scale-98': collapsed,
215
+ 'i-ph:caret-down scale-98': !collapsed,
216
+ })}
217
+ onClick={onClick}
218
+ >
219
+ {folder.name}
220
+ </NodeButton>
221
+ </FolderContextMenu>
222
  );
223
  }
224
 
package.json CHANGED
@@ -57,6 +57,7 @@
57
  "@octokit/rest": "^21.0.2",
58
  "@octokit/types": "^13.6.2",
59
  "@openrouter/ai-sdk-provider": "^0.0.5",
 
60
  "@radix-ui/react-dialog": "^1.1.2",
61
  "@radix-ui/react-dropdown-menu": "^2.1.2",
62
  "@radix-ui/react-separator": "^1.1.0",
 
57
  "@octokit/rest": "^21.0.2",
58
  "@octokit/types": "^13.6.2",
59
  "@openrouter/ai-sdk-provider": "^0.0.5",
60
+ "@radix-ui/react-context-menu": "^2.2.2",
61
  "@radix-ui/react-dialog": "^1.1.2",
62
  "@radix-ui/react-dropdown-menu": "^2.1.2",
63
  "@radix-ui/react-separator": "^1.1.0",