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

# Navigation chrome

> Modifiers for configuring the navigation bar and pushing destinations within a NavigationStack

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" />;
};

These iOS-only modifiers configure the navigation chrome around content inside a [NavigationStack](/bindjs/components/NavigationStack). Use `navigationDestination` for programmatic pushes, `navigationTitle` to set the title text, and the `navigationBar*` modifiers to fine-tune title size and back button visibility.

All four modifiers are typically applied to the content inside a `NavigationStack` — either the root view or a pushed destination view.

## navigationDestination

Programmatically presents a navigation destination view.

```typescript theme={null}
.navigationDestination(props: {
    isPresented: boolean,
    setIsPresented: (value: boolean) => void,
    destination: () => Component
}): Component
```

<ParamField path="props" type="object" required>
  Configuration for the navigation destination.

  <Expandable title="properties">
    <ParamField path="isPresented" type="boolean" required>
      Whether the destination view is currently pushed onto the navigation stack.
    </ParamField>

    <ParamField path="setIsPresented" type="(value: boolean) => void" required>
      Callback to update the presented state. Called with `false` when the user navigates back.
    </ParamField>

    <ParamField path="destination" type="() => Component" required>
      A function returning the component to push onto the navigation stack.
    </ParamField>
  </Expandable>
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: "not-implemented",
web: "not-implemented",
}}
/>

**Programmatic navigation**

```typescript theme={null}
const body = () => {
    const [showDetail, setShowDetail] = useState(false)

    return VStack([
        Button("Show Details", () => setShowDetail(true))
    ]).navigationDestination({
        isPresented: showDetail,
        setIsPresented: setShowDetail,
        destination: () => VStack([
            Text("Detail View")
                .font("title")
        ]).navigationTitle("Details")
    })
}
```

**Conditional navigation based on data**

```typescript theme={null}
const body = () => {
    const [selectedItem, setSelectedItem] = useState(null)

    return VStack([
        ForEach(items, (item) =>
            Button(item.name, () => setSelectedItem(item))
        )
    ]).navigationDestination({
        isPresented: selectedItem !== null,
        setIsPresented: (presented) => {
            if (!presented) setSelectedItem(null)
        },
        destination: () => Text(selectedItem?.name ?? "")
            .navigationTitle(selectedItem?.name ?? "")
    })
}
```

<Note>
  This modifier provides programmatic control over navigation, as opposed to [NavigationLink](/bindjs/components/NavigationLink) which navigates on tap. The destination view is pushed onto the [NavigationStack](/bindjs/components/NavigationStack); when the user taps the back button, `setIsPresented` is called with `false`.
</Note>

## navigationTitle

Sets the navigation bar title.

```typescript theme={null}
.navigationTitle(title: string): Component
```

<ParamField path="title" type="string" required>
  The text to display in the navigation bar.
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: "not-implemented",
web: "not-implemented",
}}
/>

**Setting a page title**

```typescript theme={null}
VStack([
    Text("Welcome to the app")
]).navigationTitle("Home")
```

**With large title display mode**

```typescript theme={null}
ScrollView([
    VStack([
        ForEach(items, (item) => Text(item.name))
    ])
])
    .navigationTitle("My Items")
    .navigationBarTitleDisplayMode("large")
```

**On a detail view**

```typescript theme={null}
const body = () => {
    const [showDetail, setShowDetail] = useState(false)

    return NavigationStack([
        VStack([
            NavigationLink("Go to Details", () =>
                Text("Detail content")
                    .navigationTitle("Details")
                    .navigationBarTitleDisplayMode("inline")
            )
        ]).navigationTitle("Home")
    ])
}
```

<Note>
  This modifier must be used within a [NavigationStack](/bindjs/components/NavigationStack) to have a visible effect. The title appears in the navigation bar and is also used as the back button label when a child view is pushed.
</Note>

## navigationBarBackButtonHidden

Hides the navigation bar back button.

```typescript theme={null}
.navigationBarBackButtonHidden(isHidden?: boolean): Component
```

<ParamField path="isHidden" type="boolean" optional default="true">
  Whether the back button is hidden. Defaults to `true`.
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: "not-implemented",
web: "not-implemented",
}}
/>

**Hiding the back button**

```typescript theme={null}
VStack([
    Text("Custom Detail View")
]).navigationBarBackButtonHidden()
```

**With a custom back action**

When hiding the default back button, provide an alternative navigation method using a toolbar item.

```typescript theme={null}
const body = () => {
    const [showDetail, setShowDetail] = useState(false)

    return VStack([
        Text("Detail Content")
    ])
        .navigationBarBackButtonHidden()
        .toolbar(
            ToolbarItem("navigationBarLeading",
                Button("Close", () => setShowDetail(false))
            )
        )
}
```

<Note>
  This modifier is typically applied to a destination view within a [NavigationStack](/bindjs/components/NavigationStack). When hiding the back button, consider providing an alternative way for the user to navigate back.
</Note>

## navigationBarTitleDisplayMode

Sets the navigation bar title display mode.

```typescript theme={null}
.navigationBarTitleDisplayMode(mode: "large" | "inline" | "automatic"): Component
```

<ParamField path="mode" type="string" required>
  The title display mode:

  * `"large"` -- a large, scrollable title that collapses as the user scrolls
  * `"inline"` -- a small, centered title in the navigation bar
  * `"automatic"` -- inherits the display mode from the navigation context
</ParamField>

<PlatformStatuses
  statuses={{
ios: { status: "supported" },
android: "not-implemented",
web: "not-implemented",
}}
/>

**Large title**

```typescript theme={null}
ScrollView([
    VStack([
        ForEach(items, (item) => Text(item.name))
    ])
])
    .navigationTitle("Settings")
    .navigationBarTitleDisplayMode("large")
```

**Inline title**

```typescript theme={null}
VStack([
    Text("Detail content")
])
    .navigationTitle("Item Details")
    .navigationBarTitleDisplayMode("inline")
```

<Note>
  The `"large"` mode shows a prominent title that smoothly transitions to an inline title as the user scrolls down — the default for root-level views in a navigation stack. The `"inline"` mode always shows a compact title centered in the navigation bar, typical for detail/pushed views. Apply this modifier to content within a [NavigationStack](/bindjs/components/NavigationStack).
</Note>

## See also

* [NavigationStack](/bindjs/components/NavigationStack) — navigation container
* [NavigationLink](/bindjs/components/NavigationLink) — tap-to-navigate link
* [Toolbar](/bindjs/modifiers/toolbar) — toolbar items and visibility
* [Presentation](/bindjs/modifiers/presentation) — modal sheets and full-screen covers
