FN-8250: pin Settings at bottom of mobile More menu

Pin the omitted Settings destination beneath the mobile More-menu divider.

- Render Settings after the More-menu separator when omitted from primary tabs.
- Prevent duplicate Settings entries when it is a primary tab.
- Cover ordering and duplicate-prevention behavior with MobileNavBar tests.
- Add a patch changeset for the mobile navigation fix.

Files changed:
 .changeset/fn-8250-mobile-more-settings.md         |  7 +++++++
 packages/dashboard/app/components/MobileNavBar.tsx | 11 ++++++++++-
 .../app/components/__tests__/MobileNavBar.test.tsx | 22 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8250

Fusion-Task-Lineage: 4eea65d8-2e01-4fa4-986e-ffc15e906553

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-17 15:54:39 -07:00
parent c43fdbb520
commit 669cb7cc56
3 changed files with 39 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Mobile "More" menu now pins Settings to the bottom below the divider.
category: fix
dev: MobileNavBar renders the omitted `settings` destination after `.mobile-more-separator` instead of inline.

View File

@@ -626,7 +626,9 @@ export function MobileNavBar({
{effectiveOmittedItems.map((item) => renderSelectableItem(item, "more"))}
{effectiveOmittedItems
.filter((item) => item !== "settings")
.map((item) => renderSelectableItem(item, "more"))}
{overflowPluginViews.map((entry) => {
const pluginTaskView = buildPluginTaskViewId(entry.pluginId, entry.view.viewId);
@@ -646,6 +648,13 @@ export function MobileNavBar({
})}
<div className="mobile-more-separator" />
{/*
FNXC:Navigation 2026-07-17-15:43:
Mobile More-sheet pins Settings below the `mobile-more-separator` divider so it stays at the bottom of
the list (FN-8250), not inline in the middle. The omitted-items guard prevents a duplicate when Settings
is promoted to a primary footer tab.
*/}
{effectiveOmittedItems.includes("settings") && renderSelectableItem("settings", "more")}
</div>
</>

View File

@@ -703,6 +703,28 @@ describe("MobileNavBar", () => {
expect(screen.getByTestId("mobile-more-item-settings")).toBeDefined();
});
it("pins omitted Settings below the More divider as the final selectable item", () => {
const { container } = render(<MobileNavBar {...createDefaultProps()} />);
fireEvent.click(screen.getByTestId("mobile-nav-tab-more"));
const sheet = container.querySelector(".mobile-more-sheet");
const separator = sheet?.querySelector(".mobile-more-separator");
const settings = screen.getByTestId("mobile-more-item-settings");
expect(sheet).toBeInTheDocument();
expect(separator).toBeInTheDocument();
expect(separator!.compareDocumentPosition(settings) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
expect(Array.from(sheet!.querySelectorAll(".mobile-more-item")).at(-1)).toBe(settings);
});
it("does not duplicate Settings in More when Settings is a primary tab", () => {
render(<MobileNavBar {...createDefaultProps()} mobileNavPrimaryItems={["settings"]} />);
expect(screen.getByTestId("mobile-nav-tab-settings")).toBeInTheDocument();
fireEvent.click(screen.getByTestId("mobile-nav-tab-more"));
expect(screen.queryByTestId("mobile-more-item-settings")).toBeNull();
});
it("shows the stash orphan badge on the Git Manager item instead of a Stash Recovery item", () => {
render(<MobileNavBar {...createDefaultProps()} stashOrphanCount={8} />);
fireEvent.click(screen.getByTestId("mobile-nav-tab-more"));