Files
resolutionflow/docs/archive/2026-02-13-ux-improvements-implementation.md
chihlasm 350c977eda feat: add procedural flows with intake forms, navigation, and seed templates
Adds a new "procedural" tree type for linear step-by-step project workflows
(domain controller setup, M365 onboarding, VPN config, etc). Includes intake
form builder, two-panel step navigation, variable resolution, procedural
exports, 3 seed templates, and UI rename from "Trees" to "Flows".

Also archives 19 implemented plan docs and creates deferred features backlog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 04:13:52 -05:00

8.6 KiB

UX Improvements — Implementation Plan (Merged)

Context

Five frontend UX improvements for tree navigation, my-trees, and app layout. Changes are primarily frontend with minimal backend updates for session rewind tracking. Single branch: feat/ux-improvements.

Locked Decisions

  • Breadcrumb rewind persists immediately via API call.
  • Rewound steps are soft-abandoned (history preserved via rewind markers, never deleted).
  • Shortcuts modal is global from AppLayout and route-aware.
  • Follow existing monochrome design system with subtle keycap/hint styling.
  • sessions.decisions is JSONB — no DB migration needed for rewind marker fields.

Step 1: Command Copy UX (Quick Win)

Files: TreeNavigationPage.tsx

Changes

  • Add a copy-to-clipboard button next to every command block:
    • Action node commands (currentNode.commands)
    • Custom step commands (currentCustomStep.step_data.content.commands)
    • Command output textarea (when content exists)
  • Button styling: opacity-0 group-hover:opacity-100 with Clipboard icon, positioned absolute top-1.5 right-1.5 inside a group relative wrapper.
  • On click: navigator.clipboard.writeText(text), swap icon to Check for 2 seconds.
  • Track copied state with copiedCommand: string | null.
  • Show toast only on copy failure to avoid noisy UX on success.
  • Refactor duplicate command block rendering into a single local render helper to keep behavior consistent across action/custom-step sections.

Step 2: Keyboard Hints + Global Shortcuts Modal (Quick Win)

Files: AppLayout.tsx, TreeNavigationPage.tsx, new shortcutCatalog.ts

In-Page Hints (TreeNavigationPage.tsx)

  • Add keycap-style badges ([1], [2], etc.) next to decision option buttons. Style: kbd look, lower contrast, subtle.
  • Add [Esc] hint next to the Back button label.

Global Shortcuts Modal (AppLayout.tsx)

  • Add ? icon button in the app header (desktop + mobile drawer).
  • Opens a modal (reuse existing Modal component).
  • Modal is route-aware using location.pathname via a shortcutCatalog.ts file:
    • Tree Navigation routes: 1-9 Select option, Esc Go back, Enter Continue.
    • Tree Editor routes: Ctrl+S Save, Ctrl+Z Undo, Ctrl+Shift+Z Redo.
    • Other routes: Minimal generic navigation shortcuts.
  • Do NOT bind ? as a keyboard shortcut — it conflicts with text inputs. The modal is click-driven only.

Keyboard Listener (TreeNavigationPage.tsx)

  • Add useEffect keydown listener on document.
  • Keys 1-9: If current node is a decision node with options, call handleSelectOption for the corresponding option (index = key - 1).
  • Escape: Trigger back/rewind navigation (same handler as breadcrumb rewind — see Step 3).
  • Guards:
    • Only active when currentNode?.type === 'decision' and options exist.
    • Ignore if selectingOption is truthy (loading state).
    • Ignore if any modal is open.
  • Cleanup: Return removal function for the listener.

Step 3: Interactive Breadcrumbs with Soft-Abandon Rewind (Medium)

Files: TreeNavigationPage.tsx, session.py, session_to_tree.py, export_service.py, SessionDetailPage.tsx, SessionHistoryPage.tsx

Public Interface Changes

Extend DecisionRecord in session.py and session.ts with optional fields:

decision_kind?: 'step' | 'rewind_marker'  (default 'step')
rewind_source?: 'breadcrumb' | 'back_button'
rewind_from_node_id?: string
rewind_to_node_id?: string
abandoned_path_segment?: string[]

No DB migration required — sessions.decisions is JSONB and stores these optional fields directly.

