Skip to content

Adding safe area edge detection for the scrollableAxes behavior#596

Merged
johnnewman-square merged 6 commits intomainfrom
johnnewman/task/scrollable-axes-edge-insets
Nov 13, 2025
Merged

Adding safe area edge detection for the scrollableAxes behavior#596
johnnewman-square merged 6 commits intomainfrom
johnnewman/task/scrollable-axes-edge-insets

Conversation

@johnnewman-square
Copy link
Contributor

@johnnewman-square johnnewman-square commented Oct 30, 2025

Adding a ScrollView API to allow clients to specify the edges that should be inset for the safe area when using the scrollableAxes content inset behavior. Before this change, content that landed outside the safe area but inside the scroll view bounds was not scrollable when using scrollableAxes. (See linked docs for details)

The goal of this update is to address the issue of content not being scrollable without introducing breaking API changes or large behavioral changes to ScrollView. A few alternative approaches could be:

  • turn on alwaysBouncesVertical and/or alwaysBounceHorizontal, which will cause scrollableAxes to honor the safe areas along both edges of the bouncing axes.
  • update client implementations to use the always content inset behavior. This would require refactoring the ScrollView layout to no longer produce a contentSize equal to the ScrollView bounds when using fittingWidth and fittingHeight.

The approach in this PR will enable the safe area behavior we need along a precise edge, like the bottom, while limiting the risk of regressions.

@johnnewman-square johnnewman-square force-pushed the johnnewman/task/scrollable-axes-edge-insets branch 3 times, most recently from b4f0481 to f3e9924 Compare November 1, 2025 14:38
@johnnewman-square johnnewman-square force-pushed the johnnewman/task/scrollable-axes-edge-insets branch from f3e9924 to 3b59837 Compare November 3, 2025 14:09
@johnnewman-square johnnewman-square changed the base branch from main to johnnewman/bug/traits-fix November 3, 2025 14:59
@johnnewman-square johnnewman-square marked this pull request as ready for review November 3, 2025 15:45
@johnnewman-square johnnewman-square requested a review from a team as a code owner November 3, 2025 15:45
johnnewman-square added a commit that referenced this pull request Nov 4, 2025
…Label (#597)

This reverts #590. During
integration testing, the original change caused KIF failures while
searching for labels with the `staticText` trait. The work to audit the
failures and make necessary code changes has been ticketed
[here](https://block.atlassian.net/browse/UI-9567).

This revert allows the changes in
#596 to be fully tested.
Base automatically changed from johnnewman/bug/traits-fix to main November 4, 2025 18:08
* main:
  Reverting the change to remove accessibility traits on the AttributedLabel (#597)
- Renaming processScrollableAxesEdgeConfigurations.
- Hoisting calculateConfiguration to the containing class and renaming its closure.
Copy link
Collaborator

@watt watt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very thorough and well-documented, nice work!


/// Determines whether `scrollableAxesSafeAreaEdges` has been modified by the
/// client or not.
public private(set) var didModifyScrollableAxesSafeAreaEdges: Bool = false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this meant to be used somewhere, or just cruft?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property is used to minimally apply the .bottom edge if the client hasn’t already set an edge, in this PR. If the client already configured the edge behavior, this property is used to avoid making further changes.

Copy link
Contributor Author

@johnnewman-square johnnewman-square Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After chatting in person, we discussed defaulting scrollableAxesSafeAreaEdges to nil, which we could then check against to determine if the client has modified the property.

(In the linked PR, we can ask those clients to supply the empty set if they want to opt out of the .bottom inset behavior.)

  • Remove didModifyScrollableAxesSafeAreaEdges and make scrollableAxesSafeAreaEdges default to nil.

/// the safe area.
///
/// The default value is the empty set, which leverages standard UIKit behavior.
public var scrollableAxesSafeAreaEdges: SafeAreaEdge = [] {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason not to make the default .all?

Copy link
Contributor Author

@johnnewman-square johnnewman-square Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. There were a few reasons that the empty set was used for the default:

  • Specifying SafeAreaEdge.all will have the same effect as setting the contentInsetAdjustmentBehavior to .always.
  • Including the .top edge breaks a number of snapshots that currently draw content within the top safe area. Similar to the snapshot breakages, .top can change expected behavior at runtime if a client aligned the ScrollView to the screen's top edge and manually adjusted its content to avoid the safe area by including padding around their elements.
  • Including the horizontal edges can also break snapshots and will enable horizontal scrolling in contexts that traditionally have not horizontally scrolled, like cases where we’re using ContentSize.fittingHeight and constraining the ScrollView to the screen's left or right edge.

I'd like to provide this control knob to clients without enabling it automatically, with the exception of this change, where we’re minimally enabling the .bottom edge. Happy to chat further though!


I can make .all internal and add a note explaining that clients should use ContentInsetAdjustmentBehavior.always instead:

  • Update SafeAreaEdge.all

- Using an autoclosure.
- Moving ScrollViewUITests into BlueprintUI-Tests and renaming.
- Making SafeAreaEdge.all internal.
- Changing ContentEdgeConfigurations.none to a constant.
Removing didModifyScrollableAxesSafeAreaEdges.
@johnnewman-square johnnewman-square merged commit f91cf8f into main Nov 13, 2025
8 checks passed
@johnnewman-square johnnewman-square deleted the johnnewman/task/scrollable-axes-edge-insets branch November 13, 2025 20:26
johnnewman-square added a commit that referenced this pull request Nov 13, 2025
## What's Changed
* Reverting the change to remove accessibility traits on the
AttributedLabel by @johnnewman-square in
#597
* Adding safe area edge detection for the scrollableAxes behavior by
@johnnewman-square in #596


**Full Changelog**:
6.3.1...6.4.0
maxg-square added a commit that referenced this pull request Nov 27, 2025
* main:
  chore: Release 6.5.0 (#600)
  refactor: Migrate Accessibility Infrastructure from Market Design System (#593)
  chore: Release 6.4.0 (#599)
  Adding safe area edge detection for the scrollableAxes behavior (#596)
  Reverting the change to remove accessibility traits on the AttributedLabel (#597)
  Update changelog for 6.3.1 release (#591)
  Fix warnings in Xcode 26 (#589)
  Apply empty accessibility traits to AttributedLabel if supplied traits is nil
  Bump rexml from 3.3.9 to 3.4.2
maxg-square added a commit that referenced this pull request Nov 27, 2025
* maxg/cache_1_equivalency:
  chore: Release 6.5.0 (#600)
  refactor: Migrate Accessibility Infrastructure from Market Design System (#593)
  chore: Release 6.4.0 (#599)
  Adding safe area edge detection for the scrollableAxes behavior (#596)
  Reverting the change to remove accessibility traits on the AttributedLabel (#597)
  Update changelog for 6.3.1 release (#591)
  Fix warnings in Xcode 26 (#589)
  Apply empty accessibility traits to AttributedLabel if supplied traits is nil
  Bump rexml from 3.3.9 to 3.4.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants