or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-functions.mdexperimental-features.mdheader-components.mdindex.mdnavigation-utilities.mdscreen-components.mdtypes-interfaces.md

experimental-features.mddocs/

0

# Experimental Features

1

2

Beta and experimental components for advanced navigation patterns including bottom tabs, split views, and experimental screen hosting. These features are under active development and may change in future versions.

3

4

## Core Imports

5

6

```typescript

7

import {

8

BottomTabs,

9

BottomTabsScreen,

10

ScreenStackHost,

11

StackScreen,

12

StackScreenLifecycleState,

13

SplitViewHost,

14

SplitViewScreen

15

} from "react-native-screens";

16

```

17

18

## Capabilities

19

20

### Bottom Tabs

21

22

Experimental native bottom tabs component that provides platform-native tab bar functionality with improved performance over JavaScript-based implementations.

23

24

```typescript { .api }

25

/**

26

* Experimental native bottom tabs component

27

*/

28

function BottomTabs(props: BottomTabsProps): JSX.Element;

29

30

interface BottomTabsProps {

31

/** Currently selected tab index */

32

selectedTab?: number;

33

34

/** Callback when tab selection changes */

35

onTabChange?: (event: NativeSyntheticEvent<NativeFocusChangeEvent>) => void;

36

37

/** Whether tabs should be scrollable (Android) */

38

scrollable?: boolean;

39

40

/** Tab bar background color */

41

barTintColor?: ColorValue;

42

43

/** Selected tab tint color */

44

selectedItemColor?: ColorValue;

45

46

/** Unselected tab tint color */

47

unselectedItemColor?: ColorValue;

48

49

/** Tab bar style (iOS) */

50

barStyle?: 'default' | 'black';

51

52

/** Whether tab bar is translucent (iOS) */

53

translucent?: boolean;

54

55

/** Tab bar appearance (iOS) */

56

appearance?: 'default' | 'opaque';

57

58

/** Content inset adjustment behavior (iOS) */

59

contentInsetAdjustmentBehavior?: 'automatic' | 'scrollableAxes' | 'never' | 'always';

60

}

61

62

interface NativeFocusChangeEvent {

63

/** Index of the newly focused tab */

64

focusedTab: number;

65

66

/** Index of the previously focused tab */

67

previouslyFocusedTab: number;

68

}

69

```

70

71

**Usage Example:**

72

73

```typescript

74

import React, { useState } from 'react';

75

import { BottomTabs, BottomTabsScreen } from 'react-native-screens';

76

import { View, Text } from 'react-native';

77

78

function TabNavigator() {

79

const [selectedTab, setSelectedTab] = useState(0);

80

81

const handleTabChange = (event) => {

82

setSelectedTab(event.nativeEvent.focusedTab);

83

};

84

85

return (

86

<BottomTabs

87

selectedTab={selectedTab}

88

onTabChange={handleTabChange}

89

barTintColor="#f8f9fa"

90

selectedItemColor="#007AFF"

91

unselectedItemColor="#8E8E93"

92

>

93

<BottomTabsScreen

94

title="Home"

95

tabBarIcon="home"

96

badge="3"

97

>

98

<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

99

<Text>Home Tab Content</Text>

100

</View>

101

</BottomTabsScreen>

102

103

<BottomTabsScreen

104

title="Search"

105

tabBarIcon="search"

106

>

107

<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

108

<Text>Search Tab Content</Text>

109

</View>

110

</BottomTabsScreen>

111

112

<BottomTabsScreen

113

title="Profile"

114

tabBarIcon="person"

115

>

116

<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>

117

<Text>Profile Tab Content</Text>

118

</View>

119

</BottomTabsScreen>

120

</BottomTabs>

121

);

122

}

123

```

124

125

### Bottom Tabs Screen

126

127

Individual screen component within the bottom tabs navigator that represents a single tab with its content and configuration.

128

129

```typescript { .api }

130

/**

131

* Individual screen within bottom tabs

132

*/

133

function BottomTabsScreen(props: BottomTabsScreenProps): JSX.Element;

134

135

interface BottomTabsScreenProps {

136

/** Tab title */

137

title?: string;

138

139

/** Tab bar icon name or component */

140

tabBarIcon?: string | React.ComponentType<any>;

141

142

/** Badge text to display on tab */

143

badge?: string;

144

145

/** Badge background color */

146

badgeColor?: ColorValue;

147

148

/** Whether tab is enabled */

149

enabled?: boolean;

150

151

/** Tab tint color when selected */

152

activeTintColor?: ColorValue;

153

154

/** Tab tint color when unselected */

155

inactiveTintColor?: ColorValue;

156

157

/** Tab background color */

158

backgroundColor?: ColorValue;

159

160

/** Whether tab should show title */

161

showTitle?: boolean;

162

163

/** Custom tab bar component */

164

tabBarComponent?: React.ComponentType<any>;

165

166

/** Tab press callback */

167

onTabPress?: () => void;

168

169

/** Tab long press callback */

170

onTabLongPress?: () => void;

171

}

172

```

173

174

**Advanced Usage:**

175

176

```typescript

177

import React from 'react';

178

import { BottomTabsScreen } from 'react-native-screens';

179

import { Image } from 'react-native';

180

181

function CustomTabIcon({ focused, color }) {

182

return (

183

<Image

184

source={focused ? require('./home-filled.png') : require('./home-outline.png')}

185

style={{ width: 24, height: 24, tintColor: color }}

186

/>

187

);

188

}

189

190

function CustomBottomTabsScreen() {

191

return (

192

<BottomTabsScreen

193

title="Home"

194

tabBarIcon={CustomTabIcon}

195

badge="5"

196

badgeColor="#FF3B30"

197

onTabPress={() => console.log('Home tab pressed')}

198

onTabLongPress={() => console.log('Home tab long pressed')}

199

>

200

{/* Screen content */}

201

</BottomTabsScreen>

202

);

203

}

204

```

205

206

### Screen Stack Host

207

208

Experimental screen stack host component that provides advanced screen stack management with enhanced lifecycle control.

209

210

```typescript { .api }

211

/**

212

* Experimental screen stack host component

213

*/

214

function ScreenStackHost(props: ViewProps): JSX.Element;

215

```

216

217

**Usage Example:**

218

219

```typescript

220

import React from 'react';

221

import { ScreenStackHost, StackScreen } from 'react-native-screens';

222

223

function ExperimentalStackNavigator() {

224

return (

225

<ScreenStackHost>

226

<StackScreen

227

active={1}

228

lifecycle={StackScreenLifecycleState.Active}

229

>

230

{/* Screen content */}

231

</StackScreen>

232

</ScreenStackHost>

233

);

234

}

235

```

236

237

### Stack Screen

238

239

Experimental stack screen component with enhanced lifecycle management and performance optimizations.

240

241

```typescript { .api }

242

/**

243

* Experimental stack screen component

244

*/

245

function StackScreen(props: StackScreenProps): JSX.Element;

246

247

interface StackScreenProps extends ViewProps {

248

/** Screen active state */

249

active?: 0 | 1;

250

251

/** Screen lifecycle state */

252

lifecycle?: StackScreenLifecycleState;

253

254

/** Screen identifier */

255

screenId?: string;

256

257

/** Performance optimization settings */

258

optimizationHints?: {

259

/** Whether screen content should be preloaded */

260

preload?: boolean;

261

262

/** Whether screen should be kept in memory */

263

keepAlive?: boolean;

264

265

/** Priority level for resource allocation */

266

priority?: 'low' | 'normal' | 'high';

267

};

268

}

269

```

270

271

### Stack Screen Lifecycle State

272

273

Enumeration of lifecycle states for stack screens, providing fine-grained control over screen behavior.

274

275

```typescript { .api }

276

/**

277

* Lifecycle states for stack screens

278

*/

279

enum StackScreenLifecycleState {

280

/** Screen is not yet initialized */

281

Uninitialized = 0,

282

283

/** Screen is being created */

284

Creating = 1,

285

286

/** Screen is active and visible */

287

Active = 2,

288

289

/** Screen is inactive but still in memory */

290

Inactive = 3,

291

292

/** Screen is being destroyed */

293

Destroying = 4,

294

295

/** Screen has been destroyed */

296

Destroyed = 5

297

}

298

```

299

300

**Usage Example:**

301

302

