or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-components.mdbuttons.mdcomponents.mdconstants.mdevents.mdgestures.mdindex.mdsetup.md

advanced-components.mddocs/

0

# Advanced Layout Components

1

2

Sophisticated layout and interaction components for complex UI patterns like swipe-to-reveal and drawer layouts.

3

4

## Capabilities

5

6

### Swipeable

7

8

Component for creating swipe-to-reveal interfaces, commonly used in messaging apps and todo lists for contextual actions.

9

10

```typescript { .api }

11

/**

12

* Swipeable component for creating swipe-to-reveal interfaces

13

* Provides left and right swipe actions with customizable animations

14

*/

15

function Swipeable(props: {

16

friction?: number;

17

leftThreshold?: number;

18

rightThreshold?: number;

19

dragOffsetFromLeftEdge?: number;

20

dragOffsetFromRightEdge?: number;

21

overshootLeft?: boolean;

22

overshootRight?: boolean;

23

overshootFriction?: number;

24

onSwipeableLeftOpen?: () => void;

25

onSwipeableRightOpen?: () => void;

26

onSwipeableOpen?: (direction: "left" | "right") => void;

27

onSwipeableClose?: (direction: "left" | "right") => void;

28

onSwipeableLeftWillOpen?: () => void;

29

onSwipeableRightWillOpen?: () => void;

30

onSwipeableWillOpen?: (direction: "left" | "right") => void;

31

onSwipeableWillClose?: (direction: "left" | "right") => void;

32

renderLeftActions?: (

33

progressAnimatedValue: Animated.AnimatedAddition,

34

dragX: Animated.AnimatedAddition

35

) => React.ReactNode;

36

renderRightActions?: (

37

progressAnimatedValue: Animated.AnimatedAddition,

38

dragX: Animated.AnimatedAddition

39

) => React.ReactNode;

40

useNativeAnimations?: boolean;

41

animationOptions?: object;

42

containerStyle?: StyleProp<ViewStyle>;

43

childrenContainerStyle?: StyleProp<ViewStyle>;

44

enableTrackpadTwoFingerGesture?: boolean;

45

children: React.ReactNode;

46

}): JSX.Element;

47

48

interface SwipeableProps {

49

friction?: number;

50

leftThreshold?: number;

51

rightThreshold?: number;

52

dragOffsetFromLeftEdge?: number;

53

dragOffsetFromRightEdge?: number;

54

overshootLeft?: boolean;

55

overshootRight?: boolean;

56

overshootFriction?: number;

57

onSwipeableLeftOpen?: () => void;

58

onSwipeableRightOpen?: () => void;

59

onSwipeableOpen?: (direction: "left" | "right") => void;

60

onSwipeableClose?: (direction: "left" | "right") => void;

61

onSwipeableLeftWillOpen?: () => void;

62

onSwipeableRightWillOpen?: () => void;

63

onSwipeableWillOpen?: (direction: "left" | "right") => void;

64

onSwipeableWillClose?: (direction: "left" | "right") => void;

65

renderLeftActions?: (

66

progressAnimatedValue: Animated.AnimatedAddition,

67

dragX: Animated.AnimatedAddition

68

) => React.ReactNode;

69

renderRightActions?: (

70

progressAnimatedValue: Animated.AnimatedAddition,

71

dragX: Animated.AnimatedAddition

72

) => React.ReactNode;

73

useNativeAnimations?: boolean;

74

animationOptions?: object;

75

containerStyle?: StyleProp<ViewStyle>;

76

childrenContainerStyle?: StyleProp<ViewStyle>;

77

enableTrackpadTwoFingerGesture?: boolean;

78

children: React.ReactNode;

79

}

80

```

81

82

**Usage Example:**

83

84

