Skip to content

Bugfix: Stabilize NavigationStack Layout + Reduce NavigationBar Spacing on Sheets#475

Open
fhasse95 wants to merge 1 commit into
skiptools:mainfrom
fhasse95:Navigation-Layout-Bugfix
Open

Bugfix: Stabilize NavigationStack Layout + Reduce NavigationBar Spacing on Sheets#475
fhasse95 wants to merge 1 commit into
skiptools:mainfrom
fhasse95:Navigation-Layout-Bugfix

Conversation

@fhasse95

@fhasse95 fhasse95 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

This PR stabilizes NavigationStack layout behavior so that the navigation bar and the content below it no longer jump when the navigation bar height is measured or updated.

Before this change, the navigation bar could be laid out with an initial height of zero or an incomplete height, and then expand to its final size after the first layout/measurement pass. Visually, this made the navigation bar appear collapsed immediately after a tab switch and then "slide" or jump into place once layout completed.

In release builds with simple views this is often hard to notice because the layout pass completes very quickly. With more complex views, or in debug builds, however, the intermediate state becomes visible. This is also reproducible in the Skip Showcase app in a debug build when taking a closer look.

To reproduce this in the Skip Showcase app:

  1. Install and launch a debug build of the app
  2. Start on the About tab
  3. Switch to the Showcase tab
  4. Observe the navigation bar during the initial layout of the Showcase view

Note: The jump only happens during the first layout of that view. After the Showcase tab has been laid out once, switching away and back again usually does not reproduce the issue since the navigation bar has already been measured.

Below is a before/after comparison of this example in the Skip Showcase app, slowed down to make the issue easier to see:

Before:
Before

After:
After

As shown above, before the change, the navigation bar is initially collapsed after switching tabs and becomes visible only after layout catches up. After the change, the navigation bar is present at the correct size immediately.

This is achieved by reserving an estimated top-bar height before the first real measurement is available. Once the actual top-bar size has been measured, the layout switches to the measured value. This keeps the content and navigation bar stable during initial layout and prevents the visible jump.

I also manually verified additional cases that previously showed navigation-bar jumps during initial layout, including NavigationStack inside .sheet and .fullScreenCover, using my own Skip app with more complex views and navigation flows. Those cases are also fixed with this change.

As part of the same layout improvements, this PR also reduces unnecessary empty space between the navigation bar and the top edge of sheets, making better use of the available sheet area:

Large Title (Before / After):
Before (Sheet Large)After (Sheet Large)

Inline Title (Before / After):
Before (Sheet Inline)After (Sheet Inline)


Thank you for contributing to the Skip project! Please review the contribution guide at https://skip.dev/docs/contributing/ for advice and guidance on making high-quality PRs.

Use this space to describe your change and add any labels (bug, enhancement, documentation, etc.) to help categorize your contribution.

Skip Pull Request Checklist:

  • REQUIRED: I have signed the Contributor Agreement
  • REQUIRED: I have tested my change locally with swift test
  • OPTIONAL: I have tested my change on an iOS simulator or device
  • OPTIONAL: I have tested my change on an Android emulator or device
  • REQUIRED: I have checked whether this change requires a corresponding update in the Skip Fuse UI repository (link related PR if applicable)
  • OPTIONAL: I have added an example of any UI changes to the Showcase sample app

  • AI was used to generate or assist with generating this PR. Please specify below how you used AI to help you, and what steps you have taken to manually verify the changes.

I used Codex to iteratively investigate and refine the fix for the NavigationStack layout issue. To verify the results, I tested multiple playground views in the Skip Showcase app and my own Skip app, which contains several navigation scenarios, including sheets, full-screen covers, tab bars, and nested navigation. All of these scenarios work properly after the bug fix.


@cla-bot cla-bot Bot added the cla-signed label Jul 3, 2026
@dfabulich

Copy link
Copy Markdown
Member

This code is extremely finicky, and has tests all over the showcase. I think it would help for you to list out exactly which playgrounds you tested and how.

One that you didn't explicitly call out is the SafeArea playground --> Geometry padding playground, which has facilities for hiding and showing the Navigation Bar, both with and without a sheet.

@fhasse95

fhasse95 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

This code is extremely finicky, and has tests all over the showcase. I think it would help for you to list out exactly which playgrounds you tested and how.

One that you didn't explicitly call out is the SafeArea playground --> Geometry padding playground, which has facilities for hiding and showing the Navigation Bar, both with and without a sheet.

Yes, I totally agree. Since this code is central and used in many places, I wanted to be extra careful. That's why I tried out the changes in various scenarios.

In Skip Showcase, I validated the changes using the following playgrounds:

  • Sheet Playground

    • Tested all options, including both .sheet and .fullScreenCover, with both inline and large navigation bar title modes.
  • NavigationStack Playground

    • Tested all available options, again with both inline and large navigation bar title modes.
  • Toolbar Playground

    • Tested all available options, including hiding/showing the navigation bar, custom navigation bar colors, etc.
  • SafeArea Playground

    • Tested all available options, with particular focus on .fullScreenCover, .sheet, and the Geometry Padding playground.
    • I also verified that features such as hiding/showing the navigation bar continued to behave correctly there.

During implementation, I first tested the changes in my own app across a variety of scenarios, refining the implementation iteratively based on my observations. Besides fixing the original issue, I specifically looked at things like switching between tabs, verifying the initial layout pass of the navigation bar, and the layout behavior of sheets and full-screen covers. I also made sure that neither the navigation bar nor the underlying content jumped during transitions.

Most of my testing was done on my Google Pixel 9, where I also verified gesture-driven interactions, such as slowly dismissing a sheet using the back gesture, to ensure the navigation bar behaves correctly throughout the interactive transition.

Once everything looked good there, I built Skip Showcase against my local SkipUI branch and went through all of the playgrounds above. To make sure I hadn't introduced any regressions, I repeatedly switched between my bugfix branch and the current main branch of SkipUI and compared the behavior side by side. Other than the initial layout pass bug now being fixed, I wasn't able to observe any side effects.

That said, I obviously can't completely rule out that I may have missed an edge case. So please feel free to try it with either your own app(s) or with Skip Showcase, and let me know if you spot anything that doesn't look right 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants