diff --git a/docs/plans/2026-02-03-continuation-modal-ux.md b/docs/plans/2026-02-03-continuation-modal-ux.md new file mode 100644 index 00000000..fd322b78 --- /dev/null +++ b/docs/plans/2026-02-03-continuation-modal-ux.md @@ -0,0 +1,39 @@ +# Continuation Modal UX Improvements + +**Date:** 2026-02-03 +**Status:** Approved + +## Changes + +### 1. Parent option labels: hover tooltips instead of static headers + +The ContinuationModal currently groups descendant nodes under uppercase headers like "FROM: PRINTER WON'T PRINT AT ALL -> NOTHING HAPPENS / NO RESPONSE". These clutter the screen. + +**Change:** Move `parentOptionLabel` from static section headers to a `title` attribute on each descendant button. The descendants become a flat list. Hovering shows the path context as a native browser tooltip. + +The "Or" divider and "Build Custom Branch" button at the bottom remain unchanged. + +**Files:** `frontend/src/components/session/ContinuationModal.tsx` + +### 2. Land on custom step before navigating to selected descendant + +Currently, selecting a descendant in the ContinuationModal navigates directly to that node. The user should land on their custom step first to write notes, then proceed. + +**Change:** Add `pendingContinuationNodeId` state to `TreeNavigationPage`. When the user selects a descendant: + +1. Store the selected node ID in `pendingContinuationNodeId` +2. Close the ContinuationModal (user is now viewing their custom step) +3. Render a "Continue to: [node name]" button on the custom step view +4. Clicking it navigates to the descendant and clears `pendingContinuationNodeId` + +The "Continue to" button and custom branch controls are mutually exclusive. If the user chose "Build Custom Branch", they get the existing Add Another Step / This Solves My Issue controls instead. + +**Files:** `frontend/src/pages/TreeNavigationPage.tsx` + +## Summary of state changes + +| State | Purpose | +|-------|---------| +| `pendingContinuationNodeId` | Stores which descendant the user selected, so the custom step can show a "Continue to" button | + +## No backend changes required diff --git a/frontend/src/components/session/ContinuationModal.tsx b/frontend/src/components/session/ContinuationModal.tsx index 2b13b002..64354ad0 100644 --- a/frontend/src/components/session/ContinuationModal.tsx +++ b/frontend/src/components/session/ContinuationModal.tsx @@ -37,15 +37,6 @@ export function ContinuationModal({ onSelectNode, onBuildCustomBranch }: ContinuationModalProps) { - // Group nodes by parent option - const groupedNodes = descendantNodes.reduce((acc, node) => { - if (!acc[node.parentOptionLabel]) { - acc[node.parentOptionLabel] = [] - } - acc[node.parentOptionLabel].push(node) - return acc - }, {} as Record) - const hasDescendants = descendantNodes.length > 0 return ( @@ -58,36 +49,28 @@ export function ContinuationModal({ Select the next step in your troubleshooting path:

-
- {Object.entries(groupedNodes).map(([parentOption, nodes]) => ( -
-

- From: {parentOption} -

-
- {nodes.map(node => ( - - ))} +
+ {descendantNodes.map(node => ( +
+
+

{node.label}

+

+ {nodeTypeLabels[node.type]} +

+
+ + ))}
diff --git a/frontend/src/pages/TreeNavigationPage.tsx b/frontend/src/pages/TreeNavigationPage.tsx index d02f5922..aacd3820 100644 --- a/frontend/src/pages/TreeNavigationPage.tsx +++ b/frontend/src/pages/TreeNavigationPage.tsx @@ -8,7 +8,7 @@ import { cn } from '@/lib/utils' import { MarkdownContent } from '@/components/ui/MarkdownContent' import { CustomStepModal } from '@/components/step-library/CustomStepModal' import { PostStepActionModal, ContinuationModal, ForkTreeModal, type DescendantNode } from '@/components/session' -import { Plus, CheckCircle } from 'lucide-react' +import { Plus, CheckCircle, ArrowRight } from 'lucide-react' interface LocationState { sessionId?: string @@ -48,6 +48,7 @@ export function TreeNavigationPage() { // Continuation flow const [showContinuationModal, setShowContinuationModal] = useState(false) const [branchOriginNodeId, setBranchOriginNodeId] = useState(null) + const [pendingContinuationNodeId, setPendingContinuationNodeId] = useState(null) // Custom branch mode const [customBranchMode, setCustomBranchMode] = useState(false) @@ -409,18 +410,26 @@ export function TreeNavigationPage() { } } - // Handle selecting a descendant node from continuation modal - const handleSelectDescendant = async (nodeId: string) => { + // Handle selecting a descendant node from continuation modal. + // Stores the selection so the user can write notes on their custom step first. + const handleSelectDescendant = (nodeId: string) => { setShowContinuationModal(false) setBranchOriginNodeId(null) + setPendingContinuationNodeId(nodeId) + } - const newPath = [...pathTaken, nodeId] + // Navigate to the previously-selected descendant node + const handleContinueToDescendant = async () => { + if (!pendingContinuationNodeId || !session) return + + const newPath = [...pathTaken, pendingContinuationNodeId] setPathTaken(newPath) - setCurrentNodeId(nodeId) + setCurrentNodeId(pendingContinuationNodeId) setNotes('') + setPendingContinuationNodeId(null) try { - await sessionsApi.update(session!.id, { path_taken: newPath }) + await sessionsApi.update(session.id, { path_taken: newPath }) } catch (err) { console.error('Failed to update session path:', err) } @@ -777,6 +786,27 @@ export function TreeNavigationPage() {
)} + {/* Continue to selected descendant */} + {pendingContinuationNodeId && !customBranchMode && (() => { + const targetNode = findNode(pendingContinuationNodeId, tree?.tree_structure) + const targetLabel = targetNode?.question || targetNode?.title || 'next step' + return ( +
+ +
+ ) + })()} + {/* Custom Branch Controls */} {customBranchMode && (