```typescript

85

import React, { useRef } from "react";

86

import { View, Text, Animated, TouchableOpacity } from "react-native";

87

import { Swipeable } from "react-native-gesture-handler";

88

89

function SwipeableItem({ item, onDelete, onArchive }) {

90

const swipeableRef = useRef<Swipeable>(null);

91

92

const renderLeftActions = (progress, dragX) => {

93

const trans = dragX.interpolate({

94

inputRange: [0, 50, 100, 101],

95

outputRange: [-20, 0, 0, 1],

96

extrapolate: "clamp",

97

});

98

99

return (

100

<View style={{ flex: 1, backgroundColor: "green", justifyContent: "center" }}>

101

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

102

<TouchableOpacity

103

onPress={() => {

104

onArchive(item.id);

105

swipeableRef.current?.close();

106

}}

107

style={{ paddingHorizontal: 20 }}

108

>

109

<Text style={{ color: "white", fontWeight: "bold" }}>Archive</Text>

110

</TouchableOpacity>

111

</Animated.View>

112

</View>

113

);

114

};

115

116

const renderRightActions = (progress, dragX) => {

117

const trans = dragX.interpolate({

118

inputRange: [-101, -100, -50, 0],

119

outputRange: [1, 0, 0, 20],

120

extrapolate: "clamp",

121

});

122

123

return (

124

<View style={{ flex: 1, backgroundColor: "red", justifyContent: "center" }}>

125

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

126

<TouchableOpacity

127

onPress={() => {

128

onDelete(item.id);

129

swipeableRef.current?.close();

130

}}

131

style={{ paddingHorizontal: 20 }}

132

>

133

<Text style={{ color: "white", fontWeight: "bold" }}>Delete</Text>

134

</TouchableOpacity>

135

</Animated.View>

136

</View>

137

);

138

};

139

140

return (

141

<Swipeable

142

ref={swipeableRef}

143

renderLeftActions={renderLeftActions}

144

renderRightActions={renderRightActions}

145

leftThreshold={80}

146

rightThreshold={80}

147

friction={1.5}

148

>

149

<View style={{

150

padding: 15,

151

backgroundColor: "white",

152

borderBottomWidth: 1,

153

borderBottomColor: "#eee"

154

}}>

155

<Text>{item.title}</Text>

156

</View>

157

</Swipeable>

158

);

159

}

160

```

161

162

### Pressable

163

164

Modern pressable component using the new gesture API, providing advanced press handling with gesture coordination.

165

166

```typescript { .api }

167

/**

168

* Modern pressable component using the new gesture API

169

* Provides sophisticated press detection with gesture relationship management

170

*/

171

function Pressable(props: {

172

children?: React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode);

173

onPress?: (event?: GestureResponderEvent) => void;

174

onPressIn?: (event?: GestureResponderEvent) => void;

175

onPressOut?: (event?: GestureResponderEvent) => void;

176

onLongPress?: (event?: GestureResponderEvent) => void;

177

onHoverIn?: (event?: MouseEvent) => void;

178

onHoverOut?: (event?: MouseEvent) => void;

179

disabled?: boolean;

180

delayLongPress?: number;

181

hitSlop?: Insets;

182

pressRetentionOffset?: Insets;

183

android_disableSound?: boolean;

184

android_ripple?: AndroidRippleConfig;

185

testID?: string;

186

style?: StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>);

187

unstable_pressDelay?: number;

188

// Gesture Handler specific props

189

simultaneousWithExternalGesture?: GestureRef[];

190

requireExternalGestureToFail?: GestureRef[];

191

blocksExternalGesture?: GestureRef[];

192

}): JSX.Element;

193

194

interface PressableProps {

195

children?: React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode);

196

onPress?: (event?: GestureResponderEvent) => void;

197

onPressIn?: (event?: GestureResponderEvent) => void;

198

onPressOut?: (event?: GestureResponderEvent) => void;

199

onLongPress?: (event?: GestureResponderEvent) => void;

200

onHoverIn?: (event?: MouseEvent) => void;

201

onHoverOut?: (event?: MouseEvent) => void;

202

disabled?: boolean;

203

delayLongPress?: number;

204

hitSlop?: Insets;

205

pressRetentionOffset?: Insets;

206

android_disableSound?: boolean;

207

android_ripple?: AndroidRippleConfig;

208

testID?: string;

209

style?: StyleProp<ViewStyle> | ((state: PressableStateCallbackType) => StyleProp<ViewStyle>);

210

unstable_pressDelay?: number;

211

simultaneousWithExternalGesture?: GestureRef[];

212

requireExternalGestureToFail?: GestureRef[];

213

blocksExternalGesture?: GestureRef[];

214

}

215

216

interface PressableStateCallbackType {

217

pressed: boolean;

218

hovered?: boolean;

219

focused?: boolean;

220

}

221

222

interface AndroidRippleConfig {

223

color?: string;

224

borderless?: boolean;

225

radius?: number;

226

foreground?: boolean;

227

}

228

```

229

230

**Usage Example:**

231

232

```typescript

233

import React from "react";

234

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

235

import { Pressable } from "react-native-gesture-handler";

236

237

function MyPressable() {

238

return (

239

<Pressable

240

onPress={() => console.log("Pressable pressed")}

241

onLongPress={() => console.log("Pressable long pressed")}

242

android_ripple={{ color: "rgba(0,0,0,0.1)", borderless: false }}

243

style={({ pressed }) => [

244

{

245

padding: 15,

246

backgroundColor: pressed ? "#e0e0e0" : "white",

247

borderRadius: 8,

248

borderWidth: 1,

249

borderColor: "#ccc",

250

},

251

]}

252

>

253

{({ pressed }) => (

254

<Text style={{ color: pressed ? "blue" : "black" }}>

255

{pressed ? "Pressed!" : "Press me"}

256

</Text>

257

)}

258

</Pressable>

259

);

260

}

261

```

262

263

### DrawerLayout (Deprecated)

264

265

Drawer layout component for creating side navigation panels. This component is deprecated in favor of the react-native-reanimated version.

266

267

```typescript { .api }

268

/**

269

* Drawer layout component (deprecated)

270

* Use react-native-reanimated drawer implementations instead

271

* @deprecated Use DrawerLayout from react-native-reanimated

272

*/

273

function DrawerLayout(props: {

274

drawerPosition: DrawerPosition;

275

drawerWidth?: number;

276

drawerBackgroundColor?: string;

277

drawerLockMode?: DrawerLockMode;

278

keyboardDismissMode?: DrawerKeyboardDismissMode;

279

onDrawerClose?: () => void;

280

onDrawerOpen?: () => void;

281

onDrawerSlide?: (event: DrawerSlideEvent) => void;

282

onDrawerStateChanged?: (newState: DrawerState) => void;

283

renderNavigationView: () => React.ReactNode;

284

statusBarBackgroundColor?: string;

285

drawerType?: DrawerType;

286

overlayColor?: string;

287

contentContainerStyle?: StyleProp<ViewStyle>;

288

edgeWidth?: number;

289

minSwipeDistance?: number;

290

hideStatusBar?: boolean;

291

statusBarAnimation?: "slide" | "fade" | "none";

292

children?: React.ReactNode;

293

}): JSX.Element;

294

295

interface DrawerLayoutProps {

296

drawerPosition: DrawerPosition;

297

drawerWidth?: number;

298

drawerBackgroundColor?: string;

299

drawerLockMode?: DrawerLockMode;

300

keyboardDismissMode?: DrawerKeyboardDismissMode;

301

onDrawerClose?: () => void;

302

onDrawerOpen?: () => void;

303

onDrawerSlide?: (event: DrawerSlideEvent) => void;

304

onDrawerStateChanged?: (newState: DrawerState) => void;

305

renderNavigationView: () => React.ReactNode;

306

statusBarBackgroundColor?: string;

307

drawerType?: DrawerType;

308

overlayColor?: string;

309

contentContainerStyle?: StyleProp<ViewStyle>;

310

edgeWidth?: number;

311

minSwipeDistance?: number;

312

hideStatusBar?: boolean;

313

statusBarAnimation?: "slide" | "fade" | "none";

314

children?: React.ReactNode;

315

}

316

317

// Drawer-related types

318

type DrawerPosition = "left" | "right";

319

type DrawerState = "Idle" | "Dragging" | "Settling";

320

type DrawerType = "front" | "back" | "slide";

321

type DrawerLockMode = "unlocked" | "locked-closed" | "locked-open";

322

type DrawerKeyboardDismissMode = "none" | "on-drag";

323

324

interface DrawerSlideEvent {

325

nativeEvent: {

326

offset: number;

327

};

328

}

329

```

330

331

## Utility Components

332

333

### createNativeWrapper

334

335

Function for wrapping React Native components to add gesture handler capabilities.

336

337

```typescript { .api }

338

/**

339

* Creates a native wrapper for React Native components

340

* Adds gesture handling capabilities to existing components

341

*/

342

function createNativeWrapper<T>(

343

Component: React.ComponentType<T>,

344

config?: {

345

shouldCancelWhenOutside?: boolean;

346

shouldActivateOnStart?: boolean;

347

disallowInterruption?: boolean;

348

}

349

): React.ComponentType<T & {

350

waitFor?: React.Ref<any> | React.Ref<any>[];

351

simultaneousHandlers?: React.Ref<any> | React.Ref<any>[];

352

}>;

353

```

