or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdscene-map.mdtab-bar-indicator.mdtab-bar-item.mdtab-bar.mdtab-view.md

tab-bar-item.mddocs/

0

# Tab Bar Item

1

2

The TabBarItem component represents an individual tab in the tab bar. It handles rendering of labels, icons, badges, and provides touch interaction capabilities with accessibility support. Each tab item automatically adapts its appearance based on the active/inactive state.

3

4

## Capabilities

5

6

### TabBarItem Component

7

8

Individual tab item component with support for labels, icons, badges, and custom rendering.

9

10

```typescript { .api }

11

/**

12

* Individual tab item component for rendering single tabs

13

* @param props - TabBarItem configuration and interaction handlers

14

* @returns JSX element containing the tab item interface

15

*/

16

function TabBarItem<T extends Route>(props: Props<T>): JSX.Element;

17

18

interface Props<T extends Route> extends TabDescriptor<T> {

19

/** Animated position value for state transitions */

20

position: Animated.AnimatedInterpolation<number>;

21

/** Route object associated with this tab */

22

route: T;

23

/** Complete navigation state */

24

navigationState: NavigationState<T>;

25

/** Active tab color override */

26

activeColor?: string;

27

/** Inactive tab color override */

28

inactiveColor?: string;

29

/** Press ripple color (Android) */

30

pressColor?: string;

31

/** Press opacity effect value */

32

pressOpacity?: number;

33

/** Layout measurement event handler */

34

onLayout?: (event: LayoutChangeEvent) => void;

35

/** Required press event handler */

36

onPress: () => void;

37

/** Required long press event handler */

38

onLongPress: () => void;

39

/** Default tab width for layout calculations */

40

defaultTabWidth?: number;

41

/** Tab container styling */

42

style: StyleProp<ViewStyle>;

43

/** Android ripple effect configuration */

44

android_ripple?: PressableAndroidRippleConfig;

45

}

46

```

47

48

**Usage Examples:**

49

50

```typescript

51

import React from 'react';

52

import { TabBar, TabBarItem } from 'react-native-tab-view';

53

import Icon from 'react-native-vector-icons/MaterialIcons';

54

55

// Custom tab item with icon

56

const renderTabBar = (props) => (

57

<TabBar

58

{...props}

59

renderTabBarItem={({ route, ...itemProps }) => (

60

<TabBarItem

61

{...itemProps}

62

route={route}

63

icon={({ focused, color }) => (

64

<Icon

65

name={getIconName(route.key)}

66

size={24}

67

color={color}

68

/>

69

)}

70

activeColor="#1976d2"

71

inactiveColor="#757575"

72

/>

73

)}

74

/>

75

);

76

77

// Tab item with badge

78

const renderTabBarWithBadges = (props) => (

79

<TabBar

80

{...props}

81

renderTabBarItem={({ route, ...itemProps }) => (

82

<TabBarItem

83

{...itemProps}

84

route={route}

85

badge={({ route }) => {

86

const count = getBadgeCount(route.key);

87

return count > 0 ? (

88

<View style={styles.badge}>

89

<Text style={styles.badgeText}>{count}</Text>

90

</View>

91

) : null;

92

}}

93

/>

94

)}

95

/>

96

);

97

98

// Custom label rendering

99

const renderTabBarWithCustomLabels = (props) => (

100

<TabBar

101

{...props}

102

renderTabBarItem={({ route, ...itemProps }) => (

103

<TabBarItem

104

{...itemProps}

105

route={route}

106

label={({ focused, color, labelText }) => (

107

<Text

108

style={[

109

{ color, fontSize: 12 },

110

focused && { fontWeight: 'bold', fontSize: 14 }

111

]}

112

>

113

{labelText?.toUpperCase()}

114

</Text>

115

)}

116

/>

117

)}

118

/>

119

);

120

```

121

122

### Tab Item Configuration

123

124

Configure tab appearance and behavior through TabDescriptor interface.

125

126

