or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

flatlist-component.mdhoc-component.mdindex.mdscrollview-component.mdsectionlist-component.md

sectionlist-component.mddocs/

0

# KeyboardAwareSectionList Component

1

2

The KeyboardAwareSectionList is a SectionList component that automatically handles keyboard appearance by scrolling to keep focused TextInput fields visible. It extends React Native's SectionList with keyboard awareness capabilities, making it ideal for sectioned lists containing input fields.

3

4

## Capabilities

5

6

### Component Class

7

8

A SectionList component enhanced with keyboard awareness functionality.

9

10

```typescript { .api }

11

/**

12

* A SectionList component that automatically scrolls to keep focused TextInput fields visible

13

* when the keyboard appears. Extends SectionList with keyboard-aware behavior.

14

*/

15

export class KeyboardAwareSectionList<ItemT = any> extends React.Component<

16

KeyboardAwareSectionListProps<ItemT>,

17

KeyboardAwareState

18

> {

19

getScrollResponder(): any;

20

scrollToPosition(x: number, y: number, animated?: boolean): void;

21

scrollToEnd(animated?: boolean): void;

22

scrollForExtraHeightOnAndroid(extraHeight: number): void;

23

scrollToFocusedInput(

24

reactNode: any,

25

extraHeight?: number,

26

keyboardOpeningTime?: number

27

): void;

28

scrollIntoView(

29

element: React.ReactElement,

30

options?: ScrollIntoViewOptions

31

): Promise<void>;

32

update(): void;

33

}

34

35

interface KeyboardAwareSectionListProps<ItemT> extends KeyboardAwareProps, SectionListProps<ItemT> {}

36

```

37

38

**Usage Examples:**

39

40

```typescript

41

import React, { useState } from 'react';

42

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

43

import { KeyboardAwareSectionList } from 'react-native-keyboard-aware-scroll-view';

44

45

interface ContactSection {

46

title: string;

47

data: Contact[];

48

}

49

50

interface Contact {

51

id: string;

52

name: string;

53

email: string;

54

phone: string;

55

}

56

57

// Basic usage with sectioned contact form

58

export function ContactForm() {

59

const [sections] = useState<ContactSection[]>([

60

{

61

title: 'Personal Contacts',

62

data: [

63

{ id: '1', name: '', email: '', phone: '' },

64

{ id: '2', name: '', email: '', phone: '' },

65

]

66

},

67

{

68

title: 'Work Contacts',

69

data: [

70

{ id: '3', name: '', email: '', phone: '' },

71

{ id: '4', name: '', email: '', phone: '' },

72

]

73

},

74

{

75

title: 'Emergency Contacts',

76

data: [

77

{ id: '5', name: '', email: '', phone: '' },

78

]

79

}

80

]);

81

82

const renderContactItem = ({ item }: { item: Contact }) => (

83

<View style={styles.contactItem}>

84

<TextInput

85

style={styles.input}

86

placeholder="Name"

87

defaultValue={item.name}

88

/>

89

<TextInput

90

style={styles.input}

91

placeholder="Email"

92

defaultValue={item.email}

93

keyboardType="email-address"

94

/>

95

<TextInput

96

style={styles.input}

97

placeholder="Phone"

98

defaultValue={item.phone}

99

keyboardType="phone-pad"

100

/>

101

</View>

102

);

103

104

const renderSectionHeader = ({ section }: { section: ContactSection }) => (

105

<View style={styles.sectionHeader}>

106

<Text style={styles.sectionTitle}>{section.title}</Text>

107

</View>

108

);

109

110

return (

111

<KeyboardAwareSectionList

112

sections={sections}

113

renderItem={renderContactItem}

114

renderSectionHeader={renderSectionHeader}

115

keyExtractor={item => item.id}

116

style={styles.container}

117

enableOnAndroid={true}

118

extraHeight={75}

119

/>

120

);

121

}

122

123

// Advanced usage with mixed content types

124

export function SettingsForm() {

125

const [settingsSections] = useState([

126

{

127

title: 'Account Settings',

128

data: [

129

{ id: 'username', type: 'input', label: 'Username', value: '' },

130

{ id: 'email', type: 'input', label: 'Email', value: '' },

131

{ id: 'bio', type: 'textarea', label: 'Bio', value: '' },

132

]

133

},

134

{

135

title: 'Preferences',

136

data: [

137

{ id: 'theme', type: 'input', label: 'Theme Color', value: '' },

138

{ id: 'language', type: 'input', label: 'Language', value: '' },

139

]

140

}

141

]);

142

143

const renderSettingItem = ({ item }: { item: any }) => (

144

<View style={styles.settingItem}>

145

<Text style={styles.settingLabel}>{item.label}</Text>

146

{item.type === 'textarea' ? (

147

<TextInput

148

style={[styles.input, styles.textarea]}

149

placeholder={`Enter ${item.label.toLowerCase()}`}

150

defaultValue={item.value}

151

multiline

152

numberOfLines={3}

153

/>

154

) : (

155

<TextInput

156

style={styles.input}

157

placeholder={`Enter ${item.label.toLowerCase()}`}

158

defaultValue={item.value}

159

/>

160

)}

161

</View>

162

);

163

164

const renderSectionHeader = ({ section }: { section: any }) => (

165

<View style={styles.sectionHeader}>

166

<Text style={styles.sectionTitle}>{section.title}</Text>

167

</View>

168

);

169

170

return (

171

<KeyboardAwareSectionList

172

sections={settingsSections}

173

renderItem={renderSettingItem}

174

renderSectionHeader={renderSectionHeader}

175

keyExtractor={item => item.id}

176

style={styles.container}

177

enableOnAndroid={true}

178

enableAutomaticScroll={true}

179

extraHeight={100}

180

extraScrollHeight={50}

181

keyboardOpeningTime={250}

182

resetScrollToCoords={{ x: 0, y: 0 }}

183

enableResetScrollToCoords={true}

184

stickySectionHeadersEnabled={true}

185

onKeyboardWillShow={(frames) => console.log('Keyboard will show', frames)}

186

/>

187

);

188

}

189

190

const styles = StyleSheet.create({

191

container: { flex: 1, backgroundColor: '#f5f5f5' },

192

sectionHeader: {

193

backgroundColor: '#e0e0e0',

194

padding: 15,

195

borderBottomWidth: 1,

196

borderBottomColor: '#ccc',

197

},

198

sectionTitle: {

199

fontSize: 16,

200

fontWeight: 'bold',

201

color: '#333',

202

},

203

contactItem: {

204

backgroundColor: 'white',

205

padding: 15,

206

borderBottomWidth: 1,

207

borderBottomColor: '#eee',

208

},

209

settingItem: {

210

backgroundColor: 'white',

211

padding: 15,

212

borderBottomWidth: 1,

213

borderBottomColor: '#eee',

214

},

215

settingLabel: {

216

fontSize: 14,

217

fontWeight: '500',

218

marginBottom: 8,

219

color: '#333',

220

},

221

input: {

222

borderWidth: 1,

223

borderColor: '#ccc',

224

padding: 10,

225

marginBottom: 10,

226

borderRadius: 5,

227

backgroundColor: '#fafafa',

228

},

229

textarea: {

230

height: 80,

231

textAlignVertical: 'top',

232

},

233

});

234

```

235

236

### Get Scroll Responder

237

238

Gets the underlying SectionList's scroll responder for advanced scroll operations.

239

240

```typescript { .api }

241

/**

242

* Get the underlying SectionList's scroll responder

243

* @returns The scroll responder instance

244

*/

245

getScrollResponder(): any;

246

```

247

248

### Scroll to Position

249

250

Programmatically scrolls to a specific position in the SectionList.

251

252

```typescript { .api }

253

/**

254

* Scroll to specific position with or without animation

255

* @param x - The x coordinate to scroll to

256

* @param y - The y coordinate to scroll to

257

* @param animated - Whether to animate the scroll (default: true)

258

*/

259

scrollToPosition(x: number, y: number, animated?: boolean): void;

260

```

261

262

### Scroll to End

263

264

Scrolls to the end of the SectionList content.

265

266

```typescript { .api }

267

/**

268

* Scroll to end with or without animation

269

* @param animated - Whether to animate the scroll (default: true)

270

*/

271

scrollToEnd(animated?: boolean): void;

272

```

273

274

**Usage Example:**

275

276

```typescript

277

import React, { useRef } from 'react';

278

import { Button } from 'react-native';

279

import { KeyboardAwareSectionList } from 'react-native-keyboard-aware-scroll-view';

280

281

export function ScrollableSectionList({ sections }: { sections: any[] }) {

282

const sectionListRef = useRef<KeyboardAwareSectionList>(null);

283

284

const scrollToTop = () => {

285

sectionListRef.current?.scrollToPosition(0, 0, true);

286

};

287

288

const scrollToEnd = () => {

289

sectionListRef.current?.scrollToEnd(true);

290

};

291

292

return (

293

<>

294

<KeyboardAwareSectionList

295

ref={sectionListRef}

296

sections={sections}

297

renderItem={({ item }) => <YourItemComponent item={item} />}

298

renderSectionHeader={({ section }) => <YourHeaderComponent section={section} />}

299

keyExtractor={item => item.id}

300

/>

301

<Button title="Scroll to Top" onPress={scrollToTop} />

302

<Button title="Scroll to End" onPress={scrollToEnd} />

303

</>

304

);

305

}

306

```

307

308