354

355

**Usage Example:**

356

357

```typescript

358

import React from "react";

359

import { View } from "react-native";

360

import { createNativeWrapper } from "react-native-gesture-handler";

361

362

const WrappedView = createNativeWrapper(View, {

363

shouldCancelWhenOutside: true,

364

shouldActivateOnStart: true,

365

});

366

367

function MyWrappedView() {

368

return (

369

<WrappedView

370

style={{ width: 100, height: 100, backgroundColor: "red" }}

371

onGestureEvent={(event) => {

372

console.log("Gesture event:", event.nativeEvent);

373

}}

374

/>

375

);

376

}

377

```

378

379

## Advanced Animation Integration

380

381

### Reanimated Integration

382

383

Advanced components work seamlessly with react-native-reanimated for smooth animations:

384

385

```typescript

386

import React from "react";

387

import { View } from "react-native";

388

import Animated, {

389

useSharedValue,

390

useAnimatedStyle,

391

withSpring

392

} from "react-native-reanimated";

393

import { Pressable } from "react-native-gesture-handler";

394

395

function AnimatedPressable() {

396

const scale = useSharedValue(1);

397

398

const animatedStyle = useAnimatedStyle(() => ({

399

transform: [{ scale: scale.value }],

400

}));

401

402

return (

403

<Pressable

404

onPressIn={() => {

405

scale.value = withSpring(0.95);

406

}}

407

onPressOut={() => {

408

scale.value = withSpring(1);

409

}}

410

>

411

<Animated.View style={[{ padding: 20, backgroundColor: "blue" }, animatedStyle]}>

412

{/* Content */}

413

</Animated.View>

414

</Pressable>

415

);

416

}

417

```

418

419

### Swipeable Animation Customization

420

421

Customize Swipeable animations with detailed control:

422

423

```typescript

424

import React from "react";

425

import { View, Text, Animated } from "react-native";

426

import { Swipeable } from "react-native-gesture-handler";

427

428

function CustomAnimatedSwipeable() {

429

const renderRightActions = (progress, dragX) => {

430

// Custom scaling animation

431

const scale = progress.interpolate({

432

inputRange: [0, 1],

433

outputRange: [0.8, 1],

434

});

435

436

// Custom opacity animation

437

const opacity = progress.interpolate({

438

inputRange: [0, 0.5, 1],

439

outputRange: [0, 0.5, 1],

440

});

441

442

return (

443

<Animated.View

444

style={{

445

flex: 1,

446

backgroundColor: "red",

447

justifyContent: "center",

448

alignItems: "center",

449

transform: [{ scale }],

450

opacity,

451

}}

452

>

453

<Text style={{ color: "white", fontWeight: "bold" }}>Delete</Text>

454

</Animated.View>

455

);

456

};

457

458

return (

459

<Swipeable

460

renderRightActions={renderRightActions}

461

friction={1.5}

462

rightThreshold={40}

463

>

464

<View style={{ padding: 20, backgroundColor: "white" }}>

465

<Text>Swipe left for custom animation</Text>

466

</View>

467

</Swipeable>

468

);

469

}

470

```

471

472

## Performance Considerations

473

474

### Memory Management

475

476

Advanced components are optimized for memory efficiency:

477

478

- Automatic cleanup of gesture recognizers

479

- Efficient animation value management

480

- Reduced memory allocation during gestures

481

482

### Native Performance

483

484

Components leverage native implementations for optimal performance:

485

486

- Native thread gesture recognition

487

- Hardware-accelerated animations

488

- Minimal JavaScript bridge usage during interactions

489

490

### Best Practices

491

492

```typescript

493

// ✅ Good: Use refs for programmatic control

494

const swipeableRef = useRef<Swipeable>(null);

495

496

// ✅ Good: Cleanup in useEffect

497

useEffect(() => {

498

return () => {

499

swipeableRef.current?.close();

500

};

501

}, []);

502

503

// ❌ Avoid: Creating new objects in render

504

const renderActions = () => ({ flex: 1 }); // Creates new object each render

505

506

// ✅ Better: Use static styles or useMemo

507

const actionStyles = { flex: 1 };

508

const renderActions = () => actionStyles;

509

```