Skip to content

Pass checkEdges to avoid recomposition/layout shift in hot code paths#365

Open
dfabulich wants to merge 2 commits intoskiptools:mainfrom
dfabulich:isal-edges
Open

Pass checkEdges to avoid recomposition/layout shift in hot code paths#365
dfabulich wants to merge 2 commits intoskiptools:mainfrom
dfabulich:isal-edges

Conversation

@dfabulich
Copy link
Copy Markdown
Contributor

@dfabulich dfabulich commented Mar 25, 2026

IgnoresSafeAreaLayout doesn't expand into its expandInto edges on first render unless the caller specifically opts into that behavior by passing the edges with checkEdges. Instead, it will eventually get called back in onGloballyPositionedInWindow, at which point we know for certain which edges we should expand into.

If we don't check the correct edges on first render, the UI may display incorrect layout temporarily and then shift to the correct position (or, at the very least, do an unnecessary recomposition).

In my experiments with the Showcase and my own app, NavigationStack and TabView basically always do expand into their edges; similarly, the .ignoresSafeArea() modifier edges are very very likely to be expanded into.

Passing the expandInto edges in checkEdges saves a recomposition (and often a layout shift) in very hot code paths.

I've also added a logTag parameter to IgnoresSafeAreaLayout, and added debug logging, so we can see when/where recompositions happen. (This seems to be a common area for recompositions that cause layout shifts. I think the log noise will probably pay off.)

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 in 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 Cursor to add the logTag parameter on all of the ISAL callers. Then, I manually tested the Showcase in the following playgrounds, keeping a log of SkipUI.ISAL log entries:

  • Content Margins
  • GeometryReader
  • Grid
  • List
  • NavigationStack
  • Safe Area
  • Scroll View
  • Searchable
  • Tab View
  • Table
  • Toolbar

Then, I added my changes and redid the testing. I found that my changes reduced recompositions and reduced layout shift in the Showcase app.

This seems to be a common area for recompositions that cause layout shifts. I think the log noise will probably pay off.
IgnoresSafeAreaLayout doesn't expand into its `expandInto` edges on first render unless the caller specifically opts into that behavior by passing the edges with `checkEdges`. Instead, it will eventually get called back in `onGloballyPositionedInWindow`, at which point we know for certain which edges we should expand into.

If we don't check the correct edges on first render, the UI may display incorrect layout temporarily and then shift to the correct position (or, at the very least, do an unnecessary recomposition).

In my experiments with the Showcase and my own app, `NavigationStack` and `TabView` basically always do expand into their edges; similarly, the `.ignoresSafeArea()` modifier edges are very very likely to be expanded into.

Passing the `expandInto` edges in `checkEdges` saves a recomposition (and often a layout shift) in very hot code paths.
@cla-bot cla-bot bot added the cla-signed label Mar 25, 2026
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.

1 participant