Improve tree editor modal UX: cancel/save and inline node naming

Change 1: Add Cancel button and defer saving until Done is clicked
- NodeEditorModal now uses local draft state instead of updating store directly
- Cancel button discards changes; Done button commits to store
- If editing a brand new node, Cancel deletes it entirely
- NodeList tracks isEditingNewNode to pass to modal

Change 2: Inline node naming when creating from NodePicker dropdown
- Selecting "+ New Decision/Action/Solution" shows inline title input
- User enters title before node is created (Enter to create, Escape to cancel)
- Node appears in dropdown with human-readable title immediately

Change 3: Improved dropdown labels
- Format changed from "UUID (UUID...)" to "Title (UUID...)"
- Untitled nodes show "Untitled Question" or "Untitled {type}"
- Root node shows "Root Question (root)" when empty

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-01-30 01:01:23 -05:00
parent adcaf2f4fe
commit 1d5ba598ca
4 changed files with 244 additions and 81 deletions

View File

@@ -657,16 +657,32 @@ export const useTreeEditorStore = create<TreeEditorState>()(
.filter(id => id !== excludeNodeId)
.map(id => {
const node = findNodeInTree(id, state.treeStructure)
let label = id
let type: NodeType = 'decision'
let title = ''
if (node) {
type = node.type
if (node.question) label = node.question.slice(0, 50)
else if (node.title) label = node.title.slice(0, 50)
if (node.question) title = node.question.slice(0, 50)
else if (node.title) title = node.title.slice(0, 50)
}
// Use short ID format, but 'root' stays as-is
const shortId = id === 'root' ? 'root' : id.slice(0, 8) + '...'
return { id, label: `${label} (${shortId})`, type }
// Format: "Title (shortId)" or just "(shortId)" if no title
// For root without a question, show "Root Question (root)"
let label: string
if (id === 'root') {
label = title ? `${title} (root)` : 'Root Question (root)'
} else if (title) {
label = `${title} (${shortId})`
} else {
// No title yet - show placeholder with ID
const typeName = type === 'decision' ? 'Untitled Question' : `Untitled ${type}`
label = `${typeName} (${shortId})`
}
return { id, label, type }
})
}
})),