diff --git a/src/renderer/components/Editor/Editor.css b/src/renderer/components/Editor/Editor.css index 6a0265b..32afc8e 100644 --- a/src/renderer/components/Editor/Editor.css +++ b/src/renderer/components/Editor/Editor.css @@ -196,6 +196,24 @@ color: var(--accent); } +.annotation-tooltip-dismiss { + float: right; + background: transparent; + border: none; + color: var(--text-muted); + font-size: 14px; + line-height: 1; + padding: 0 0 0 8px; + cursor: pointer; + opacity: 0.6; + transition: opacity 0.15s, color 0.15s; +} + +.annotation-tooltip-dismiss:hover { + opacity: 1; + color: var(--text-primary); +} + .annotation-tooltip-body { color: var(--text-primary); word-break: break-word; diff --git a/src/renderer/components/Editor/MarkdownEditor.tsx b/src/renderer/components/Editor/MarkdownEditor.tsx index 2a2ede5..8c74b41 100644 --- a/src/renderer/components/Editor/MarkdownEditor.tsx +++ b/src/renderer/components/Editor/MarkdownEditor.tsx @@ -217,6 +217,14 @@ const annotationHoverTooltip = hoverTooltip( label.className = 'annotation-tooltip-label' label.textContent = 'Your comment' dom.appendChild(label) + const dismissBtn = document.createElement('button') + dismissBtn.className = 'annotation-tooltip-dismiss' + dismissBtn.title = 'Dismiss' + dismissBtn.textContent = '×' + dismissBtn.addEventListener('click', () => { + useEditorStore.getState().removeAnnotation(ann.id) + }) + dom.appendChild(dismissBtn) const divider = document.createElement('div') divider.className = 'annotation-tooltip-divider' dom.appendChild(divider) @@ -241,6 +249,15 @@ const annotationHoverTooltip = hoverTooltip( label.textContent = ann.type.replace(/_/g, ' ') dom.appendChild(label) + const dismissBtn = document.createElement('button') + dismissBtn.className = 'annotation-tooltip-dismiss' + dismissBtn.title = 'Dismiss' + dismissBtn.textContent = '×' + dismissBtn.addEventListener('click', () => { + useEditorStore.getState().removeAnnotation(ann.id) + }) + dom.appendChild(dismissBtn) + const divider = document.createElement('div') divider.className = 'annotation-tooltip-divider' dom.appendChild(divider) diff --git a/src/renderer/components/FileTree/FileTree.css b/src/renderer/components/FileTree/FileTree.css index 03504bf..0ef6a12 100644 --- a/src/renderer/components/FileTree/FileTree.css +++ b/src/renderer/components/FileTree/FileTree.css @@ -18,6 +18,29 @@ text-transform: uppercase; } +.file-tree-header-actions { + display: flex; + align-items: center; + gap: 2px; +} + +.file-tree-action-btn { + background: none; + border: none; + cursor: pointer; + font-size: 15px; + line-height: 1; + padding: 0 3px; + opacity: 0.55; + transition: opacity 0.15s; + flex-shrink: 0; + color: var(--text-muted); +} + +.file-tree-action-btn:hover { + opacity: 1; +} + .file-tree-bible-btn { background: none; border: none; diff --git a/src/renderer/components/FileTree/FileTree.tsx b/src/renderer/components/FileTree/FileTree.tsx index e3e3e9f..b0561e6 100644 --- a/src/renderer/components/FileTree/FileTree.tsx +++ b/src/renderer/components/FileTree/FileTree.tsx @@ -1,10 +1,43 @@ +import { useState } from 'react' import { useEditorStore } from '../../store/editorStore' import { currentEditorView } from '../Editor/MarkdownEditor' import { FileTreeNode } from './FileTreeNode' +import { ContextMenu } from './ContextMenu' +import type { MenuItem } from './ContextMenu' import './FileTree.css' export function FileTree(): JSX.Element { - const { fileTree, activeFilePath, setActiveFile, markSaved } = useEditorStore() + const { fileTree, activeFilePath, setActiveFile, markSaved, setFileTree } = useEditorStore() + const [creatingRoot, setCreatingRoot] = useState<'file' | 'dir' | null>(null) + const [createRootValue, setCreateRootValue] = useState('') + const [rootMenuPos, setRootMenuPos] = useState<{ x: number; y: number } | null>(null) + + const rootMenuItems: MenuItem[] = [ + { label: 'New File', action: () => { setCreatingRoot('file'); setCreateRootValue('') } }, + { label: 'New Folder', action: () => { setCreatingRoot('dir'); setCreateRootValue('') } }, + ] + + async function refreshTree(): Promise { + const tree = await window.api.listFiles() + setFileTree(tree) + } + + async function submitCreateRoot(): Promise { + const trimmed = createRootValue.trim() + setCreatingRoot(null) + setCreateRootValue('') + if (!trimmed) return + try { + if (creatingRoot === 'file') { + await window.api.createFile('__root__', trimmed) + } else { + await window.api.createDir('__root__', trimmed) + } + await refreshTree() + } catch (err) { + console.error('Create at root failed:', err) + } + } const handleOpenStoryBible = async (): Promise => { try { @@ -31,15 +64,48 @@ export function FileTree(): JSX.Element { ) }