```typescript

303

import React, { useEffect } from 'react';

304

import { StackScreen, StackScreenLifecycleState } from 'react-native-screens';

305

306

function LifecycleAwareScreen({ lifecycle }) {

307

useEffect(() => {

308

switch (lifecycle) {

309

case StackScreenLifecycleState.Creating:

310

console.log('Screen is being created');

311

break;

312

case StackScreenLifecycleState.Active:

313

console.log('Screen is now active');

314

break;

315

case StackScreenLifecycleState.Inactive:

316

console.log('Screen is now inactive');

317

break;

318

case StackScreenLifecycleState.Destroying:

319

console.log('Screen is being destroyed');

320

break;

321

}

322

}, [lifecycle]);

323

324

return (

325

<StackScreen

326

lifecycle={lifecycle}

327

optimizationHints={{

328

preload: true,

329

keepAlive: false,

330

priority: 'normal'

331

}}

332

>

333

{/* Screen content */}

334

</StackScreen>

335

);

336

}

337

```

338

339

### Split View Host

340

341

Host component for split view layouts, primarily designed for iPad and larger screens to provide master-detail interfaces.

342

343

```typescript { .api }

344

/**

345

* Host component for split view layouts (iPad)

346

*/

347

function SplitViewHost(props: SplitViewHostProps): JSX.Element;

348

349

interface SplitViewHostProps extends ViewProps {

350

/** Split view display mode */

351

displayMode?: SplitViewDisplayMode;

352

353

/** Primary column width */

354

primaryColumnWidth?: number;

355

356

/** Secondary column width */

357

secondaryColumnWidth?: number;

358

359

/** Minimum primary column width */

360

minimumPrimaryColumnWidth?: number;

361

362

/** Maximum primary column width */

363

maximumPrimaryColumnWidth?: number;

364

365

/** Preferred display mode */

366

preferredDisplayMode?: SplitViewDisplayMode;

367

368

/** Whether primary column is shown */

369

showsPrimaryColumn?: boolean;

370

371

/** Whether secondary column is shown */

372

showsSecondaryColumn?: boolean;

373

374

/** Callback when display mode changes */

375

onDisplayModeChange?: (event: NativeSyntheticEvent<{ displayMode: SplitViewDisplayMode }>) => void;

376

377

/** Callback when column visibility changes */

378

onColumnVisibilityChange?: (event: NativeSyntheticEvent<{

379

primaryVisible: boolean;

380

secondaryVisible: boolean;

381

}>) => void;

382

}

383

```

384

385

**Usage Example:**

386

387

```typescript

388

import React, { useState } from 'react';

389

import { SplitViewHost, SplitViewScreen } from 'react-native-screens';

390

import { View, Text, FlatList, TouchableOpacity } from 'react-native';

391

392

function MasterDetailInterface() {

393

const [selectedItem, setSelectedItem] = useState(null);

394

const [displayMode, setDisplayMode] = useState('automatic');

395

396

const handleDisplayModeChange = (event) => {

397

setDisplayMode(event.nativeEvent.displayMode);

398

};

399

400

return (

401

<SplitViewHost

402

displayMode={displayMode}

403

primaryColumnWidth={320}

404

minimumPrimaryColumnWidth={250}

405

maximumPrimaryColumnWidth={400}

406

onDisplayModeChange={handleDisplayModeChange}

407

>

408

<SplitViewScreen column="primary">

409

<View style={{ flex: 1, backgroundColor: '#f5f5f5' }}>

410

<Text style={{ fontSize: 18, padding: 16 }}>Master</Text>

411

<FlatList

412

data={items}

413

keyExtractor={(item) => item.id}

414

renderItem={({ item }) => (

415

<TouchableOpacity

416

onPress={() => setSelectedItem(item)}

417

style={{

418

padding: 16,

419

backgroundColor: selectedItem?.id === item.id ? '#007AFF' : 'white'

420

}}

421

>

422

<Text style={{

423

color: selectedItem?.id === item.id ? 'white' : 'black'

424

}}>

425

{item.title}

426

</Text>

427

</TouchableOpacity>

428

)}

429

/>

430

</View>

431

</SplitViewScreen>

432

433

<SplitViewScreen column="secondary">

434

<View style={{ flex: 1, backgroundColor: 'white', padding: 16 }}>

435

<Text style={{ fontSize: 18, marginBottom: 16 }}>Detail</Text>

436

{selectedItem ? (

437

<View>

438

<Text style={{ fontSize: 16, fontWeight: 'bold' }}>

439

{selectedItem.title}

440

</Text>

441

<Text style={{ marginTop: 8 }}>

442

{selectedItem.description}

443

</Text>

444

</View>

445

) : (

446

<Text style={{ color: '#8E8E93' }}>

447

Select an item from the master list

448

</Text>

449

)}

450

</View>

451

</SplitViewScreen>

452

</SplitViewHost>

453

);

454

}

455

```

456

457

### Split View Screen

458

459

Individual screen component within a split view layout, representing either the primary or secondary column content.

460

461

```typescript { .api }

462

/**

463

* Individual screen within split view

464

*/

465

function SplitViewScreen(props: SplitViewScreenProps): JSX.Element;

466

467

interface SplitViewScreenProps extends ViewProps {

468

/** Which column this screen represents */

469

column: 'primary' | 'secondary';

470

471

/** Whether this column is currently visible */

472

visible?: boolean;

473

474

/** Column background color */

475

backgroundColor?: ColorValue;

476

477

/** Column border configuration */

478

borderColor?: ColorValue;

479

borderWidth?: number;

480

481

/** Callback when column becomes visible */

482

onAppear?: () => void;

483

484

/** Callback when column becomes hidden */

485

onDisappear?: () => void;

486

}

487

```

488

489

## Types

490

491

### Split View Display Mode

492

493

```typescript { .api }

494

type SplitViewDisplayMode =

495

| 'automatic' // System determines layout

496

| 'secondaryOnly' // Show only secondary column

497

| 'oneBesideSecondary' // Primary beside secondary

498

| 'oneOverSecondary' // Primary over secondary

499

| 'twoBesideSecondary' // Two columns beside secondary

500

| 'twoOverSecondary' // Two columns over secondary

501

| 'twoDisplaceSecondary'; // Two columns displacing secondary

502

```

503

504

## Feature Flags and Configuration

505

506

### Enabling Experimental Features

507

508

```typescript

509

import { featureFlags } from "react-native-screens";

510

511

// Enable experimental bottom tabs

512

featureFlags.experiment.controlledBottomTabs = true;

513

514

// Check if experimental features are available

515

if (featureFlags.experiment.controlledBottomTabs) {

516

// Use experimental BottomTabs component

517

} else {

518

// Use alternative implementation

519

}

520

```

521

522

### Private API Access

523

524

```typescript

525

// Import private debugging utilities (use with caution)

526

import {

527

internalEnableDetailedBottomTabsLogging,

528

bottomTabsDebugLog

529

} from "react-native-screens/private";

530

531

// Enable detailed logging for debugging (development only)

532

if (__DEV__) {

533

internalEnableDetailedBottomTabsLogging(true);

534

535

// Custom debug logging

536

bottomTabsDebugLog('Custom debug message', { data: 'value' });

537

}

538

```

539

540

## Platform Support

541

542

### iOS Specific Features

543

- Native UITabBarController integration for BottomTabs

544

- UISplitViewController for split views

545

- iOS-specific tab bar appearance options

546

- Form sheet and popover presentations

547

548

### Android Specific Features

549

- Material Design bottom navigation

550

- Fragment-based tab management

551

- Scrollable tab bars

552

- Android-specific navigation patterns

553

554

### Compatibility Notes

555

- Bottom tabs require iOS 11+ and Android API 21+

556

- Split views are primarily designed for iPad but work on iPhone in landscape

557

- Experimental features may have limited testing on all device configurations

558

- Performance characteristics may vary between platforms

559

560

## Migration and Stability

561

562

### Stability Considerations

563

- Experimental features are subject to breaking changes

564

- APIs may be removed or significantly modified in future versions

565

- Thorough testing recommended before production use

566

- Consider feature flags for gradual rollout

567

568

### Migration Path

569

```typescript

570

// Gradual migration approach

571

import { featureFlags, BottomTabs } from "react-native-screens";

572

573

function ConditionalBottomTabs() {

574

// Check if experimental features are stable enough

575

const useExperimental = featureFlags.experiment.controlledBottomTabs &&

576

Platform.OS === 'ios' && // Start with iOS only

577

!__DEV__; // Production ready

578

579

if (useExperimental) {

580

return <BottomTabs {...props} />;

581

}

582

583

// Fallback to stable implementation

584

return <LegacyBottomTabs {...props} />;

585

}

586

```

587

588

### Testing Recommendations

589

- Test on multiple device sizes and orientations

590

- Verify performance characteristics meet requirements

591

- Test edge cases and error scenarios

592

- Monitor memory usage and performance metrics

593

- Validate accessibility features work correctly