Move completed plan docs to docs/plans/archive/. Add survey migration 046 and reference HTML/plan files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.3 KiB
Tree Forking UI Design
Date: 2026-02-24 Feature: Personal tree forking — explicit modal, reason capture, fork badge
Overview
Add a proper fork UX to the flow library. The backend is fully complete (POST /trees/:id/fork, fork fields in API responses, tests passing). The frontend needs: a ForkModal component with a "Reason for Forking" field, updated fork handlers in TreeLibraryPage and MyTreesPage, fork field types on Tree, and a "Fork" chip on tree cards.
What's Being Built
1. Types — frontend/src/types/tree.ts
Add ForkInfo interface and fork fields to Tree:
export interface ForkInfo {
parent_tree_id: string
parent_tree_name: string | null
fork_depth: number
fork_reason: string | null
has_parent_updates: boolean
}
Add to Tree:
fork_info?: ForkInfo | null
parent_tree_id?: string | null
fork_depth?: number
Add to TreeCreate:
fork_reason?: string
2. ForkModal Component — frontend/src/components/library/ForkModal.tsx
A focused dialog with:
- Name field — pre-filled with
"Copy of <original name>" - "Reason for Forking" — optional textarea (placeholder: "e.g. customizing for a specific client…")
- Cancel (secondary) + Fork (gradient) buttons
- Calls
treesApi.fork(treeId, { name, fork_reason })on submit - Success: shows toast, navigates to
/my-trees - Error: shows inline error, stays open
3. Update Fork Handlers
In TreeLibraryPage and MyTreesPage, replace the current silent handleForkTree (which calls treesApi.fork() directly) with a handler that:
- Sets the selected tree to fork
- Opens
ForkModal
The modal handles the actual API call and navigation.
4. "Fork" Badge on Tree Cards
In TreeGridView, TreeListView, and TreeTableView, render a small chip when fork_depth > 0 (or parent_tree_id is set on TreeListItem):
{tree.fork_depth > 0 && (
<span className="rounded-full bg-violet-400/15 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wide text-violet-400">
Fork
</span>
)}
fork_depth needs to be added to TreeListItem (it comes from the backend list response).
What's NOT Being Built
- Lineage tree view / "forked from" link — out of scope
- "Has updates available" notification — out of scope
- Fork management / ancestry tracking UI — out of scope
Data Flow
User clicks "Fork" on a card
→ onForkTree(tree) called
→ parent sets forkTarget state + opens ForkModal
→ user fills Name + optional Reason
→ ForkModal calls treesApi.fork(treeId, { name, fork_reason })
→ on success: toast "Flow forked!" + navigate('/my-trees')
→ My Trees page loads, forked flow shows "Fork" badge
Files Changed
| File | Change |
|---|---|
frontend/src/types/tree.ts |
Add ForkInfo, fork fields on Tree, fork_depth on TreeListItem |
frontend/src/components/library/ForkModal.tsx |
New component |
frontend/src/pages/TreeLibraryPage.tsx |
Open modal instead of silent fork |
frontend/src/pages/MyTreesPage.tsx |
Open modal instead of silent fork |
frontend/src/components/library/TreeGridView.tsx |
Fork badge |
frontend/src/components/library/TreeListView.tsx |
Fork badge |
frontend/src/components/library/TreeTableView.tsx |
Fork badge |