Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt

Use this file to discover all available pages before exploring further.

These iOS-only modifiers configure scrollable containers — ScrollView, List, and TextEditor. They control the background, indicator visibility, bounce/stretch edge effects, programmatic position, and scroll snapping. For carousel-style snapping, pair scrollTargetLayout (on the inner container) with scrollTargetBehavior (on the outer ScrollView). Most other modifiers are applied directly to the scrolling component.

scrollContentBackground

Controls the visibility of the scroll content background.
.scrollContentBackground(visibility: "hidden" | "visible"): Component
visibility
"hidden" | "visible"
required
Whether to show or hide the default background. Use "hidden" to remove the system background from Lists and other scrollable containers.
Hide list background Remove the default grouped list background to show a custom background underneath.
List([
    Section("Settings", [
        Text("Account"),
        Text("Notifications"),
        Text("Privacy"),
    ])
])
    .scrollContentBackground("hidden")
    .background(Color("blue"))
Transparent text editor
const body = () => {
    const [text, setText] = useState("")
    return TextEditor({ text, setText })
        .scrollContentBackground("hidden")
        .background(Material("thin"))
}

scrollPosition

Tracks and controls scroll position by child view ID.
.scrollPosition(props: {
    id: string | null;
    setId: (value: string | null) => void;
}): Component
props
object
required
Track scroll position
const body = () => {
    const [scrollId, setScrollId] = useState(null)
    return ScrollView([
        ForEach(items, (item) =>
            Text(item.name)
                .padding(16)
                .id(item.id)
        )
    ]).scrollPosition({ id: scrollId, setId: setScrollId })
}
Programmatic scroll
const body = () => {
    const [scrollId, setScrollId] = useState(null)
    return VStack([
        Button("Scroll to top", () => setScrollId("item-0")),
        ScrollView([
            ForEach(items, (item) =>
                Text(item.name)
                    .padding(16)
                    .id(item.id)
            )
        ]).scrollPosition({ id: scrollId, setId: setScrollId })
    ])
}
Children must have .id() set for scroll position tracking to work. Use with scrollTargetLayout and scrollTargetBehavior for snapping scroll views.

scrollIndicators

Controls the visibility of scroll indicators on a scroll view.
.scrollIndicators(visibility: 'automatic' | 'visible' | 'hidden' | 'never')
.scrollIndicators(props: { visibility?: 'automatic' | 'visible' | 'hidden' | 'never'; axes?: Axis })
visibility
string
required
The scroll indicator visibility. One of:
  • "automatic" — system default behavior (show when scrolling, hide when idle)
  • "visible" — always show scroll indicators
  • "hidden" — hide scroll indicators when possible
  • "never" — never show scroll indicators
props
object
required
Object form for axis-targeted control.
Hide scroll indicators
ScrollView([
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollIndicators("hidden")
Never show indicators
ScrollView([
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollIndicators("never")
Hide only vertical indicators
ScrollView({ axes: "vertical" }, [
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollIndicators({
    visibility: "hidden",
    axes: "vertical"
})
The difference between "hidden" and "never" is that "hidden" allows the system to show indicators in certain accessibility contexts, while "never" unconditionally hides them.

scrollEdgeEffectHidden

Hides the scroll edge bounce or stretch effect.
.scrollEdgeEffectHidden(isHidden?: boolean): Component
isHidden
boolean
default:"true"
Whether to hide the edge effect. Defaults to true when called without arguments.
Hide the bounce effect
ScrollView([
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollEdgeEffectHidden()
Conditionally hide
ScrollView([
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollEdgeEffectHidden(false)

scrollEdgeEffectStyle

Sets the visual style for the scroll edge effect.
.scrollEdgeEffectStyle(props: {
    style?: "automatic" | "soft" | "hard";
    edges?: EdgeSet;
}): Component
props
object
required
Soft edge effect
ScrollView([
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollEdgeEffectStyle({ style: "soft" })
Hard effect on specific edges
ScrollView([
    ForEach(items, (item) =>
        Text(item.name).padding(12)
    )
]).scrollEdgeEffectStyle({ style: "hard", edges: "vertical" })

scrollTargetLayout

Marks a container’s children as scroll snap targets.
.scrollTargetLayout(isEnabled?: boolean): Component
isEnabled
boolean
default:"true"
Whether the layout acts as a scroll target. Defaults to true.
Horizontal card carousel Apply .scrollTargetLayout() to the inner container (e.g., HStack) and .scrollTargetBehavior("viewAligned") to the outer ScrollView.
ScrollView({ axis: "horizontal" }, [
    HStack({ spacing: 16 }, items.map((item) =>
        VStack([
            Image({ url: item.image })
                .resizable()
                .scaledToFill()
                .frame({ width: 280, height: 180 })
                .clipped(),
            Text(item.title)
                .font("headline")
                .padding(12),
        ])
            .background(Color("white"))
            .cornerRadius(12)
            .shadow({ radius: 4 })
    )).scrollTargetLayout()
]).scrollTargetBehavior("viewAligned")
Disable snapping
HStack({ spacing: 16 }, items.map((item) =>
    Text(item.name)
        .frame({ width: 200, height: 100 })
)).scrollTargetLayout(false)

scrollTargetBehavior

Sets scroll snapping behavior for a ScrollView.
.scrollTargetBehavior(behavior: "viewAligned" | "paging"): Component
behavior
"viewAligned" | "paging"
required
The snapping behavior:
  • "viewAligned" — snaps to child views marked with .scrollTargetLayout()
  • "paging" — snaps to page boundaries (one screen width or height at a time)
View-aligned snapping Combine with scrollTargetLayout on the inner container to snap to individual child views.
ScrollView({ axis: "horizontal" }, [
    HStack({ spacing: 16 }, items.map((item) =>
        Text(item.name)
            .frame({ width: 300, height: 200 })
            .background(Color("blue"))
            .cornerRadius(12)
    )).scrollTargetLayout()
]).scrollTargetBehavior("viewAligned")
Paging behavior
ScrollView({ axis: "horizontal" }, [
    HStack({ spacing: 0 }, pages.map((page) =>
        Image({ url: page.url })
            .resizable()
            .scaledToFill()
            .frame({ width: 375, height: 600 })
            .clipped()
    ))
]).scrollTargetBehavior("paging")

See also

  • ScrollView — scrollable container
  • List — scrollable list with native row chrome
  • List chrome — list-specific row and style modifiers
  • Axis — axis values for indicator targeting
  • EdgeSet — edge selectors for edge effects