> ## 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.

# GeometryReader

> Provides the parent container's geometry to a content builder function.

export const PlatformStatuses = ({statuses}) => {
  const StatusBadge = ({status, label}) => {
    const styles = {
      green: {
        backgroundColor: '#dcfce7',
        color: '#166534'
      },
      orange: {
        backgroundColor: '#fed7aa',
        color: '#9a3412'
      },
      red: {
        backgroundColor: '#fecaca',
        color: '#991b1b'
      },
      gray: {
        backgroundColor: '#f3f4f6',
        color: '#4b5563'
      }
    };
    const baseStyle = {
      display: 'inline-flex',
      alignItems: 'center',
      padding: '0.125rem 0.625rem',
      borderRadius: '9999px',
      fontSize: '0.875rem',
      fontWeight: '500'
    };
    const colorStyle = styles[status] || styles.green;
    return <span style={{
      ...baseStyle,
      ...colorStyle
    }}>
        {label || status}
      </span>;
  };
  const STATUS_CONFIG = {
    supported: {
      label: "Supported",
      color: "green"
    },
    partial: {
      label: "Partial",
      color: "orange"
    },
    "not-implemented": {
      label: "Not Implemented",
      color: "gray"
    }
  };
  const renderCard = (platform, value) => {
    if (!value) return null;
    const {status, note} = typeof value === "string" ? {
      status: value
    } : value;
    const config = STATUS_CONFIG[status];
    if (!config) return null;
    const titleMap = {
      ios: "SwiftUI",
      android: "Jetpack Compose",
      web: "Web"
    };
    return <Card key={platform} title={titleMap[platform] || platform}>
          <StatusBadge status={config.color} label={config.label} />
          {note && <div style={{
      marginTop: '0.5rem',
      fontSize: '0.875rem',
      color: '#6b7280'
    }}>
              {note}
            </div>}
      </Card>;
  };
  if (statuses == null) {
    return null;
  }
  return <Columns cols="3">
      {Object.entries(statuses).map(([platform, value]) => renderCard(platform, value))}
    </Columns>;
};

export const ComposeJS = ({code, name, height}) => {
  const encodedCode = useMemo(() => {
    if (!code) return "";
    try {
      return btoa(code);
    } catch (e) {
      console.error("Failed to encode code", e);
      return "";
    }
  }, [code]);
  if (!encodedCode) {
    return null;
  }
  return <iframe src={`https://www.metabind.ai/embed?code=${encodedCode}&name=${name ?? 'Example'}`} loading="lazy" style={{
    width: "100%",
    height: height || '350px',
    border: "1px solid #e5e7eb",
    borderRadius: "var(--rounded-2xl,1rem)",
    overflow: "hidden"
  }} title="ComposeJS Preview" />;
};

```typescript theme={null}
GeometryReader(content: (geometry: GeometryProxy) => Component): Component;
```

<ParamField path="content" type="(geometry: GeometryProxy) => Component" required>
  A function that receives a GeometryProxy and returns a component. The proxy provides the container's size, safe area insets, and frame information.
</ParamField>

## GeometryProxy

The `geometry` parameter passed to the content function has the following properties:

<ParamField path="size" type="{ width: number; height: number }">
  The container's size in points.
</ParamField>

<ParamField path="safeAreaInsets" type="{ top: number; leading: number; bottom: number; trailing: number }">
  The safe area insets of the container.
</ParamField>

<ParamField path="containerCornerInsets" type="object" optional>
  Corner insets for rounded container shapes (e.g. device corners).

  <Expandable title="properties">
    <ParamField path="topLeading" type="{ width: number; height: number }">Corner inset for the top-leading corner.</ParamField>
    <ParamField path="topTrailing" type="{ width: number; height: number }">Corner inset for the top-trailing corner.</ParamField>
    <ParamField path="bottomLeading" type="{ width: number; height: number }">Corner inset for the bottom-leading corner.</ParamField>
    <ParamField path="bottomTrailing" type="{ width: number; height: number }">Corner inset for the bottom-trailing corner.</ParamField>
  </Expandable>
</ParamField>

## Methods

<ParamField path="frame" type="(coordinateSpace: CoordinateSpace) => GeometryRect">
  Returns the frame rectangle in the given coordinate space. CoordinateSpace is one of `"global"` (relative to the screen), `"local"` (relative to the component itself), `"scrollView"` (relative to the nearest scroll view), or any custom string registered via `.coordinateSpace()`.
</ParamField>

<ParamField path="bounds" type="(coordinateSpace: CoordinateSpace) => GeometryRect | {}">
  Returns the bounds of a named coordinate space, or an empty object if unavailable.
</ParamField>

## Support

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: { status: "partial", note: "safeAreaInsets, containerCornerInsets, and bounds() not supported" },
web: { status: "supported" },
}}
/>

## Usage

### Proportional sizing

Size a child relative to the available space:

```typescript theme={null}
GeometryReader((geometry) =>
    Circle()
        .fill(Color("blue"))
        .frame({
            width: geometry.size.width * 0.5,
            height: geometry.size.width * 0.5
        })
)
```

### Responsive layout

Choose a layout based on the available width:

```typescript theme={null}
GeometryReader((geometry) =>
    geometry.size.width > 400
        ? HStack({ spacing: 16 }, [sidebar, content])
        : VStack({ spacing: 8 }, [sidebar, content])
)
```

### Using frame coordinates

Access the component's position in global coordinates:

```typescript theme={null}
GeometryReader((geometry) => {
    const frame = geometry.frame("global")
    return Text(`Y position: ${frame.minY}`)
})
```

## Notes

* GeometryReader expands to fill all available space in its parent container. This can affect layout if not accounted for.
* Use GeometryReader sparingly. For adaptive layouts, consider [ViewThatFits](/bindjs/components/ViewThatFits) as a simpler alternative that does not expand to fill space.
* The `frame()` method returns a GeometryRect with `minX`, `minY`, `maxX`, `maxY`, `width`, `height`, `midX`, and `midY` properties.

## See Also

* [ViewThatFits](/bindjs/components/ViewThatFits) — adaptive layout without geometry access
