Skip to content

[ios][ui] Add scrollTargetBehavior and scrollTargetLayout modifiers#43955

Merged
intergalacticspacehighway merged 1 commit intoexpo:mainfrom
ramonclaudio:feat/expo-ui-scroll-position
Apr 6, 2026
Merged

[ios][ui] Add scrollTargetBehavior and scrollTargetLayout modifiers#43955
intergalacticspacehighway merged 1 commit intoexpo:mainfrom
ramonclaudio:feat/expo-ui-scroll-position

Conversation

@ramonclaudio
Copy link
Copy Markdown
Contributor

@ramonclaudio ramonclaudio commented Mar 15, 2026

Why

Split from the larger scroll position tracking PR per @intergalacticspacehighway feedback. Scroll position state and callbacks (onScrollPositionChange, scrollToID, id()) are deferred pending worklet callback support (#44214).

scrollTargetLayout was converted from a VStack/HStack prop to a modifier, matching SwiftUI's API surface.

What

  • scrollTargetBehavior() modifier: paging or viewAligned scroll snapping
  • scrollTargetLayout() modifier: marks a stack as a scroll target layout
  • ScrollTargetBehaviorModifier.swift, ScrollTargetLayoutModifier.swift registered in ViewModifierRegistry
  • TS exports in modifiers/index.ts with BuiltInModifier union entries
<ScrollView modifiers={[scrollTargetBehavior('paging')]}>
  <VStack modifiers={[scrollTargetLayout()]}>
    {items.map(item => (
      <Text key={item.id}>{item.text}</Text>
    ))}
  </VStack>
</ScrollView>

Test plan

  • yarn build passes
  • npx tsc --noEmit passes
  • yarn test passes (42/42)
  • yarn lint --fix passes (0 errors, 0 warnings)
  • Swift compiles (ExpoUI target)
  • Both modifiers have #available(iOS 17.0, tvOS 17.0, macOS 14.0, *) guards

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 15, 2026

Subscribed to pull request

File Patterns Mentions
docs/** @amandeepmittal
packages/expo-ui/** @Kudo, @behenate, @intergalacticspacehighway

Generated by CodeMention

@expo-bot expo-bot added bot: suggestions ExpoBot has some suggestions bot: passed checks ExpoBot has nothing to complain about and removed bot: suggestions ExpoBot has some suggestions labels Mar 15, 2026
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch from 35aefec to fe50c1c Compare March 15, 2026 14:47
Copy link
Copy Markdown
Member

@amandeepmittal amandeepmittal left a comment

Choose a reason for hiding this comment

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

Thank you for adding docs. Left some minor suggestions.

Also, let's wait for the technical review.

Comment thread packages/expo-ui/src/swift-ui/ScrollView/index.tsx Outdated
Comment thread packages/expo-ui/src/swift-ui/modifiers/index.ts Outdated
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch from fe50c1c to 0954ff8 Compare March 18, 2026 12:56
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch from 0954ff8 to c47a2ec Compare April 3, 2026 19:07
@ramonclaudio
Copy link
Copy Markdown
Contributor Author

Mind taking a look when you get a chance @intergalacticspacehighway?

@intergalacticspacehighway
Copy link
Copy Markdown
Contributor

intergalacticspacehighway commented Apr 6, 2026

@ramonclaudio thanks for the PR, sorry for the delay.

can scrollTargetLayout be added as modifier instead of prop?
Also, can we hold scrollPosition and other scroll related callbacks until #44214 is merged? This will allow us scroll callbacks run as UI worklet which I think makes more sense in the long run, as it won't block the JS thread since events are frequent.

@ramonclaudio ramonclaudio changed the title [ios][ui] Add scroll position tracking and scroll target behavior to ScrollView feat(expo-ui): add id, scrollTargetBehavior, and scrollTargetLayout modifiers Apr 6, 2026
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch from c47a2ec to 85da2b6 Compare April 6, 2026 13:36
@ramonclaudio ramonclaudio changed the title feat(expo-ui): add id, scrollTargetBehavior, and scrollTargetLayout modifiers [ios][ui] Add id, scrollTargetBehavior, and scrollTargetLayout modifiers Apr 6, 2026
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch 4 times, most recently from fe89c0b to c3f229a Compare April 6, 2026 14:01
@ramonclaudio ramonclaudio changed the title [ios][ui] Add id, scrollTargetBehavior, and scrollTargetLayout modifiers [ios][ui] Add scrollTargetBehavior and scrollTargetLayout modifiers Apr 6, 2026
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch 4 times, most recently from cc0f7d8 to cf1484b Compare April 6, 2026 14:22
@ramonclaudio
Copy link
Copy Markdown
Contributor Author

@intergalacticspacehighway no worries. I converted scrollTargetLayout from a prop to a modifier and stripped out all scroll position state/callbacks (onScrollPositionChange, scrollToID, scrollToEdge, scrollToPoint, id()).

Happy to rebase the scroll position tracking onto main once the worklet chain lands.

Comment thread packages/expo-ui/ios/Modifiers/ScrollTargetBehaviorModifier.swift Outdated
@ramonclaudio ramonclaudio force-pushed the feat/expo-ui-scroll-position branch from cf1484b to c095722 Compare April 6, 2026 16:03
Copy link
Copy Markdown
Member

@amandeepmittal amandeepmittal left a comment

Choose a reason for hiding this comment

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

Docs changes lg!

@intergalacticspacehighway are we planning to publish this for SDK 55?

@intergalacticspacehighway
Copy link
Copy Markdown
Contributor

@intergalacticspacehighway are we planning to publish this for SDK 55?

yeah, will be shipped with 55!

@intergalacticspacehighway intergalacticspacehighway merged commit 45d9efe into expo:main Apr 6, 2026
14 checks passed
intergalacticspacehighway pushed a commit that referenced this pull request Apr 6, 2026
…43955)

## Why

Split from the larger scroll position tracking PR per
@intergalacticspacehighway feedback. Scroll position state and callbacks
(`onScrollPositionChange`, `scrollToID`, `id()`) are deferred pending
worklet callback support (#44214).

`scrollTargetLayout` was converted from a VStack/HStack prop to a
modifier, matching SwiftUI's API surface.

## What

- `scrollTargetBehavior()` modifier: `paging` or `viewAligned` scroll
snapping
- `scrollTargetLayout()` modifier: marks a stack as a scroll target
layout
- `ScrollTargetBehaviorModifier.swift`,
`ScrollTargetLayoutModifier.swift` registered in `ViewModifierRegistry`
- TS exports in `modifiers/index.ts` with `BuiltInModifier` union
entries

```tsx
<ScrollView modifiers={[scrollTargetBehavior('paging')]}>
  <VStack modifiers={[scrollTargetLayout()]}>
    {items.map(item => (
      <Text key={item.id}>{item.text}</Text>
    ))}
  </VStack>
</ScrollView>
```

## Test plan

- `yarn build` passes
- `npx tsc --noEmit` passes
- `yarn test` passes (42/42)
- `yarn lint --fix` passes (0 errors, 0 warnings)
- Swift compiles (ExpoUI target)
- Both modifiers have `#available(iOS 17.0, tvOS 17.0, macOS 14.0, *)`
guards
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot: passed checks ExpoBot has nothing to complain about sdk-55

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants