diff --git a/content/guide/styling.md b/content/guide/styling.md
index 4a8a642c..afc353ac 100644
--- a/content/guide/styling.md
+++ b/content/guide/styling.md
@@ -226,7 +226,8 @@ This list of properties can be set in CSS or through the style property of each
| `border-radius` | `borderRadius` | Sets a border radius to the matched view’s. |
| `box-shadow` | `boxShadow` | Sets a box shadow to the matched view's. |
| `clip-path` | `clipPath` | Sets the clip-path. Supported shapes are circle, ellipse, rect and polygon. You can define your own shape using [clippy](http://bennettfeely.com/clippy/) |
-| `color` | `color` | Sets a solid-color value to the matched view’s foreground. |
+| `color` | `color` | Sets a solid-color value to the matched view’s foreground.
+| `direction` | `direction` | Sets the direction of text, table and grid columns, and horizontal overflow. Use rtl for languages written from right to left (like Hebrew or Arabic), and ltr for those written from left to right (like English and most other languages). |
| `font` | `font` | Sets the font properties (this includes `font-family`, `font-size`, `font-style` and `font-weight`) of the matched view. |
| `font-family` | `fontFamily` | Sets the font family of the matched view. |
| `font-size` | `fontSize` | Sets the font size of the matched view (only supports device-independent units). |
@@ -259,6 +260,39 @@ This list of properties can be set in CSS or through the style property of each
| `width` | `width` | Sets the view width. |
| `z-index` | `zIndex` | Sets the z-index. (On Android API Level 21 and above.) |
+## Layout direction (LTR / RTL)
+
+NativeScript now supports an **inherited CSS `direction` property** to force the layout direction of views to either left-to-right (`ltr`) or right-to-left (`rtl`).
+
+```css
+/* Apply RTL to the entire app */
+.ns-root {
+ direction: rtl;
+}
+```
+
+What this does:
+
+- tells NativeScript to use the **platform’s native direction APIs** so you get the OS-level behavior for RTL,
+- makes navigation transitions direction-aware (slide, flip, etc.),
+- makes default label/text alignment respect the direction,
+- enables direction-aware layout for FlexboxLayout on iOS,
+- aligns horizontal scroll views to the end in RTL,
+- and allows using `start` / `end` values for `horizontalAlignment` to align relative to the current direction.
+
+Android note:
+
+```xml
+
+
+
+```
+
+You **must** enable `android:supportsRtl="true"` in the manifest for Android to actually honor RTL. On iOS this is always available.
+
### Accessing NativeScript View properties with CSS
You can also set NativeScript component properties value that are not part of the CSS specification. For example:
diff --git a/content/ui/list-view.md b/content/ui/list-view.md
index 575f1d25..65259b7a 100644
--- a/content/ui/list-view.md
+++ b/content/ui/list-view.md
@@ -1,18 +1,19 @@
---
title: ListView
-description: UI component for rendering large lists using view recycling.
+description: UI component for rendering large lists using view recycling, with optional sticky headers, sectioned data, and an integrated search bar.
contributors:
- rigor789
- Ombuweb
+ - NathanWalker
---
-`` is a UI component that renders items in a vertically scrolling list, the template for the items can be defined via `itemTemplate` (or multiple templates via `itemTemplates` - more on that below). The ListView only renders the visible items, as the user scrolls, new items render by reusing a no-longer-visible item's view—this is usually referred to as view-recycling.
+`` is a UI component that renders items in a vertically scrolling list. The template for the items can be defined via `itemTemplate` (or multiple templates via `itemTemplates` — more on that below). The ListView only renders the visible items; as the user scrolls, new items render by reusing a no-longer-visible item's view — this is usually referred to as view-recycling.
-::: tip
+Newer versions of `ListView` (v9+) can also render **sectioned data** (for example, A–Z lists) with **sticky headers** and an **optional search bar** that can auto-hide on iOS.
-For additional features and improved performance in certain scenarios, consider using an alternative implementation like the
+::: tip
+You can also explore
[CollectionView](https://github.com/nativescript-community/ui-collectionview) from the community.
-
:::
@@ -78,6 +79,72 @@ Individual items can be rendered using a different template. For example, let's
+### Sectioned ListView with sticky headers and search
+
+Starting with v9, ListView can render sectioned data with sticky headers and an optional search bar. This is useful for contact lists, country lists, or any data grouped by a key.
+
+A supported data shape looks like this:
+
+```ts
+const countries: { title: string; items: { name: string; code?: string; flag?: string }[] }[] = [
+ {
+ title: 'A',
+ items: [
+ { name: 'Albania', code: 'AL' },
+ ],
+ },
+ {
+ title: 'B',
+ items: [
+ { name: 'Bahamas', code: 'BS' },
+ ],
+ },
+]
+```
+
+You can then bind this data to the ListView and enable the new props:
+
+```xml
+
+```
+
+In code you can listen for search changes:
+
+```ts
+listView.on('searchChange', (args: SearchEventData) => {
+ console.log('search text:', args.text)
+ // apply filtering to your backing data if desired
+})
+```
+
+Notes:
+
+- `searchAutoHide` is currently iOS-only (it will auto-hide the search on scroll).
+- `stickyHeaderTemplate` accepts the same binding context as the section (`title`, etc.).
+- Make sure each section’s `items` array is present; empty / null sections may not render as expected.
+
## Props
### items
@@ -128,6 +195,71 @@ Gets or sets the available itemTemplates.
See [KeyedTemplate](/api/interface/KeyedTemplate).
+### sectioned
+
+```ts
+sectioned: boolean
+```
+
+Enables sectioned data rendering on the `ListView`. When `true`, the ListView expects the `items` source to be an **array of sections** where each section has a `title` (or similar field) and an `items` array:
+
+```ts
+{
+ title: string;
+ items: any[];
+}
+```
+
+This allows the ListView to render grouped lists with headers.
+
+### stickyHeader
+
+```ts
+stickyHeader: boolean
+```
+
+Enables sticky (pinned) headers while scrolling sectioned data. When enabled, the current section header stays at the top of the list until the next section header pushes it away.
+
+### stickyHeaderTemplate
+
+```ts
+stickyHeaderTemplate: string | KeyedTemplate
+```
+
+Gets or sets the template used to render a section header when sticky headers are enabled. This accepts bindings from the current section (for example: `{{ title }}`).
+
+### stickyHeaderHeight
+
+```ts
+stickyHeaderHeight: number
+```
+
+Explicit height for the sticky header. Providing this can improve measurement and scrolling performance, especially on iOS where headers update as you scroll.
+
+### stickyHeaderTopPadding
+
+```ts
+stickyHeaderTopPadding: boolean | number
+```
+
+Controls the padding applied to the sticky header at the top. Set to `false` to disable the extra top padding; set to a number to supply an explicit padding value.
+
+### showSearch
+
+```ts
+showSearch: boolean
+```
+
+Shows a built-in search bar above the ListView. This is useful when you want a declarative, per-list search input without adding a separate `SearchBar` component.
+
+### searchAutoHide
+
+```ts
+searchAutoHide: boolean
+```
+
+(iOS only) When `true`, the built-in search bar will auto-hide when the user scrolls. This mirrors common iOS list behaviors.
+
### separatorColor
```ts
@@ -150,6 +282,8 @@ rowHeight: number
Gets or sets the row height of the ListView. Useful when your items have a fixed height, as the required calculations are greatly simplified and the rendering can be faster.
+> Android: with the latest ListView improvements, row items will now react properly to spacing (padding and margin), so setting `rowHeight` alongside your layout spacing should behave more predictably across platforms.
+
### iosEstimatedRowHeight
Gets or sets the estimated height of rows in the ListView. Default value: `44px`
@@ -235,6 +369,18 @@ on('loadMoreItems', (args: EventData) => {
Emitted when the user reaches the end of the ListView. Useful for loading additional items (ie. infinite scroll).
+### searchChange
+
+```ts
+on('searchChange', (args: SearchEventData) => {
+ console.log('Search text changed:', args.text)
+})
+```
+
+Emitted when the built-in search bar text changes. You can use this to filter the underlying list data, or to drive remote searches.
+
+See `SearchEventData` in the API reference for the shape of the event.
+
## Native component
- Android: [`android.widget.ListView`](https://developer.android.com/reference/android/widget/ListView.html)
diff --git a/content/ui/sidebar.ts b/content/ui/sidebar.ts
index 58748f73..5524ee7b 100644
--- a/content/ui/sidebar.ts
+++ b/content/ui/sidebar.ts
@@ -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' },
diff --git a/content/ui/split-view.md b/content/ui/split-view.md
new file mode 100644
index 00000000..754ecdd9
--- /dev/null
+++ b/content/ui/split-view.md
@@ -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
+---
+
+`` 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 `` 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
+
+
+
+
+
+
+
+```
+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
+
+
+
+
+```
+
+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. citeturn2view0
+
+## 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)
diff --git a/content/ui/tab-view.md b/content/ui/tab-view.md
index ed13bb7f..b7f53c81 100644
--- a/content/ui/tab-view.md
+++ b/content/ui/tab-view.md
@@ -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
---
`` 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.
+
@@ -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;
}
```
@@ -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).
@@ -194,7 +231,7 @@ iconSource: string
Gets or sets the icon source of the tab strip entry.
-Supported paths are `res://` or an absolute path (eg. `~/assets/image.png`).
+Supported paths are `font://`, `res://`, `sys://` (iOS only), or an absolute path (eg. `~/assets/image.png`).
See [`Image`](/ui/image) for details on the different paths.
@@ -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
+
+
+
+
+
+
+
+
+```
+
+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)