Fix file tree clicks and redesign add-file UI on instructions tab
- Add onClick handler to file row div in PackageFileTree so clicks anywhere on the row select the file (not just the inner button) - Replace "Add" button with compact "+" icon that reveals an inline input with Create/Cancel actions - Hide file name input until "+" is clicked to reduce visual clutter - Validate new file paths: reject ".." path traversal segments - Change placeholder from "docs/TOOLS.md" to "TOOLS.md" Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -286,6 +286,7 @@ export function PackageFileTree({
|
||||
style={{
|
||||
paddingInlineStart: `${TREE_BASE_INDENT + depth * TREE_STEP_INDENT - 8}px`,
|
||||
}}
|
||||
onClick={() => onSelectFile(node.path)}
|
||||
>
|
||||
{showCheckboxes && (
|
||||
<label className="flex items-center pl-2">
|
||||
|
||||
@@ -1514,6 +1514,7 @@ function PromptsTab({
|
||||
entryFile: string;
|
||||
} | null>(null);
|
||||
const [newFilePath, setNewFilePath] = useState("");
|
||||
const [showNewFileInput, setShowNewFileInput] = useState(false);
|
||||
const [expandedDirs, setExpandedDirs] = useState<Set<string>>(new Set());
|
||||
const [filePanelWidth, setFilePanelWidth] = useState(260);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -1960,30 +1961,66 @@ function PromptsTab({
|
||||
<div className="border border-border rounded-lg p-3 space-y-3 shrink-0" style={{ width: filePanelWidth }}>
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="text-sm font-medium">Files</h4>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
const candidate = newFilePath.trim();
|
||||
if (!candidate) return;
|
||||
setSelectedFile(candidate);
|
||||
setDraft("");
|
||||
setNewFilePath("");
|
||||
}}
|
||||
disabled={!newFilePath.trim()}
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
value={newFilePath}
|
||||
onChange={(event) => setNewFilePath(event.target.value)}
|
||||
placeholder="docs/TOOLS.md"
|
||||
className="font-mono text-sm"
|
||||
/>
|
||||
{!showNewFileInput && (
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-7 w-7"
|
||||
onClick={() => setShowNewFileInput(true)}
|
||||
>
|
||||
+
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{showNewFileInput && (
|
||||
<div className="space-y-2">
|
||||
<Input
|
||||
value={newFilePath}
|
||||
onChange={(event) => setNewFilePath(event.target.value)}
|
||||
placeholder="TOOLS.md"
|
||||
className="font-mono text-sm"
|
||||
autoFocus
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Escape") {
|
||||
setShowNewFileInput(false);
|
||||
setNewFilePath("");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="default"
|
||||
className="flex-1"
|
||||
disabled={!newFilePath.trim() || newFilePath.includes("..")}
|
||||
onClick={() => {
|
||||
const candidate = newFilePath.trim();
|
||||
if (!candidate || candidate.includes("..")) return;
|
||||
setSelectedFile(candidate);
|
||||
setDraft("");
|
||||
setNewFilePath("");
|
||||
setShowNewFileInput(false);
|
||||
}}
|
||||
>
|
||||
Create
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="flex-1"
|
||||
onClick={() => {
|
||||
setShowNewFileInput(false);
|
||||
setNewFilePath("");
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<PackageFileTree
|
||||
nodes={fileTree}
|
||||
selectedFile={selectedOrEntryFile}
|
||||
|
||||
Reference in New Issue
Block a user