Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: new APIS with v9
  • Loading branch information
NathanWalker committed Nov 11, 2025
commit 12e459405c5fda10c8ab066e52ea1088d7e3fa95
1 change: 1 addition & 0 deletions content/ui/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export default [
{ text: 'SearchBar', link: '/ui/search-bar' },
{ text: 'SegmentedBar', link: '/ui/segmented-bar' },
{ text: 'Slider', link: '/ui/slider' },
{ text: 'SplitView', link: '/ui/split-view' },
{ text: 'Switch', link: '/ui/switch' },
{ text: 'TabView', link: '/ui/tab-view' },
{ text: 'TextField', link: '/ui/text-field' },
Expand Down
225 changes: 225 additions & 0 deletions content/ui/split-view.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
---
title: SplitView
description: A singular root view component for coordinating up to four column roles (primary, secondary, supplementary, inspector).
contributors:
- NathanWalker
---

`<SplitView>` is an iOS-only container component that gives you a declarative [UISplitViewController](https://developer.apple.com/documentation/uikit/uisplitviewcontroller) and exposes its modern multi-column capabilities to NativeScript apps. It lets you coordinate **up to four** roles:

- **primary** – main navigation or master content
- **secondary** – detail view for the selected item
- **supplementary** – contextual / side content
- **inspector** – tool / inspector pane available on iOS 17+ when the system supports it

Each role is typically provided by a child `<Frame>` so that every column can manage its own navigation stack independently, while still being part of the same split view controller. This mirrors how native iPadOS apps structure complex layouts.

::: tip
It is intended to be used as the singular starting root view for the entire app.

This component is ideal for iPadOS-style apps, admin-style layouts, or any experience where you need a master-detail flow plus an extra contextual pane or inspector.
:::

## Example

### Declarative XML

```xml
<SplitView
displayMode="twoBesideSecondary"
splitBehavior="tile"
preferredPrimaryColumnWidthFraction="0.25"
preferredSupplementaryColumnWidthFraction="0.33"
preferredInspectorColumnWidthFraction="0.20">

<Frame splitRole="primary" defaultPage="pages/master" />
<Frame splitRole="secondary" defaultPage="pages/detail" />
<Frame splitRole="supplementary" defaultPage="pages/context" />
<Frame splitRole="inspector" defaultPage="pages/inspector" />
</SplitView>
```
This configures a 3–4 column layout (depending on OS support) and assigns each role to its own frame.

### Programmatic

```ts
import { SplitView } from '@nativescript/core'

const splitView = new SplitView()
splitView.displayMode = 'twoBesideSecondary'
splitView.splitBehavior = 'tile'
splitView.preferredPrimaryColumnWidthFraction = 0.25

// create frames with splitRole before adding them
```

### With inspector change listener

```ts
splitView.on('inspectorChange', ({ data }) => {
console.log('Inspector visible?', data.showing)
})
```
Fired whenever the inspector column is shown or hidden.

## Concepts

### Roles

SplitView coordinates **roles** rather than arbitrary children. Children declare their intended role:

```xml
<Frame splitRole="primary" />
<Frame splitRole="secondary" />
<Frame splitRole="supplementary" />
<Frame splitRole="inspector" />
```

If a role is omitted, SplitView falls back to the order in which children were added. However, declaring the role is recommended for clarity and for future layout changes.

### Column styles

The underlying controller can operate in *double* or *triple* column styles. SplitView exposes this through a common enum:

- `SplitView.SplitStyle.double`
- `SplitView.SplitStyle.triple`

iOS chooses the right `UISplitViewControllerStyle` for you. On iOS 17+ an inspector column can also be shown. citeturn2view0

## Props

### displayMode

```ts
displayMode:
| 'automatic'
| 'secondaryOnly'
| 'oneBesideSecondary'
| 'oneOverSecondary'
| 'twoBesideSecondary'
| 'twoOverSecondary'
| 'twoDisplaceSecondary'
```

Maps to [UISplitViewController.preferredDisplayMode]. Determines how the primary/supplementary columns relate to the secondary column (beside vs over vs displaced).

### splitBehavior (iOS 14+)

```ts
splitBehavior: 'automatic' | 'tile' | 'overlay' | 'displace'
```

Maps to [UISplitViewController.preferredSplitBehavior](https://developer.apple.com/documentation/uikit/uisplitviewcontroller/preferreddisplaymode). Controls how columns behave when the size class changes (for example overlaying instead of resizing). iOS 14 or newer is required.

### preferredPrimaryColumnWidthFraction

```ts
preferredPrimaryColumnWidthFraction: number // 0..1
```

Fractional width for the primary column (for example `0.25` = 25%).

### preferredSupplementaryColumnWidthFraction

```ts
preferredSupplementaryColumnWidthFraction: number // 0..1
```

Used in triple-column style to reserve width for the supplementary column.

### preferredInspectorColumnWidthFraction

```ts
preferredInspectorColumnWidthFraction: number // 0..1
```

Width fraction for the inspector column, applied only when the platform supports the inspector role (iOS 17+). On earlier versions this is safely ignored.

### inspectorShowing (readonly)

```ts
inspectorShowing: boolean
```

Current visibility state of the inspector column. Helpful to sync UI buttons with the actual split view state.

## Static members

### SplitView.getInstance()

```ts
const active = SplitView.getInstance()
```

Returns the last created SplitView instance, or `null` if none exists. This is a convenience for apps that only ever use a single SplitView and want to access it imperatively (for example, from a service).

### SplitView.SplitStyle

```ts
const { SplitStyle } = SplitView
```

Common enum representing double vs triple column styles. The iOS implementation maps this to the proper `UISplitViewController` style.

## Methods

### showPrimary() / hidePrimary()

```ts
splitView.showPrimary()
splitView.hidePrimary()
```

Shows or hides the primary column. Useful on compact width or when presenting master-detail flows modally.

### showSecondary() / hideSecondary()

```ts
splitView.showSecondary()
splitView.hideSecondary()
```

Controls the visibility of the secondary column.

### showSupplementary()

```ts
splitView.showSupplementary()
```

Ensures the supplementary column is visible when the display mode allows it. Hiding is typically handled automatically by the display mode.

### showInspector() / hideInspector()

```ts
splitView.showInspector()
splitView.hideInspector()
```

Toggles the inspector column (iOS 17+). Calls are no-ops on platforms/versions where inspector is not available.

### onSecondaryViewCollapsed(secondaryVC, primaryVC)

Lifecycle hook invoked when the system collapses the secondary onto the primary (for example, when moving to a compact size). Override in subclasses or listen at the NativeScript level to adjust your UI.

## Events

### inspectorChange

```ts
splitView.on('inspectorChange', (args) => {
console.log('Inspector visible?', args.data.showing)
})
```

Emitted whenever the inspector column changes visibility. Payload contains a `data.showing: boolean`.

## Platform notes

- **Platform**: iOS only (backed by `UISplitViewController`).
- **splitBehavior**: requires iOS 14+.
- **Inspector**: requires iOS 17+. On earlier versions the property is ignored and inspector-related methods are safe no-ops.

## Native component

- iOS: [`UISplitViewController`](https://developer.apple.com/documentation/uikit/uisplitviewcontroller)
80 changes: 78 additions & 2 deletions content/ui/tab-view.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
---
title: TabView
description: UI component for grouping content into tabs and let users switch between them.
description: UI component for grouping content into tabs and letting users switch between them.
contributors:
- rigor789
- Ombuweb
- NathanWalker
---

`<TabView>` is a UI component that shows content grouped into tabs and lets users switch between them.

As of NativeScript 9, on **iOS 26+**, TabView now supports:
- an **optional bottom accessory view** (`iosBottomAccessory`) that sits just above the tab bar and participates in layout, and
- a **configurable tab bar minimize behavior** (`iosTabBarMinimizeBehavior`) so you can control how/when the tab bar hides when scrolling.

<DeviceFrame type="ios">
<img src="../assets/images/screenshots/ios/TabView.png"/>
</DeviceFrame>
Expand Down Expand Up @@ -130,7 +135,7 @@ Sets the underline color of the tabs. **Android only.**

```css
.tab-view {
android-selected-tab-highlight-color:: #3d5a80;
android-selected-tab-highlight-color: #3d5a80;
}
```

Expand Down Expand Up @@ -160,6 +165,38 @@ Defaults to `automatic`.

See [UIImage.RenderingMode](https://developer.apple.com/documentation/uikit/uiimage/renderingmode).

### iosBottomAccessory

```ts
iosBottomAccessory: View // iOS 26+ only
```

Assigns a bottom accessory view that is rendered *above* the iOS tab bar, inside the TabView's layout. This is useful for mini players, status bars, or context-sensitive actions that should stay attached to the tab bar. On platforms below iOS 26 this property is ignored.

Notes:
- Give it an explicit `height` or style it with CSS so the TabView can measure it.
- It participates in layout pass fixes added in this release so it will resize alongside safe areas.
- On Android this is ignored.

### iosTabBarMinimizeBehavior

```ts
iosTabBarMinimizeBehavior:
| 'automatic'
| 'never'
| 'onScrollDown'
| 'onScrollUp'
```

Controls how the iOS tab bar minimizes/hides in response to scrolling. This mirrors the iOS 26 tab bar behavior on `UITabBarController`.

- `automatic` – system chooses; good default.
- `never` – keep the tab bar always visible.
- `onScrollDown` – hide the tab bar when scrolling down.
- `onScrollUp` – show the tab bar when scrolling up.

Ignored on iOS < 26 and on Android.

### ...Inherited

For additional inherited properties, refer to the [API Reference](/api/class/TabView).
Expand Down Expand Up @@ -211,6 +248,45 @@ on('selectedIndexChanged', (args: EventData) => {

Emitted when the selected tab changes.

## Platform specific notes

### iOS 26+ bottom accessory

On iOS 26+ you can attach any NativeScript view as a bottom accessory, such as a mini player, quick actions, or a context bar. On earlier iOS versions and on Android this is ignored safely.

```xml
<TabView
id="mainTabs"
selectedIndex="0"
iosTabBarMinimizeBehavior="automatic"
iosBottomAccessory="
<StackLayout
height='44'
backgroundColor='#1c1c1e'
orientation='horizontal'
horizontalAlignment='stretch'>
<Label text='Now playing…' color='white' verticalAlignment='center' marginLeft='12' />
</StackLayout>
">
<TabViewItem title="Library">
<Label text="Your library" />
</TabViewItem>
<TabViewItem title="Search">
<Label text="Search" />
</TabViewItem>
</TabView>
```

You can also set the accessory from code if you need to build it dynamically:

```ts
const tabView = page.getViewById('mainTabs') as TabView
const accessory = new StackLayout()
accessory.height = 44
accessory.backgroundColor = '#1c1c1e'
tabView.iosBottomAccessory = accessory
```

## Native component

- Android: [`androidx.viewpager.widget.ViewPager`](https://developer.android.com/reference/androidx/viewpager/widget/ViewPager)
Expand Down
Loading