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.

ScrollView is the generic scrollable container — wrap any content that may exceed the available space, on either axis. List is the iOS-native scrollable list with row chrome, separators, and optional selection tracking. ForEach iterates over data to produce one child per item, and is what you typically pair with the lazy stacks inside a ScrollView or with sections inside a List.

ScrollView

A scrollable container for content that may exceed the available space.
ScrollView(children: Component): Component;
ScrollView(children: Component[]): Component;
ScrollView(props: { axis?: Axis; showsIndicators?: boolean }, children: Component[]): Component;
children
Component | Component[]
required
The scrollable content. Typically a stack or lazy stack containing the scroll content.
props
object
Configuration options for the scroll view.
Vertical scrolling
ScrollView([
    VStack({ spacing: 12 }, [
        ForEach(items, (item) =>
            Text(item.name).padding(8)
        )
    ])
])
Horizontal scrolling
ScrollView({ axis: "horizontal", showsIndicators: false }, [
    HStack({ spacing: 16 }, [
        ForEach(cards, (card) =>
            Image({ url: card.imageUrl })
                .frame({ width: 200, height: 150 })
                .cornerRadius(12)
        )
    ])
])
With a lazy stack For large data sets, use LazyVStack or LazyHStack inside a ScrollView for efficient rendering:
ScrollView([
    LazyVStack({ spacing: 8 }, [
        ForEach(allItems, (item) =>
            HStack({ spacing: 12 }, [
                Image({ url: item.thumbnail })
                    .frame({ width: 48, height: 48 }),
                Text(item.title)
            ])
            .padding(8)
        )
    ])
])
Hiding scroll indicators
ScrollView({ showsIndicators: false }, [
    VStack({ spacing: 16 }, [
        ForEach(photos, (photo) =>
            Image({ url: photo.url })
                .aspectRatio(1.5)
        )
    ])
])

List

A scrollable list with optional selection tracking.
List(children: Component[]): Component;
List<V = string>(props: { selection: V; setSelection: (value: V) => void }, children: Component[]): Component;
children
Component[]
required
The list content. Typically contains ForEach or Section components.
props
object
Configuration options for selection tracking.
Basic list
List([
    Text("Item 1"),
    Text("Item 2"),
    Text("Item 3")
])
With ForEach
List([
    ForEach(items, (item) =>
        Text(item.name)
    )
])
With sections
List([
    Section({ header: Text("Favorites") }, [
        ForEach(favorites, (fav) => Text(fav.name))
    ]),
    Section({ header: Text("Recent") }, [
        ForEach(recent, (item) => Text(item.name))
    ])
])
With selection tracking
const body = () => {
    const [selected, setSelected] = useState("")

    return List(
        { selection: selected, setSelection: setSelected },
        [
            ForEach(items, (item) =>
                Text(item.name).tag(item.id)
            )
        ]
    )
}
List provides built-in scrolling — you don’t need to wrap it in a ScrollView. For selection tracking, each row should have a .tag() modifier so the list can identify which item is selected. Customize with .listStyle(), .listRowBackground(), and .listRowSeparator(). For a non-list scrollable layout, use ScrollView with LazyVStack.

ForEach

Iterates over data to produce components, creating one child per item.
ForEach<T>(data: T[], content: (item: T, index: number) => Component): Component;
ForEach<T>(subviews: Component, content: ({ subview: T }) => Component): Component;
data
T[]
required
An array of items to iterate over. Each item is passed to the content function.
content
(item: T, index: number) => Component
required
A function that returns a component for each item. Receives the item and its index.
subviews
Component
required
Subviews overload: a component whose children are decomposed into individual subviews for rearranging or inspection.
content
({ subview: T }) => Component
required
Subviews overload: a function that receives each subview and returns a component.
Basic iteration
ForEach(["Apple", "Banana", "Cherry"], (fruit) =>
    Text(fruit)
)
Using the index
ForEach(items, (item, index) =>
    HStack([
        Text(`${index + 1}.`),
        Text(item.name)
    ])
)
Inside a layout container
VStack({ spacing: 8 }, [
    ForEach(users, (user) =>
        HStack({ spacing: 12 }, [
            Circle()
                .fill(Color("blue"))
                .frame({ width: 32, height: 32 }),
            Text(user.name)
        ])
    )
])
Subview decomposition Use the subviews overload to inspect and rearrange children of an existing component:
ForEach(
    VStack([Text("A"), Text("B"), Text("C")]),
    ({ subview }) => subview.padding(8)
)
Each call to the content function should return exactly one component. Use Group to return multiple components as one. The index parameter is zero-based. The subviews overload enables view decomposition patterns, letting you restructure existing component trees without rebuilding them.

See also

  • LazyVStack — lazy vertical stack for long scrollable lists
  • LazyHStack — lazy horizontal stack for carousels
  • Section — grouping with headers and footers in a List
  • Group — return multiple components as one
  • Axis — scroll direction values