From 0b71e9f55e8bf545353d0c43ffb7bb607b81882f Mon Sep 17 00:00:00 2001 From: Fusion Agent Date: Thu, 20 Aug 2026 06:15:23 +0000 Subject: [PATCH] FN-070: streamline mobile navigation and task creation Refine mobile project navigation so task creation and view switching remain accessible without redundant header controls. - Add a Header New Task action backed by the existing full task form. - Move mobile Board/List destinations to the bottom navigation and preserve Planning quick entry. - Update responsive documentation, changeset metadata, and regression coverage. Files changed: .changeset/fn-070-mobile-navigation.md | 7 ++++ docs/dashboard-guide.md | 2 +- packages/dashboard/app/App.tsx | 1 + packages/dashboard/app/__tests__/mobile-feature-access-regression.test.tsx | 25 +++++++------ packages/dashboard/app/components/Board.tsx | 9 ++++- packages/dashboard/app/components/Header.tsx | 43 ++++++++++------------- packages/dashboard/app/components/ListView.tsx | 2 +- packages/dashboard/app/components/MobileNavBar.tsx | 20 ++++++++-- .../app/components/__tests__/App.test.tsx | 14 ++++--- .../app/components/__tests__/Board.test.tsx | 17 +++++++++ .../app/components/__tests__/Header.test.tsx | 16 +++++++- .../app/components/__tests__/ListView.test.tsx | 5 ++- .../app/components/__tests__/MobileNavBar.test.tsx | 24 +++++++----- 13 files changed, 123 insertions(+), 62 deletions(-) Fusion-Task-Id: FN-070 Fusion-Task-Lineage: 17bdd4fe-a2ef-481e-9083-6fb1c2d6425f Co-authored-by: Fusion --- .changeset/fn-070-mobile-navigation.md | 7 +++ docs/dashboard-guide.md | 2 +- packages/dashboard/app/App.tsx | 1 + .../mobile-feature-access-regression.test.tsx | 25 ++++++----- packages/dashboard/app/components/Board.tsx | 9 +++- packages/dashboard/app/components/Header.tsx | 43 ++++++++----------- .../dashboard/app/components/ListView.tsx | 2 +- .../dashboard/app/components/MobileNavBar.tsx | 20 +++++++-- .../app/components/__tests__/App.test.tsx | 14 +++--- .../app/components/__tests__/Board.test.tsx | 17 ++++++++ .../app/components/__tests__/Header.test.tsx | 16 ++++++- .../components/__tests__/ListView.test.tsx | 5 ++- .../__tests__/MobileNavBar.test.tsx | 24 ++++++----- 13 files changed, 123 insertions(+), 62 deletions(-) create mode 100644 .changeset/fn-070-mobile-navigation.md diff --git a/.changeset/fn-070-mobile-navigation.md b/.changeset/fn-070-mobile-navigation.md new file mode 100644 index 0000000000..9339d7a682 --- /dev/null +++ b/.changeset/fn-070-mobile-navigation.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": minor +--- + +summary: Make mobile task creation and Board/List navigation available from every project view. +category: feature +dev: Moves the mobile full-task trigger to Header while preserving Planning quick entry. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index c77458bc7d..b84f356ab9 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -198,7 +198,7 @@ While the sidebar is active on desktop/tablet project screens, Board and List wo The active nav-item highlight and the resize-handle hover/focus accent track the active color theme's `--accent` token across all themes, so shadcn, forest, ocean, and other themes no longer show a fixed blue selected state. The Header retains the Fusion brand and project selector, keeps non-navigation controls, and hides duplicate desktop view-toggle entries while the sidebar is active. -On mobile viewports (`<=768px`), the sidebar is not rendered even when the default-on setting is enabled. The existing bottom `MobileNavBar` remains the navigation surface on project task screens, with mobile-only More-sheet entries for compact tools such as Git Manager, Terminal, Files, and **Import from GitHub**. +On mobile viewports (`<=768px`), the sidebar is not rendered even when the default-on setting is enabled. The Header's **New Task** action opens the existing full form from any active project view. The bottom `MobileNavBar` provides separate **Tasks** (Board) and **List** destinations, while the Planning column keeps its inline quick-entry composer. Mobile-only More-sheet entries remain available for compact tools such as Git Manager, Terminal, Files, and **Import from GitHub**. diff --git a/packages/dashboard/app/App.tsx b/packages/dashboard/app/App.tsx index efb4aef2e3..4538bb43c5 100644 --- a/packages/dashboard/app/App.tsx +++ b/packages/dashboard/app/App.tsx @@ -1913,6 +1913,7 @@ function AppInner() { filesOpen={modalManager.filesOpen} view={taskView} onChangeView={viewMode === "project" && currentProject ? handleTaskViewChange : undefined} + onNewTask={viewMode === "project" && currentProject ? openNewTaskWithNav : undefined} showSkillsTab={skillsEnabled} showAgentsTab={agentsEnabled} searchQuery={searchQuery} diff --git a/packages/dashboard/app/__tests__/mobile-feature-access-regression.test.tsx b/packages/dashboard/app/__tests__/mobile-feature-access-regression.test.tsx index 0873c4f33c..9642065cbe 100644 --- a/packages/dashboard/app/__tests__/mobile-feature-access-regression.test.tsx +++ b/packages/dashboard/app/__tests__/mobile-feature-access-regression.test.tsx @@ -133,26 +133,29 @@ describe("Mobile Feature Access Regression Guard", () => { document.documentElement.style.removeProperty("--mobile-nav-height"); }); - it("list view is accessible via mobile nav bar", () => { + it("list view is independently accessible via mobile nav bar", () => { const props = createDefaultMobileNavProps(); render(); - const tasksTab = screen.getByTestId("mobile-nav-tab-tasks"); - expect(tasksTab.textContent).toContain("Tasks"); - - fireEvent.click(tasksTab); - expect(props.onChangeView).toHaveBeenCalledWith("board"); + fireEvent.click(screen.getByTestId("mobile-nav-tab-list")); + expect(props.onChangeView).toHaveBeenCalledWith("list"); }); - it("board view is accessible via mobile nav bar", () => { + it("board view is accessible from Tasks on mobile nav bar", () => { const props = createDefaultMobileNavProps(); render(); - const tasksTab = screen.getByTestId("mobile-nav-tab-tasks"); - expect(tasksTab.textContent).toContain("Tasks"); + fireEvent.click(screen.getByTestId("mobile-nav-tab-tasks")); + expect(props.onChangeView).toHaveBeenCalledWith("board"); + }); - fireEvent.click(tasksTab); - expect(props.onChangeView).toHaveBeenCalledWith("list"); + it("mobile Header exposes New Task without the retired view toggle", () => { + const onNewTask = vi.fn(); + render(
); + + expect(screen.queryByTestId("mobile-view-toggle")).toBeNull(); + fireEvent.click(screen.getByTestId("mobile-header-new-task")); + expect(onNewTask).toHaveBeenCalledOnce(); }); it("agents view is accessible via mobile nav bar", () => { diff --git a/packages/dashboard/app/components/Board.tsx b/packages/dashboard/app/components/Board.tsx index 7b12a9141e..6570649dae 100644 --- a/packages/dashboard/app/components/Board.tsx +++ b/packages/dashboard/app/components/Board.tsx @@ -226,6 +226,11 @@ export function Board({ tasks, projectId, maxConcurrent, showWorktreeGrouping, o setBoardElement((current) => current === element ? current : element); }, []); const viewportMode = useViewportMode(); + /* + FNXC:MobileTaskNavigation 2026-08-20-05:47: + Issue #2226 moves only the mobile full-task modal trigger to Header. Keep intake quick-create props on every viewport so Planning remains an inline composer. + */ + const mobileFullTaskModalHidden = viewportMode === "mobile"; useColumnScrollSnap(boardElement, { mobileOnly: true }); /* FNXC:BoardNavigation 2026-08-20-04:47: @@ -1006,7 +1011,7 @@ export function Board({ tasks, projectId, maxConcurrent, showWorktreeGrouping, o mergeStrategy={mergeStrategy} // FNXC:PlanApproval 2026-07-07-00:00: FN-7653 — the plan auto-approve shortcut belongs only to the intake/planning column, never to hold (Todo-like) columns; the built-in Coding workflow's Todo column carries the hold trait and was wrongly receiving this prop pair. {...((columnDef.flags.intake && !columnDef.flags.archived && !columnDef.flags.complete && !columnDef.flags.countsTowardWip && !columnDef.flags.mergeBlocker && !columnDef.flags.humanReview) ? { planAutoApproveEnabled, onTogglePlanAutoApprove } : {})} - {...(isCreateColumn && aggregateQuickCreateTarget ? { workflowId: aggregateQuickCreateTarget.workflowId, workflowOptions, defaultWorkflowId: boardWorkflows?.defaultWorkflowId ?? null, onQuickCreate: handleAggregateWorkflowQuickCreate, onNewTask: handleAggregateWorkflowNewTask, onSubtaskBreakdown } : {})} + {...(isCreateColumn && aggregateQuickCreateTarget ? { workflowId: aggregateQuickCreateTarget.workflowId, workflowOptions, defaultWorkflowId: boardWorkflows?.defaultWorkflowId ?? null, onQuickCreate: handleAggregateWorkflowQuickCreate, ...(!mobileFullTaskModalHidden ? { onNewTask: handleAggregateWorkflowNewTask } : {}), onSubtaskBreakdown } : {})} {...(columnDef.flags.mergeBlocker || columnDef.flags.humanReview ? { onToggleAutoMerge: handleToggleAutoMerge } : {})} {...(columnDefOffersArchiveAllDone(columnDef) ? { onArchiveAllDone } : {})} {...(laneSortModeChange ? { sortMode: laneSortMode, onSortModeChange: laneSortModeChange } : {})} @@ -1101,7 +1106,7 @@ export function Board({ tasks, projectId, maxConcurrent, showWorktreeGrouping, o mergeStrategy={mergeStrategy} // FNXC:PlanApproval 2026-07-07-00:00: FN-7653 — the plan auto-approve shortcut belongs only to the intake/planning column, never to hold (Todo-like) columns; the built-in Coding workflow's Todo column carries the hold trait and was wrongly receiving this prop pair. {...((columnDef.flags.intake && !columnDef.flags.archived && !columnDef.flags.complete && !columnDef.flags.countsTowardWip && !columnDef.flags.mergeBlocker && !columnDef.flags.humanReview) ? { planAutoApproveEnabled, onTogglePlanAutoApprove } : {})} - {...(isCreateColumn ? { workflowOptions, defaultWorkflowId: selectedWorkflow.id, onQuickCreate: handleWorkflowQuickCreate, onNewTask: handleSelectedWorkflowNewTask, onSubtaskBreakdown } : {})} + {...(isCreateColumn ? { workflowOptions, defaultWorkflowId: selectedWorkflow.id, onQuickCreate: handleWorkflowQuickCreate, ...(!mobileFullTaskModalHidden ? { onNewTask: handleSelectedWorkflowNewTask } : {}), onSubtaskBreakdown } : {})} {...(columnDef.flags.mergeBlocker || columnDef.flags.humanReview ? { onToggleAutoMerge: handleToggleAutoMerge } : {})} {...(columnDefOffersArchiveAllDone(columnDef) ? { onArchiveAllDone } : {})} {...{ sortMode: laneSortMode, onSortModeChange: laneSortModeChange, doneSortMode: laneSortMode, onDoneSortModeChange: laneSortModeChange }} diff --git a/packages/dashboard/app/components/Header.tsx b/packages/dashboard/app/components/Header.tsx index 6457c32023..a901466a86 100644 --- a/packages/dashboard/app/components/Header.tsx +++ b/packages/dashboard/app/components/Header.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, useRef, useCallback, useMemo, type ReactNode } from "react"; import { useTranslation } from "react-i18next"; -import { Settings, LayoutGrid, List, Search, X, Activity, MoreHorizontal, Clock, Folder, History, GitBranch, Monitor, Workflow, Bot, Target, Grid3X3, Mail, MessageSquare, Check, Zap, Sparkles, FileText, Brain, Lock, Gauge, Lightbulb, ChevronDown, ChevronRight, PanelRight, Star } from "lucide-react"; +import { Settings, LayoutGrid, List, Search, X, Activity, MoreHorizontal, Clock, Folder, History, GitBranch, Monitor, Workflow, Bot, Target, Grid3X3, Mail, MessageSquare, Check, Zap, Sparkles, FileText, Brain, Lock, Gauge, Lightbulb, ChevronDown, ChevronRight, PanelRight, Plus, Star } from "lucide-react"; import "./Header.css"; // ProjectSelector styles used by the imported standalone component. import "./ProjectSelector.css"; @@ -74,6 +74,8 @@ export interface HeaderProps { filesOpen?: boolean; view?: TaskView; onChangeView?: (view: TaskView) => void; + /** Opens the existing App-owned full New Task modal. */ + onNewTask?: () => void; /** Whether to show the skills tab in the view toggle */ showSkillsTab?: boolean; /** When true, shows the Agents view tab button. Hidden by default (experimental feature). */ @@ -137,6 +139,7 @@ export function Header({ onOpenFiles, view = "board", onChangeView, + onNewTask, showSkillsTab, showAgentsTab, searchQuery = "", @@ -621,30 +624,20 @@ export function Header({
{shellConnectionControl} - {/* Mobile View Toggle - compact board/list switcher in header when mobile nav is active */} - {hideFullNav && onChangeView && (view === "board" || view === "list") && ( -
- - -
+ {/* + FNXC:MobileTaskNavigation 2026-08-20-05:47: + Issue #2226 moves mobile Board/List navigation to the footer so Header can expose App's single full-task modal entry point from every active project view. The Planning column keeps its separate quick-entry composer. + */} + {isMobile && mobileNavEnabled && projectId && onNewTask && ( + )} {/* Mobile Search Trigger - only on mobile, show trigger button in header */} diff --git a/packages/dashboard/app/components/ListView.tsx b/packages/dashboard/app/components/ListView.tsx index a80b8cda00..baf3f2acdf 100644 --- a/packages/dashboard/app/components/ListView.tsx +++ b/packages/dashboard/app/components/ListView.tsx @@ -2710,7 +2710,7 @@ export function ListView({ {t("listView.viewOptions", "View")} - {onNewTask ? ( + {onNewTask && !isMobile ? ( {topLevelPrimaryPluginViews.map((entry) => { const pluginTaskView = buildPluginTaskViewId(entry.pluginId, entry.view.viewId); diff --git a/packages/dashboard/app/components/__tests__/App.test.tsx b/packages/dashboard/app/components/__tests__/App.test.tsx index aaef2ecf20..bcf1d9a3b7 100644 --- a/packages/dashboard/app/components/__tests__/App.test.tsx +++ b/packages/dashboard/app/components/__tests__/App.test.tsx @@ -707,7 +707,8 @@ async function waitForAppShell(): Promise { await waitFor(() => { expect(fetchSettings).toHaveBeenCalled(); if (mockUseViewportMode() === "mobile") { - expect(screen.getByTestId("mobile-view-toggle")).toBeTruthy(); + expect(screen.getByTestId("mobile-nav-tab-tasks")).toBeTruthy(); + expect(screen.getByTestId("mobile-nav-tab-list")).toBeTruthy(); } else { expect(screen.getByTitle("Settings")).toBeTruthy(); } @@ -781,7 +782,7 @@ describe("FN-8698 retained Board and List task popups", () => { const overlayFor = (view: "board" | "list") => `floating-window-overlay-task-detail-FN-8698-${view}`; const showView = async (view: "board" | "list") => { const navigationTestId = viewport === "mobile" - ? `mobile-view-toggle-${view}` + ? `mobile-nav-tab-${view === "board" ? "tasks" : "list"}` : `sidebar-nav-${view}`; fireEvent.click(screen.getByTestId(navigationTestId)); await waitFor(() => expect(document.querySelector(taskSelector(view))).toBeTruthy()); @@ -4873,7 +4874,8 @@ describe("FN-5817 mobile auto-merge toggle stability", () => { render(); const toggle = await screen.findByRole("checkbox", { name: "Auto-merge" }); - expect(screen.getByTestId("mobile-view-toggle")).toBeInTheDocument(); + expect(screen.getByTestId("mobile-nav-tab-tasks")).toBeInTheDocument(); + expect(screen.getByTestId("mobile-nav-tab-list")).toBeInTheDocument(); expect(document.querySelector("main.board")).not.toBeNull(); expect(screen.getByText("In review task")).toBeInTheDocument(); expect(screen.queryByText("Something went wrong")).toBeNull(); @@ -4885,7 +4887,8 @@ describe("FN-5817 mobile auto-merge toggle stability", () => { expect.objectContaining({ autoMerge: expect.any(Boolean) }), DEFAULT_PROJECT_ID, ); - expect(screen.getByTestId("mobile-view-toggle")).toBeInTheDocument(); + expect(screen.getByTestId("mobile-nav-tab-tasks")).toBeInTheDocument(); + expect(screen.getByTestId("mobile-nav-tab-list")).toBeInTheDocument(); expect(screen.getByRole("checkbox", { name: "Auto-merge" })).toBeInTheDocument(); expect(document.querySelector("main.board")).not.toBeNull(); expect(screen.getByText("In review task")).toBeInTheDocument(); @@ -4955,7 +4958,8 @@ describe("App shell connection status plumbing", () => { await waitFor(() => { expect(mockGetShellConnectionNativeResult).toHaveBeenCalledWith(mockShellHostContextValue.host); - expect(screen.getByTestId("mobile-view-toggle")).toBeInTheDocument(); + expect(screen.getByTestId("mobile-nav-tab-tasks")).toBeInTheDocument(); + expect(screen.getByTestId("mobile-nav-tab-list")).toBeInTheDocument(); }); expect(screen.queryByTestId("shell-connection-status-button")).toBeNull(); diff --git a/packages/dashboard/app/components/__tests__/Board.test.tsx b/packages/dashboard/app/components/__tests__/Board.test.tsx index 94f231804f..ee10cfb7a1 100644 --- a/packages/dashboard/app/components/__tests__/Board.test.tsx +++ b/packages/dashboard/app/components/__tests__/Board.test.tsx @@ -1790,6 +1790,23 @@ describe("Board", () => { expect(onNewTask).toHaveBeenCalledWith(CUSTOM_WORKFLOW.id); }); + it("keeps intake quick entry while omitting its full task button on mobile", async () => { + const mobile = installMobileBoardStabilizationHarness(); + try { + const onNewTask = vi.fn(); + enableFlag({ "FN-1": CUSTOM_WORKFLOW.id }, [DEFAULT_WORKFLOW, CUSTOM_WORKFLOW]); + renderBoard({ tasks: [mkTask({ id: "FN-1", column: "intake" })], onNewTask }); + + await selectWorkflow(CUSTOM_WORKFLOW.id); + const intakeColumn = screen.getByTestId("column-intake"); + expect(intakeColumn).toHaveAttribute("data-has-quick-create", "yes"); + expect(intakeColumn).toHaveAttribute("data-has-new-task", "no"); + expect(screen.queryByTestId("mock-new-task-intake")).toBeNull(); + } finally { + mobile.restore(); + } + }); + it("defaults All workflows quick-add to the default workflow and resolves selected workflow columns", async () => { const onQuickCreate = vi.fn().mockResolvedValue({ id: "FN-new", workflowId: "wf-custom" }); enableFlag({}, [DEFAULT_WORKFLOW, CUSTOM_WORKFLOW]); diff --git a/packages/dashboard/app/components/__tests__/Header.test.tsx b/packages/dashboard/app/components/__tests__/Header.test.tsx index caf279bfae..7ba4fd4c7f 100644 --- a/packages/dashboard/app/components/__tests__/Header.test.tsx +++ b/packages/dashboard/app/components/__tests__/Header.test.tsx @@ -185,8 +185,20 @@ describe("Header", () => { expect(workflowSlot).toBeInTheDocument(); expect(workflowSlot).toHaveClass("header-workflow-slot--mobile"); expect(workflowSlot.closest(".header-left")).toBeInTheDocument(); - expect(screen.getByTestId("mobile-view-toggle-board")).toBeInTheDocument(); - expect(screen.getByTestId("mobile-view-toggle-list")).toBeInTheDocument(); + expect(screen.queryByTestId("mobile-view-toggle")).toBeNull(); + expect(screen.queryByTestId("mobile-view-toggle-board")).toBeNull(); + expect(screen.queryByTestId("mobile-view-toggle-list")).toBeNull(); + }); + + it("renders one mobile New Task action only for an active project callback", () => { + const onNewTask = vi.fn(); + const rendered = renderHeader({ mobileNavEnabled: true, projectId: "project-1", onNewTask }, "mobile"); + fireEvent.click(screen.getByTestId("mobile-header-new-task")); + expect(onNewTask).toHaveBeenCalledOnce(); + + rendered.unmount(); + renderHeader({ mobileNavEnabled: true, onNewTask }, "mobile"); + expect(screen.queryByTestId("mobile-header-new-task")).toBeNull(); }); it("shows board view as active by default", () => { diff --git a/packages/dashboard/app/components/__tests__/ListView.test.tsx b/packages/dashboard/app/components/__tests__/ListView.test.tsx index 942fdd12c9..7846e51244 100644 --- a/packages/dashboard/app/components/__tests__/ListView.test.tsx +++ b/packages/dashboard/app/components/__tests__/ListView.test.tsx @@ -3300,13 +3300,14 @@ describe("ListView", () => { expect(desktopSplitRule).toContain("grid-template-columns: auto 0 minmax(0, 1fr)"); }); - it("keeps Bulk Edit, View, and + New Task together in the mobile toolbar controls", () => { + it("omits the full New Task button from mobile toolbar controls", () => { const viewportSpy = mockMobileViewport(); renderListView({}, { openViewOptions: false }); const actions = document.querySelector(".list-toolbar .list-action-cluster"); const actionButtons = Array.from(actions?.querySelectorAll("button") ?? []).map((button) => button.textContent); - expect(actionButtons).toEqual(["Bulk Edit", "View", "+ New Task"]); + expect(actionButtons).toEqual(["Bulk Edit", "View"]); + expect(screen.queryByText("+ New Task")).toBeNull(); viewportSpy.mockRestore(); }); diff --git a/packages/dashboard/app/components/__tests__/MobileNavBar.test.tsx b/packages/dashboard/app/components/__tests__/MobileNavBar.test.tsx index aec6c358c6..cd77961207 100644 --- a/packages/dashboard/app/components/__tests__/MobileNavBar.test.tsx +++ b/packages/dashboard/app/components/__tests__/MobileNavBar.test.tsx @@ -137,7 +137,7 @@ describe("MobileNavBar", () => { vi.useRealTimers(); }); - it("renders seven top-level tab buttons (command center + tasks + agents + missions + chat + mailbox + more) and keeps skills in More when showSkillsTab is true", () => { + it("renders eight top-level tab buttons including dedicated List and keeps skills in More when showSkillsTab is true", () => { render(); expect(screen.getByTestId("mobile-nav-tab-command-center")).toBeDefined(); @@ -146,6 +146,7 @@ describe("MobileNavBar", () => { expect(screen.getByTestId("mobile-nav-tab-missions")).toBeDefined(); expect(screen.getByTestId("mobile-nav-tab-chat")).toBeDefined(); expect(screen.getByTestId("mobile-nav-tab-mailbox")).toBeDefined(); + expect(screen.getByTestId("mobile-nav-tab-list")).toBeDefined(); expect(screen.queryByTestId("mobile-nav-tab-skills")).toBeNull(); expect(screen.queryByTestId("mobile-nav-tab-roadmaps")).toBeNull(); expect(screen.getByTestId("mobile-nav-tab-more")).toBeDefined(); @@ -243,14 +244,14 @@ describe("MobileNavBar", () => { mailboxPendingApprovalCount={2} />, ); - expectUniformMobileNavColumns(sevenTabRender.container, 7); + expectUniformMobileNavColumns(sevenTabRender.container, 8); expect(screen.getByTestId("mobile-nav-tab-command-center").className).toContain("mobile-nav-tab--active"); expect(screen.getByLabelText("Unread chat response")).toBeInTheDocument(); expect(screen.getByLabelText("Pending approvals")).toBeInTheDocument(); expect(screen.getByTestId("mobile-nav-tab-mailbox").querySelector(".mobile-nav-tab-badge")?.textContent).toBe("7"); sevenTabRender.unmount(); - // Skills is never a top-level tab, so enabling it keeps the top-level column count at seven + // Skills is never a top-level tab, so enabling it keeps the top-level column count at eight // and the skills destination, plus its active view, lives in the More sheet. const skillsEnabledRender = render( { mailboxPendingApprovalCount={1} />, ); - expectUniformMobileNavColumns(skillsEnabledRender.container, 7); + expectUniformMobileNavColumns(skillsEnabledRender.container, 8); expect(screen.queryByTestId("mobile-nav-tab-skills")).toBeNull(); expect(screen.getByTestId("mobile-nav-tab-more").className).toContain("mobile-nav-tab--active"); expect(screen.getByTestId("mobile-nav-tab-mailbox").querySelector(".mobile-nav-tab-badge")?.textContent).toBe("99+"); @@ -282,7 +283,7 @@ describe("MobileNavBar", () => { ]} />, ); - expectUniformMobileNavColumns(pluginVariantRender.container, 7); + expectUniformMobileNavColumns(pluginVariantRender.container, 8); expect(screen.queryByTestId("mobile-nav-tab-plugin-fusion-plugin-spacing-check-wide")).toBeNull(); fireEvent.click(screen.getByTestId("mobile-nav-tab-more")); expect(screen.getByTestId("mobile-more-item-plugin-fusion-plugin-spacing-check-wide")).toBeDefined(); @@ -573,12 +574,12 @@ describe("MobileNavBar", () => { expect(props.onChangeView).toHaveBeenCalledWith("board"); }); - it("tasks tab calls onChangeView with 'list' when already on list", () => { + it("tasks tab returns to board when currently on list", () => { const props = createDefaultProps(); render(); fireEvent.click(screen.getByTestId("mobile-nav-tab-tasks")); - expect(props.onChangeView).toHaveBeenCalledWith("list"); + expect(props.onChangeView).toHaveBeenCalledWith("board"); }); it("tasks tab is active when view is 'board'", () => { @@ -586,9 +587,12 @@ describe("MobileNavBar", () => { expect(screen.getByTestId("mobile-nav-tab-tasks").className).toContain("mobile-nav-tab--active"); }); - it("tasks tab is active when view is 'list'", () => { - render(); - expect(screen.getByTestId("mobile-nav-tab-tasks").className).toContain("mobile-nav-tab--active"); + it("list tab is active and routes to list when view is 'list'", () => { + const props = createDefaultProps(); + render(); + expect(screen.getByTestId("mobile-nav-tab-list").className).toContain("mobile-nav-tab--active"); + fireEvent.click(screen.getByTestId("mobile-nav-tab-list")); + expect(props.onChangeView).toHaveBeenCalledWith("list"); }); it("missions tab calls onChangeView with 'missions'", () => {