### Android Extra Height Scroll

309

310

Android-specific method for scrolling with additional height offset.

311

312

```typescript { .api }

313

/**

314

* Android-specific scroll method with extra height offset (Android only)

315

* @param extraHeight - Additional height to add to the scroll offset

316

*/

317

scrollForExtraHeightOnAndroid(extraHeight: number): void;

318

```

319

320

### Scroll to Focused Input

321

322

Scrolls to a specific focused TextInput field within a section item.

323

324

```typescript { .api }

325

/**

326

* Scroll to a specific focused input field

327

* @param reactNode - The React node handle of the input to scroll to

328

* @param extraHeight - Additional height offset (optional)

329

* @param keyboardOpeningTime - Custom keyboard opening delay (optional)

330

*/

331

scrollToFocusedInput(

332

reactNode: any,

333

extraHeight?: number,

334

keyboardOpeningTime?: number

335

): void;

336

```

337

338

### Scroll Into View

339

340

Scrolls a React element into view with customizable positioning.

341

342

```typescript { .api }

343

/**

344

* Scrolls an element into view with customizable positioning

345

* @param element - The React element to scroll into view

346

* @param options - Configuration options for scroll positioning

347

* @returns Promise that resolves when scrolling is complete

348

*/

349

scrollIntoView(

350

element: React.ReactElement,

351

options?: ScrollIntoViewOptions

352

): Promise<void>;

353

```

354

355

### Update

356

357

Manually triggers scrolling to the currently focused input field.

358

359

```typescript { .api }

360

/**

361

* Manually trigger scroll to currently focused input

362

* Useful for updating scroll position after layout changes

363

*/

364

update(): void;

365

```

366

367

## Props

368

369

The KeyboardAwareSectionList accepts all standard SectionList props plus the KeyboardAwareProps interface:

370

371

```typescript { .api }

372

interface KeyboardAwareSectionListProps<ItemT> extends KeyboardAwareProps, SectionListProps<ItemT> {

373

// Inherits all SectionList props (sections, renderItem, renderSectionHeader, etc.)

374

// Plus all KeyboardAwareProps (see main documentation)

375

}

376

```

377

378

## Common Use Cases

379

380

### User Profile Sections

381

382

```typescript

383

import React, { useState } from 'react';

384

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

385

import { KeyboardAwareSectionList } from 'react-native-keyboard-aware-scroll-view';

386

387

export function UserProfileSections() {

388

const [profileSections] = useState([

389

{

390

title: 'Basic Information',

391

data: [

392

{ id: 'firstName', label: 'First Name', value: '' },

393

{ id: 'lastName', label: 'Last Name', value: '' },

394

{ id: 'email', label: 'Email', value: '' },

395

]

396

},

397

{

398

title: 'Contact Details',

399

data: [

400

{ id: 'phone', label: 'Phone Number', value: '' },

401

{ id: 'address', label: 'Address', value: '' },

402

{ id: 'city', label: 'City', value: '' },

403

]

404

},

405

{

406

title: 'Additional Info',

407

data: [

408

{ id: 'bio', label: 'Bio', value: '', multiline: true },

409

{ id: 'website', label: 'Website', value: '' },

410

]

411

}

412

]);

413

414

const renderProfileItem = ({ item }: { item: any }) => (

415

<View style={{ padding: 15, backgroundColor: 'white' }}>

416

<Text style={{ marginBottom: 8, fontWeight: '500' }}>{item.label}</Text>

417

<TextInput

418

style={{

419

borderWidth: 1,

420

borderColor: '#ccc',

421

padding: 10,

422

borderRadius: 5,

423

height: item.multiline ? 80 : 40,

424

}}

425

placeholder={`Enter ${item.label.toLowerCase()}`}

426

defaultValue={item.value}

427

multiline={item.multiline}

428

textAlignVertical={item.multiline ? 'top' : 'center'}

429

/>

430

</View>

431

);

432

433

const renderSectionHeader = ({ section }: { section: any }) => (

434

<View style={{ backgroundColor: '#f0f0f0', padding: 12 }}>

435

<Text style={{ fontSize: 16, fontWeight: 'bold' }}>{section.title}</Text>

436

</View>

437

);

438

439

return (

440

<KeyboardAwareSectionList

441

sections={profileSections}

442

renderItem={renderProfileItem}

443

renderSectionHeader={renderSectionHeader}

444

keyExtractor={item => item.id}

445

enableOnAndroid={true}

446

extraHeight={100}

447

stickySectionHeadersEnabled={true}

448

/>

449

);

450

}

451

```

452

453

## Platform Support

454

455

- **iOS**: Full support for all features

456

- **Android**: Requires `enableOnAndroid={true}` and `windowSoftInputMode="adjustPan"` in AndroidManifest.xml for full functionality