Modifier types
Constants, hooks and types that the SwiftUI modifiers use.
Constants
Animation
Built-in animation presets for the animation modifier. Presets:
- Timing presets (
easeInOut,easeIn,easeOut,linear) acceptTimingAnimationParams. springacceptsSpringAnimationParams.interpolatingSpringacceptsInterpolatingSpringAnimationParams.- Chaining returns
ChainableAnimationType.
Example
import { Host, VStack } from '@expo/ui/swift-ui';
import { animation, Animation } from '@expo/ui/swift-ui/modifiers';
function Example() {
const [isExpanded, setIsExpanded] = useState(false);
return (
<Host style={{ flex: 1 }}>
<VStack modifiers={[animation(Animation.spring({ duration: 0.8 }), isExpanded)]}>
//...
</VStack>
</Host>
);
}shapes
Shape builders for modifiers that accept shapes, such as background and containerShape.
Shapes: roundedRectangle, capsule, rectangle, ellipse, circle, containerRelativeShape.
Example
import { background, shapes } from '@expo/ui/swift-ui/modifiers';
import { Text, Host } from '@expo/ui/swift-ui';
function Example() {
return (
<Host>
<Text
modifiers={[
background('#000', shapes.roundedRectangle({ cornerRadius: 12 })),
]}
>
Hello, world!
</Text>
</Host>
);
}Hooks
useScrollGeometryChange(callback)
iOS 18+
| Parameter | Type |
|---|---|
callback(optional) | (geometry: ScrollGeometry) => void |
Fires when the scroll geometry changes — i.e., on every scroll update and on container/content size changes. Use to drive continuous progress UI such as page indicators, parallax, or fractional offsets.
If the callback is marked with the 'worklet' directive, it runs synchronously on the UI thread (no JS-thread round-trip); otherwise it is delivered asynchronously as a regular JS event. Both paths share the same native modifier — the worklet variant is automatically wrapped in a WorkletCallback shared object whose lifetime is managed by the hook.
This is a hook because the worklet path requires a stable shared-object reference across renders. Call it at the top of your component, then include the returned modifier in your modifiers array.
Apply to a SwiftUI ScrollView (and other scrollable views). On iOS below 18.0 the modifier is a no-op.
Returns: ModifierConfig | null
See: Official SwiftUI documentation.
Example
const geometryModifier = useScrollGeometryChange((g) => {
'worklet';
progress.value = g.contentOffsetX / g.containerWidth;
});
<ScrollView modifiers={[geometryModifier]} />Event subscriptions
createModifierWithEventListener(type, eventListener, params)
| Parameter | Type |
|---|---|
type | string |
eventListener | (args: any) => void |
params(optional) | Record<string, any> |
Creates a modifier with an event listener.
Returns: ModifierConfig
createViewModifierEventListener(modifiers)
| Parameter | Type | Description |
|---|---|---|
modifiers | ModifierConfig[] | An array of modifier configs to extract event listeners from. |
Create an event listener for a view modifier.
Returns: GlobalEvent
Interfaces
ModifierConfig
Base interface for all view modifiers. All modifiers must have a type field and can include arbitrary parameters.
| Property | Type | Description |
|---|---|---|
| $type | string | - |
| eventListener(optional) | (args: any) => void | - |
Types
AccessibilityTrait
Literal type: string
The set of accessibility traits that can be added to or removed from a view with accessibilityAddTraits and accessibilityRemoveTraits.
See: Official SwiftUI documentation.
Acceptable values are: 'isButton' | 'isHeader' | 'isImage' | 'isSelected' | 'isLink' | 'isModal' | 'isSummaryElement' | 'updatesFrequently' | 'startsMediaSession' | 'allowsDirectInteraction' | 'causesPageTurn' | 'isToggle' | 'playsSound' | 'isStaticText' | 'isSearchField' | 'isKeyboardKey' | 'isTabBar'
ChainableAnimationType
| Property | Type | Description |
|---|---|---|
| [VALUE_SYMBOL] | () => AnimationObject | - |
| delay | (delay: number) => ChainableAnimationType | Adds a delay before the animation starts (in seconds). |
| repeat | (params: { autoreverses: boolean, repeatCount: number }) => ChainableAnimationType | Repeats the animation the given number of times. |
Color
Literal type: union
Acceptable values are: string | ColorValue | NamedColor
ContainerBackgroundPlacement
Literal type: string
Acceptable values are: 'widget' | 'navigation' | 'navigationSplitView'
DatePickerStyleType
Literal type: string
Acceptable values are: 'automatic' | 'compact' | 'graphical' | 'wheel'
DiscreteSymbolEffectValue
Literal type: union
Equatable primitive accepted as a discrete effect trigger.
Acceptable values are: number | string | boolean
DynamicTypeSizeValue
Literal type: string
A standard size for Dynamic Type, from xSmall through the five accessibility sizes. Mirrors SwiftUI's DynamicTypeSize.
Acceptable values are: 'xSmall' | 'small' | 'medium' | 'large' | 'xLarge' | 'xxLarge' | 'xxxLarge' | 'accessibility1' | 'accessibility2' | 'accessibility3' | 'accessibility4' | 'accessibility5'
EnvironmentConfig
Type: object shaped as below:
| Property | Type | Description |
|---|---|---|
| key | 'editMode' | - |
| value | 'active' | 'inactive' | 'transient' | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| key | 'colorScheme' | - |
| value | 'light' | 'dark' | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| key | 'locale' | - |
| value | string | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| key | 'timeZone' | - |
| value | string | - |
GaugeStyleType
Literal type: string
Acceptable values are: 'automatic' | 'circular' | 'circularCapacity' | 'linear' | 'linearCapacity'
GlobalEvent
| Property | Type | Description |
|---|---|---|
| onGlobalEvent | (event: { nativeEvent: GlobalEventPayload }) => void | - |
GlobalEventPayload
| Property | Type | Description |
|---|---|---|
| eventName(index signature) | Record<string, any> | - |
IndexViewStyleConfig
Configuration for the indexViewStyle modifier.
| Property | Type | Description |
|---|---|---|
| backgroundDisplayMode(optional) | PageIndexBackgroundDisplayMode | Translucent background behind the page indicator dots. Useful when the dots sit on top of dark or busy content. Default: 'automatic' |
InterpolatingSpringAnimationParams
| Property | Type | Description |
|---|---|---|
| bounce(optional) | number | Extra bounce to apply to the spring animation. |
| damping(optional) | number | The damping applied to the spring. |
| duration(optional) | number | Total animation duration (in seconds). |
| initialVelocity(optional) | number | The initial velocity of the animation. |
| mass(optional) | number | The mass attached to the spring. |
| stiffness(optional) | number | The stiffness of the spring. |
ListStyle
Literal type: string
Acceptable values are: 'automatic' | 'plain' | 'inset' | 'insetGrouped' | 'grouped' | 'sidebar'
MenuOrderType
Literal type: string
Acceptable values are: 'automatic' | 'fixed' | 'priority'
ObservableState
Observable state shared between JavaScript and native views (Jetpack Compose on Android and SwiftUI on iOS).
Type: SharedObject extended by:
| Property | Type | Description |
|---|---|---|
| onChange | [listener] | null | A single listener invoked on the native UI runtime whenever the value changes (after iOS didSet and Android's setter). Assigning replaces the previous listener; assign null to clear. The initial value does not fire onChange. The callback must be a worklet so it can run synchronously on the UI thread. Attach it inside useEffect and clear it in the cleanup so the listener lifecycle matches the component lifecycle. Example |
const state = useNativeState(0);
useEffect(() => {
state.onChange = (value) => {
'worklet';
console.log('changed to', value);
};
}, []);|
| value | T | The current value. Writes from a UI worklet are synchronous and immediately readable. Writes from the JS thread are scheduled to the UI thread asynchronously, the new value is not readable until the update has been applied. Prefer writing from a worklet when you need synchronous updates |
| get | () => T | Reads the current value. A React Compiler compliant alternative to reading .value |
| set | (value: T) => void | Writes a new value. A React Compiler-compliant alternative to assigning .value |
PageIndexBackgroundDisplayMode
Literal type: string
Acceptable values are: 'automatic' | 'always' | 'never' | 'interactive'
PageIndexDisplayMode
Literal type: string
Acceptable values are: 'automatic' | 'always' | 'never'
PickerStyleType
Literal type: string
Acceptable values are: 'automatic' | 'inline' | 'menu' | 'navigationLink' | 'palette' | 'segmented' | 'wheel'
PresentationBackgroundInteractionType
Presentation background interaction type.
Type: 'automatic' or 'enabled' or 'disabled' or object shaped as below:
| Property | Type | Description |
|---|---|---|
| detent | PresentationDetent | - |
| type | 'enabledUpThrough' | - |
PresentationDetent
Presentation detent type for controlling sheet heights.
'medium': System medium height (approximately half screen)'large': System large height (full screen){ fraction: number }: Fraction of screen height (0-1, for example, 0.4 equals 40% of screen){ height: number }: Fixed height in points
Type: 'medium' or 'large' or object shaped as below:
| Property | Type | Description |
|---|---|---|
| fraction | number | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| height | number | - |
PresentationSizingType
Literal type: string
Sizing behavior for a sheet presentation.
'automatic': The system default sizing.'fitted': Sizes the sheet to fit its content.'form': A compact, centered form sheet.'page': A larger page sheet.
Acceptable values are: 'automatic' | 'fitted' | 'form' | 'page'
ProgressViewStyleType
Literal type: string
Acceptable values are: 'automatic' | 'linear' | 'circular'
Shape
Literal type: ReturnType
Acceptable values are: ReturnType<shapes.roundedRectangle> | ReturnType<shapes.capsule> | ReturnType<shapes.rectangle> | ReturnType<shapes.ellipse> | ReturnType<shapes.circle> | ReturnType<shapes.containerRelativeShape>
SpringAnimationParams
| Property | Type | Description |
|---|---|---|
| blendDuration(optional) | number | The duration over which to blend between animations (in seconds). |
| bounce(optional) | number | Extra bounce to apply to the spring animation. |
| dampingFraction(optional) | number | The amount of damping applied to the spring's motion. |
| duration(optional) | number | Total animation duration (in seconds). |
| response(optional) | number | The spring's response time (in seconds). |
StrokeStyle
The characteristics of a stroke that traces a path.
See: Official SwiftUI documentation.
| Property | Type | Description |
|---|---|---|
| dash(optional) | number[] | The lengths of alternating painted and unpainted segments. An empty array draws a solid line. Default: [] |
| dashPhase(optional) | number | How far into the dash pattern the line starts. Default: 0 |
| lineCap(optional) | 'butt' | 'round' | 'square' | The endpoint style of a line segment. Default: 'butt' |
| lineJoin(optional) | 'miter' | 'round' | 'bevel' | The join type where line segments meet. Default: 'miter' |
| lineWidth(optional) | number | The width of the stroked line. Default: 1 |
| miterLimit(optional) | number | The limit past which a miter join is replaced by a bevel. Default: 10 |
SymbolEffect
Literal type: union
Acceptable values are: AppearSymbolEffect | BounceSymbolEffect | BreatheSymbolEffect | DisappearSymbolEffect | DrawOffSymbolEffect | DrawOnSymbolEffect | PulseSymbolEffect | RotateSymbolEffect | ScaleSymbolEffect | VariableColorSymbolEffect | WiggleSymbolEffect
SymbolEffectOptions
Animation options for a symbol effect.
See: Official Apple documentation.
| Property | Type | Description |
|---|---|---|
| repeat(optional) | 'continuous' | 'nonRepeating' | { count: number, delay: number } | How the effect repeats. Omit for the effect's natural cadence |
'nonRepeating'— play exactly once.'continuous'— smooth, indefinite repetition (iOS 18+).{ count?, delay? }— periodic repetition with optional count and delay in seconds (iOS 18+).
|
| speed(optional) | number | Animation speed multiplier (1.0 = default). |
TabViewStyleConfig
Configuration for the tabViewStyle modifier.
'page'— swipeable horizontal pager with optional dot indicators.'automatic'— SwiftUI's default tab-bar style.'sidebarAdaptable'— iOS 18+. Sidebar on iPad/Mac, bottom bar on iPhone.
Type: object shaped as below:
| Property | Type | Description |
|---|---|---|
| indexDisplayMode(optional) | PageIndexDisplayMode | Visibility of the page indicator dots. Only meaningful for the page style. Default: 'automatic' |
| type | 'page' | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| type | 'automatic' | - |
Or object shaped as below:
| Property | Type | Description |
|---|---|---|
| type | 'sidebarAdaptable' | - |
TimingAnimationParams
| Property | Type | Description |
|---|---|---|
| duration(optional) | number | Total animation duration (in seconds). |
UnitPointValue
Literal type: string
Acceptable values are: 'zero' | 'topLeading' | 'top' | 'topTrailing' | 'leading' | 'center' | 'trailing' | 'bottomLeading' | 'bottom' | 'bottomTrailing'
Sources
The original Expo docs for this page:
- Modifiers (
source-of-truth/versions/v57.0.0/sdk/ui/swift-ui/modifiers.md)