```typescript { .api }

127

/**

128

* Configuration interface for tab appearance and behavior

129

*/

130

interface TabDescriptor<T extends Route> {

131

/** Override accessibility label */

132

accessibilityLabel?: string;

133

/** Override accessibility enabled flag */

134

accessible?: boolean;

135

/** Test identifier for automation */

136

testID?: string;

137

/** Override tab label text */

138

labelText?: string;

139

/** Allow font scaling for accessibility */

140

labelAllowFontScaling?: boolean;

141

/** Web navigation href */

142

href?: string;

143

/** Custom label renderer function */

144

label?: (props: LabelProps<T>) => React.ReactNode;

145

/** Label text styling */

146

labelStyle?: StyleProp<TextStyle>;

147

/** Custom icon renderer function */

148

icon?: (props: IconProps<T>) => React.ReactNode;

149

/** Custom badge renderer function */

150

badge?: (props: BadgeProps<T>) => React.ReactElement;

151

/** Scene container styling */

152

sceneStyle?: StyleProp<ViewStyle>;

153

}

154

155

/**

156

* Props for custom label renderers

157

*/

158

interface LabelProps<T extends Route> {

159

route: T;

160

labelText?: string;

161

focused: boolean;

162

color: string;

163

allowFontScaling?: boolean;

164

style?: StyleProp<TextStyle>;

165

}

166

167

/**

168

* Props for custom icon renderers

169

*/

170

interface IconProps<T extends Route> {

171

route: T;

172

focused: boolean;

173

color: string;

174

size: number;

175

}

176

177

/**

178

* Props for custom badge renderers

179

*/

180

interface BadgeProps<T extends Route> {

181

route: T;

182

}

183

```

184

185

### Animation and State Management

186

187

Tab items automatically animate between active and inactive states.

188

189

```typescript { .api }

190

/**

191

* Animation configuration for tab state transitions

192

*/

193

interface TabAnimationConfig {

194

/** Default active color */

195

DEFAULT_ACTIVE_COLOR: 'rgba(255, 255, 255, 1)';

196

/** Default inactive color */

197

DEFAULT_INACTIVE_COLOR: 'rgba(255, 255, 255, 0.7)';

198

/** Default icon size */

199

ICON_SIZE: 24;

200

}

201

202

/**

203

* Opacity calculation functions for smooth transitions

204

*/

205

interface OpacityCalculations {

206

/** Calculate active state opacity */

207

getActiveOpacity: (

208

position: Animated.AnimatedInterpolation<number>,

209

routesLength: number,

210

tabIndex: number

211

) => Animated.AnimatedInterpolation<number> | number;

212

/** Calculate inactive state opacity */

213

getInactiveOpacity: (

214

position: Animated.AnimatedInterpolation<number>,

215

routesLength: number,

216

tabIndex: number

217

) => Animated.AnimatedInterpolation<number> | number;

218

}

219

```

220

221

**Animation Examples:**

222

223

```typescript

224

// Custom animated tab item

225

const AnimatedTabItem = ({ route, focused, position, ...props }) => {

226

const scale = position.interpolate({

227

inputRange: [route.index - 1, route.index, route.index + 1],

228

outputRange: [0.9, 1.1, 0.9],

229

extrapolate: 'clamp',

230

});

231

232

return (

233

<Animated.View style={{ transform: [{ scale }] }}>

234

<TabBarItem {...props} route={route} />

235

</Animated.View>

236

);

237

};

238

```

239

240

### Platform-Specific Features

241

242

TabBarItem handles platform differences automatically.

243

244

```typescript { .api }

245

/**

246

* Android-specific ripple configuration

247

*/

248

interface PressableAndroidRippleConfig {

249

/** Ripple effect color */

250

color?: string;

251

/** Whether ripple extends beyond component bounds */

252

borderless?: boolean;

253

/** Ripple radius */

254

radius?: number;

255

}

256

257

/**

258

* Default Android ripple configuration

259

*/

260

const ANDROID_RIPPLE_DEFAULT: PressableAndroidRippleConfig = {

261

borderless: true

262

};

263

```

264

265

**Platform Examples:**

266

267

```typescript

268

// Platform-specific styling

269

const renderPlatformTabBar = (props) => (

270

<TabBar

271

{...props}

272

renderTabBarItem={({ route, ...itemProps }) => (

273

<TabBarItem

274

{...itemProps}

275

route={route}

276

android_ripple={{

277

color: '#e3f2fd',

278

borderless: true,

279

radius: 32,

280

}}

281

style={Platform.select({

282

ios: { borderRadius: 10 }, // iPad hover effect

283

android: { backgroundColor: 'transparent' },

284

default: { backgroundColor: 'transparent' },

285

})}

286

/>

287

)}

288

/>

289

);

290

```

291

292

### Accessibility Support

293

294

TabBarItem provides comprehensive accessibility features.

295

296

```typescript { .api }

297

/**

298

* Accessibility configuration

299

*/

300

interface AccessibilityConfig {

301

/** ARIA role for web accessibility */

302

role: 'tab';

303

/** ARIA label attribute */

304

'aria-label': string;

305

/** ARIA selected state */

306

'aria-selected': boolean;

307

/** React Native accessibility properties */

308

accessible: boolean;

309

accessibilityLabel: string;

310

}

311

```

312

313

**Accessibility Examples:**

314

315

```typescript

316

// Enhanced accessibility

317

const renderAccessibleTabBar = (props) => (

318

<TabBar

319

{...props}

320

renderTabBarItem={({ route, ...itemProps }) => (

321

<TabBarItem

322

{...itemProps}

323

route={route}

324

accessible={true}

325

accessibilityLabel={`${route.title} tab`}

326

accessibilityHint={`Navigate to ${route.title} screen`}

327

testID={`tab-${route.key}`}

328

/>

329

)}

330

/>

331

);

332

```

333

334

### Styling and Layout

335

336

Complete control over tab item appearance and layout.

337

338

```typescript { .api }

339

/**

340

* Default tab item styles

341

*/

342

interface DefaultTabStyles {

343

/** Icon container styling */

344

icon: {

345

margin: 2;

346

};

347

/** Main item container */

348

item: {

349

flex: 1;

350

alignItems: 'center';

351

justifyContent: 'center';

352

padding: 10;

353

minHeight: 48;

354

};

355

/** Badge positioning */

356

badge: {

357

position: 'absolute';

358

top: 0;

359

end: 0;

360

};

361

/** Pressable container */

362

pressable: {

363

backgroundColor: 'transparent';

364

};

365

}

366

```

367

368

**Advanced Styling Examples:**

369

370

```typescript

371

// Custom tab item styling

372

const renderStyledTabBar = (props) => (

373

<TabBar

374

{...props}

375

renderTabBarItem={({ route, focused, ...itemProps }) => (

376

<TabBarItem

377

{...itemProps}

378

route={route}

379

style={[

380

styles.tabItem,

381

focused && styles.tabItemFocused,

382

{ minWidth: 100 }

383

]}

384

labelStyle={[

385

styles.tabLabel,

386

focused && styles.tabLabelFocused,

387

]}

388

pressOpacity={0.7}

389

/>

390

)}

391

/>

392

);

393

394

const styles = StyleSheet.create({

395

tabItem: {

396

borderRadius: 8,

397

marginHorizontal: 4,

398

paddingVertical: 8,

399

},

400

tabItemFocused: {

401

backgroundColor: 'rgba(33, 150, 243, 0.1)',

402

},

403

tabLabel: {

404

fontSize: 12,

405

fontWeight: '500',

406

},

407

tabLabelFocused: {

408

fontSize: 14,

409

fontWeight: '700',

410

},

411

});

412

```

413

414

### Event Handling

415

416

Handle user interactions with custom logic.

417

418

```typescript { .api }

419

/**

420

* Event handler types

421

*/

422

interface EventHandlers {

423

/** Press event handler */

424

onPress: () => void;

425

/** Long press event handler */

426

onLongPress: () => void;

427

/** Layout measurement handler */

428

onLayout?: (event: LayoutChangeEvent) => void;

429

}

430

431

/**

432

* Layout change event structure

433

*/

434

interface LayoutChangeEvent {

435

nativeEvent: {

436

layout: {

437

x: number;

438

y: number;

439

width: number;

440

height: number;

441

};

442

};

443

}

444

```

445

446

**Event Handling Examples:**

447

448

```typescript

449

// Custom event handling

450

const renderInteractiveTabBar = (props) => (

451

<TabBar

452

{...props}

453

renderTabBarItem={({ route, onPress, onLongPress, ...itemProps }) => (

454

<TabBarItem

455

{...itemProps}

456

route={route}

457

onPress={() => {

458

console.log('Tab pressed:', route.key);

459

onPress();

460

}}

461

onLongPress={() => {

462

console.log('Tab long pressed:', route.key);

463

showTabContextMenu(route);

464

onLongPress();

465

}}

466

onLayout={(event) => {

467

const { width, height } = event.nativeEvent.layout;

468

console.log(`Tab ${route.key} size:`, { width, height });

469

}}

470

/>

471

)}

472

/>

473

);

474

```