Reserved Layout Regions

GeometryReader in Scripting is the equivalent of SwiftUI’s GeometryReader. It provides layout information about the container in which its content is placed, including size, safe-area insets, and (on supported systems) container corner insets.

This component is essential for building responsive layouts that depend on the parent container’s geometry.


GeometryProxy

When GeometryReader constructs its child content, it injects a GeometryProxy instance into the children callback. This proxy exposes real-time layout information about the container.

interface GeometryProxy {
  readonly size: Size;
  readonly safeAreaInsets: {
    leading: number;
    top: number;
    trailing: number;
    bottom: number;
  };
  /**
   * Requires iOS 26.0+.
   */
  readonly containerCornerInsets: {
    bottomLeading: Size;
    bottomTrailing: Size;
    topLeading: Size;
    topTrailing: Size;
  } | null;
}

GeometryProxy Properties

1. size

readonly size: Size

The actual size of the container during layout.

Size structure

type Size = {
  width: number
  height: number
}

Use this property when calculating adaptive layout behavior, such as scaling, alignment, or proportional spacing.


2. safeAreaInsets

readonly safeAreaInsets: {
  leading: number
  top: number
  trailing: number
  bottom: number
}

Represents the safe-area insets of the current container. This ensures content does not overlap with the device notch, home indicator, or other system UI elements.

Common use cases

  • Adjusting content away from the screen edges
  • Implementing custom navigation bars or toolbars
  • Ensuring layout compatibility across devices

3. containerCornerInsets (iOS 26.0+)

readonly containerCornerInsets: {
  bottomLeading: Size
  bottomTrailing: Size
  topLeading: Size
  topTrailing: Size
} | null

Available only on iOS 26+. Provides layout insets corresponding to the physical or visual rounded corners of the container.

Use cases

  • Adapting UI for windowed environments
  • Handling rounded container corners (Stage Manager, split view, floating scenes)
  • Performing precision layout aligned to dynamic corner geometry

If the platform does not support it, the value will be null.


GeometryReader Component

type GeometryReaderProps = {
  children: (proxy: GeometryProxy) => VirtualNode;
};
declare const GeometryReader: FunctionComponent<GeometryReaderProps>;

Props

NameTypeRequiredDescription
children(proxy: GeometryProxy) => VirtualNodeYesA callback that receives the geometry proxy and returns the view content.

Behavior

  1. GeometryReader occupies the available space in its parent.
  2. During layout, it computes size, safe-area insets, and corner insets.
  3. It passes these values to the children(proxy) callback.
  4. The returned VirtualNode content is laid out using these values.

This behavior matches SwiftUI’s GeometryReader model.


Example: Centered Content

import { GeometryReader, Text, VStack } from "scripting"

function View() {
  return <GeometryReader>
    {(proxy) => {
      return <VStack
        frame={{
          width: proxy.size.width,
          height: proxy.size.height,
          alignment: "center"
        }}
      >
        <Text>Hello Geometry</Text>
        <Text>
          width: {proxy.size.width}
        </Text>
        <Text>
          height: {proxy.size.height}
        </Text>
      </VStack>
    }}
  </GeometryReader>
}

Example: Adjusting Layout by Safe Area

<GeometryReader>
  {(proxy) => {
    return <VStack
      padding={{
        top: proxy.safeAreaInsets.top,
        bottom: proxy.safeAreaInsets.bottom
      }}
    >
      <Text>Content inside safe area.</Text>
    </VStack>
  }}
</GeometryReader>

Example (iOS 26+): Using containerCornerInsets

<GeometryReader>
  {(proxy) => {
    const corners = proxy.containerCornerInsets
    return <Text>
      {corners == null
        ? "Corner insets not available"
        : `Top Leading Corner: ${corners.topLeading.width}, ${corners.topLeading.height}`
      }
    </Text>
  }}
</GeometryReader>

Best Practices

  • Use GeometryReader only when needed, as it creates a flexible layout container.
  • Prefer using it for adaptive, responsive layouts where container size matters.
  • Avoid placing complex or deeply nested views inside GeometryReader unless required.

Concentric corner radii (iOS 27.0+)

proxy.concentricCornerRadii returns { topLeading, bottomLeading, bottomTrailing, topTrailing }, in points. It describes the concentric rectangle corner radii appropriate for the current geometry. It is null on earlier systems and when SwiftUI has no corner information. It is a layout snapshot and updates alongside size and safeAreaInsets; it does not retain a native GeometryProxy or expose arbitrary-frame queries.


Reserved regions (iOS 27.1+)

proxy.reservedRegions(kind, options?) returns layout snapshots for kind: "occlusion" | "division". Each ReservedRegion contains kind, frame ({ x, y, width, height }), margins ({ top, bottom, leading, trailing }) and isActive. Frames use the GeometryReader's local coordinates in points. Earlier systems return an empty array.

By default both kinds query active regions with mirrored layout direction. For a non-default query, declare it in GeometryReader.reservedRegionQueries and use the same options when calling reservedRegions. Options are includeInactive?: boolean and layoutDirectionBehavior?: "fixed" | "mirrors" | { mirrors: "leftToRight" | "rightToLeft" }. Calling an undeclared non-default query throws. Frames and regions are snapshots of the current layout build; retaining a proxy does not keep it live.

Use regions to avoid placing controls beneath a fold or occlusion, while preserving reading order and access to all common tasks. The result may be empty even on a supported system.

<GeometryReader reservedRegionQueries={[{ kind: "division", includeInactive: true }]}>
  {proxy => <Text>{proxy.reservedRegions("division", { includeInactive: true }).length} division regions</Text>}
</GeometryReader>