Frontend Changes (TreeNavigationPage.tsx)

  • Replace static breadcrumb <span> elements with <button> for all non-current crumbs.
  • Styling: text-white/40 hover:text-white/70 hover:underline cursor-pointer for clickable items. Current item remains font-medium text-white as a <span>.
  • Introduce a unified rewind handler used by both:
    • Breadcrumb click
    • Back button / Esc key
  • Rewind algorithm:
    1. Compute newPath = pathTaken.slice(0, targetIndex + 1).
    2. Append a rewind_marker decision with: decision_kind, rewind_source, rewind_from_node_id, rewind_to_node_id, abandoned_path_segment (nodes removed from active path), and timestamp.
    3. Persist immediately via sessionsApi.update(session.id, { path_taken: newPath, decisions: newDecisions }).
    4. On API failure: restore previous local state and show error toast.
  • Clear any custom step state if active (customStepFlow.setCurrentCustomStep(null)).
  • Session continues accumulating steps naturally from the jumped-to node.

Backend/Downstream Compatibility

  • save_as_tree conversion: Ignore records where decision_kind === 'rewind_marker'.
  • Export generators (Markdown, Text, HTML): Skip rewind marker records in step numbering and output.
  • Session detail/timeline pages: Display rewind markers as explicit timeline events (e.g., "Rewound from Step 6 to Step 3").
  • Session "decision count" in SessionHistoryPage.tsx: Exclude rewind markers from the count.

Step 4: Prominent "Create Tree" CTA (Quick Win)

Files: MyTreesPage.tsx

Header Update

  • Convert header to flex row with action button:
    • Left: Title + subtitle.
    • Right: "Create Tree" button with Plus icon, linking to /trees/new.
  • Permission-aware: Only show for users with create permission (use existing role checks / usePermissions hook). Viewers cannot see it.

Empty State Update

  • Replace single "Browse Trees" link with two actions:
    • Primary (white bg, higher visual weight): "Browse Library" → links to /trees.
    • Secondary (outline/border style): "Create from Scratch" with Plus icon → links to /trees/new.
  • "Create from Scratch" is also permission-gated.

Step 5: Timer Visibility + Action Loading Feedback (Quick Win)

Files: TreeNavigationPage.tsx

Timer Enhancement

  • Change timer from plain text-white/40 to a pill/badge style:
    rounded-full bg-white/10 px-2.5 py-0.5 text-sm text-white/60
    
  • Slightly larger icon: h-4 w-4 (from h-3.5 w-3.5).
  • More visible but still secondary to tree name.

Action Loading Feedback

  • Add selectingOption: string | null state (stores option ID being selected).
  • When an option is being processed:
    • The active option button shows an inline spinner replacing the number badge.
    • All other option buttons get opacity-50 pointer-events-none.
    • Keyboard shortcuts are disabled to prevent double-submits.
  • Add similar feedback for "Continue" button with a "Continuing..." label.
  • Preserve existing isCompleting behavior for completion flow.

Files Modified Summary

File Steps
TreeNavigationPage.tsx 1, 2, 3, 5
MyTreesPage.tsx 4
AppLayout.tsx 2 (global shortcuts modal + ? button)
shortcutCatalog.ts (new) 2 (route → shortcut definitions)
session.py 3 (accept rewind marker fields in decisions)
session_to_tree.py 3 (ignore rewind markers)
export_service.py 3 (skip rewind markers in export output)
SessionDetailPage.tsx 3 (display rewind events in timeline)
SessionHistoryPage.tsx 3 (exclude rewind markers from decision count)

Verification

Build

cd frontend && npm run build    # clean build, no type errors
cd backend && pytest --override-ini="addopts="

Manual Testing

  • Copy button appears on hover over all command blocks; copies correctly; shows check feedback; failure shows toast.
  • Keycap hints [1], [2], etc. visible next to decision options; [Esc] visible near back button.
  • Number keys 1-9 select decision options; Esc triggers rewind; shortcuts disabled during loading.
  • ? icon in app header opens global shortcuts modal with route-aware content.
  • ? is NOT bound as a keyboard shortcut (no conflict with text inputs).
  • Clicking a previous breadcrumb rewinds to that point, persists immediately, and adds a rewind marker to session decisions.
  • Back button uses the same rewind marker flow as breadcrumbs.
  • Session detail page shows rewind events in timeline; decision count excludes rewind markers.
  • Exports (Markdown, Text, HTML) skip rewind markers and render only actual steps.
  • save_as_tree ignores rewind markers.
  • Timer displays as a visible pill badge.
  • Option/continue buttons show spinner + disable siblings during loading.
  • MyTreesPage header shows "Create Tree" button (hidden for viewers).
  • Empty state shows both "Browse Library" (primary) and "Create from Scratch" (secondary, permission-gated).