From 125c5f5744093c3e5c1accd0385239c009dbec2e Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Mon, 22 Jun 2026 02:00:12 -0700 Subject: [PATCH] feat(dashboard): TodoView nav-stack in narrow dock; taller scrollable import preview; shared ViewHeader - TodoView collapses to a single-panel navigation stack (list -> items with Back) via container query when narrow (right dock); wide two-panel layout unchanged. - Embedded Import Tasks body scrolls vertically so the preview can be much taller (stacked layout gives the preview natural height; wide layout keeps internal scroll). - Add a shared ViewHeader component (icon + CC-style title + wrapping actions) for consistent main-view headers. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../app/components/GitHubImportModal.css | 11 +- .../dashboard/app/components/TodoView.css | 101 ++++++++++++++++++ .../dashboard/app/components/TodoView.tsx | 26 ++++- .../dashboard/app/components/ViewHeader.css | 42 ++++++++ .../dashboard/app/components/ViewHeader.tsx | 28 +++++ .../components/__tests__/TodoView.test.tsx | 1 + 6 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 packages/dashboard/app/components/ViewHeader.css create mode 100644 packages/dashboard/app/components/ViewHeader.tsx diff --git a/packages/dashboard/app/components/GitHubImportModal.css b/packages/dashboard/app/components/GitHubImportModal.css index a5bd773631..d36795aec5 100644 --- a/packages/dashboard/app/components/GitHubImportModal.css +++ b/packages/dashboard/app/components/GitHubImportModal.css @@ -997,6 +997,15 @@ Fix (embedded variant only — modal path untouched): turn the embedded root int container-name: github-import-embedded; } +/* +FNXC:RightDockEmbedding 2026-06-22-01:00: +Embedded Import Tasks must scroll vertically so a long preview is fully reachable. The view body is the scroll container; in the stacked (narrow) layout the preview takes its natural (content) height and the body scrolls, so the preview can be much taller than the viewport. In the wide two-pane layout the preview keeps its own internal scroll. +*/ +.github-import-modal--embedded .github-import-modal__body { + min-height: 0; + overflow-y: auto; +} + /* Default (narrow container): single stacked column. */ .github-import-modal--embedded .github-import-workspace { flex-direction: column; @@ -1011,7 +1020,7 @@ Fix (embedded variant only — modal path untouched): turn the embedded root int } .github-import-modal--embedded .github-import-preview-pane { - flex: 1 1 auto; + flex: 0 0 auto; width: 100%; min-width: 0; } diff --git a/packages/dashboard/app/components/TodoView.css b/packages/dashboard/app/components/TodoView.css index 7534ed5444..5efba6855a 100644 --- a/packages/dashboard/app/components/TodoView.css +++ b/packages/dashboard/app/components/TodoView.css @@ -14,6 +14,20 @@ FN-6829 mounts Todos as a flex child of .project-content like GoalsView; grow, z width: 100%; overflow: hidden; padding: var(--space-lg); + /* + FNXC:TodosStyling 2026-06-22-00:00: + TodoView renders both in the wide main area and inside the narrow right dock (no width prop). Make it a query container so the layout switch is driven by the actual rendered width, not a viewport media query or a prop. Below the container breakpoint the two-panel split collapses into a single-panel navigation stack (see `@container todo-view (max-width: 520px)`). + */ + container-type: inline-size; + container-name: todo-view; +} + +/* +FNXC:TodosStyling 2026-06-22-00:00: +The narrow-stack Back button is hidden by default (wide two-panel layout shows both panels, so there is nothing to go "back" to). The narrow container query reveals it. +*/ +.todo-mobile-back-btn { + display: none; } .todo-view-header { @@ -401,6 +415,93 @@ FN-6829 mounts Todos as a flex child of .project-content like GoalsView; grow, z } } +/* +FNXC:TodosStyling 2026-06-22-00:00: +NARROW container (right dock): collapse the side-by-side split into a single-panel navigation stack. Exactly one panel shows at a time, full-width with its own internal scroll and no horizontal overflow. `data-mobile-stack-view` (set by the component from `mobileStackView`) decides which panel is visible: "list" shows the master list-selection panel; "detail" shows the items panel with the Back button revealed. Tap targets are enlarged for touch. 520px is tuned to the content: below it the sidebar's fixed width plus the items pane no longer fit comfortably. +*/ +@container todo-view (max-width: 520px) { + .todo-view-layout { + flex-direction: column; + min-height: 0; + overflow: hidden; + gap: 0; + } + + /* Single panel at a time: full-width, owns its vertical scroll. */ + .todo-view-sidebar, + .todo-view-main { + width: 100%; + min-width: 0; + flex: 1 1 auto; + border-right: none; + padding-right: 0; + overflow-x: hidden; + overflow-y: auto; + } + + .todo-view-sidebar { + border-bottom: none; + } + + /* On the list panel, hide the items pane; on the detail panel, hide the list pane. */ + .todo-view-layout[data-mobile-stack-view="list"] .todo-view-main { + display: none; + } + + .todo-view-layout[data-mobile-stack-view="detail"] .todo-view-sidebar { + display: none; + } + + /* Reveal the Back affordance only in the narrow stack. */ + .todo-mobile-back-btn { + display: inline-flex; + } + + /* Comfortable touch targets and full-width add controls in the stack. */ + .todo-list-item, + .todo-list-select-btn, + .todo-add-list-btn, + .todo-icon-btn, + .todo-item, + .todo-item-reorder-btn, + .todo-add-item-row .btn { + min-height: calc(var(--space-2xl) + var(--space-xs)); + } + + .todo-list-item-actions, + .todo-item-actions { + opacity: 1; + } + + .todo-item-actions { + margin-left: 0; + } + + .todo-add-item-row { + flex-wrap: wrap; + } + + .todo-add-item-row .btn { + width: 100%; + } + + /* Anchor the agent picker to the full stack width to avoid horizontal overflow. */ + .todo-agent-picker-trigger { + position: static; + } + + .todo-agent-picker-dropdown { + left: 0; + right: 0; + min-width: 100%; + max-height: calc(var(--space-2xl) * 8); + } + + .todo-agent-picker-item { + min-height: calc(var(--space-2xl) + var(--space-xs)); + } +} + @media (max-width: 768px) { .todo-view { padding: var(--space-md); diff --git a/packages/dashboard/app/components/TodoView.tsx b/packages/dashboard/app/components/TodoView.tsx index 47e7f6acd7..952f24bb39 100644 --- a/packages/dashboard/app/components/TodoView.tsx +++ b/packages/dashboard/app/components/TodoView.tsx @@ -8,6 +8,7 @@ import { X, ChevronUp, ChevronDown, + ChevronLeft, Loader2, ListChecks, Bot, @@ -80,6 +81,12 @@ export function TodoView({ const agentPickerRef = useRef(null); const { confirm } = useConfirm(); + /* + FNXC:Todos 2026-06-22-00:00: + TodoView mounts in the narrow right dock (no width prop) where the two side-by-side panels (list selection + items) cannot fit. The layout switch is driven by a CSS container query on `.todo-view` (container-name: todo-view), NOT a prop. In the NARROW container we render a single-panel navigation stack: the master list-selection panel first, and selecting a list navigates forward to its items panel with a Back affordance. `mobileStackView` tracks which panel the narrow stack shows; the WIDE two-panel layout ignores it entirely (both panels always render). Selecting a list pushes to "detail"; Back returns to "list". + */ + const [mobileStackView, setMobileStackView] = useState<"list" | "detail">("list"); + const selectedList = useMemo( () => lists.find((list) => list.id === selectedListId) ?? null, [lists, selectedListId], @@ -106,6 +113,13 @@ export function TodoView({ resetListDraftState(); resetItemDraftState(); setSelectedListId(listId); + // FNXC:Todos 2026-06-22-00:00: Narrow stack navigates forward to the items panel on selection; no-op visually in the wide two-panel layout. + setMobileStackView("detail"); + } + + // FNXC:Todos 2026-06-22-00:00: Narrow-stack Back affordance returns to the master list-selection panel. Inert in the wide layout where both panels are always visible. + function handleMobileBack(): void { + setMobileStackView("list"); } const loadAgents = useCallback(async () => { @@ -329,7 +343,7 @@ export function TodoView({ return (
{header} -
+