or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-creation.mdconfiguration.mdindex.mdreact-native-features.mdstyling-theming.mdutilities.md

react-native-features.mddocs/

0

# React Native Features

1

2

React Native-specific enhancements including layout measurement, pressability handling, platform optimizations, and cross-platform compatibility features.

3

4

## Capabilities

5

6

### Layout Measurement

7

8

Element layout measurement system providing React Native-style layout information on both platforms.

9

10

```typescript { .api }

11

/**

12

* Hook for tracking element layout changes

13

* @param stateRef - Component state reference

14

* @param onLayout - Layout change callback

15

* @returns Layout measurement utilities

16

*/

17

function useElementLayout(

18

stateRef?: React.MutableRefObject<any>,

19

onLayout?: (event: LayoutEvent) => void

20

): LayoutMeasurement;

21

22

/**

23

* Set the layout measurement strategy

24

* @param strategy - Measurement strategy to use

25

*/

26

function setOnLayoutStrategy(strategy: LayoutStrategy): void;

27

28

/**

29

* Create element measurement function

30

* @param element - Element to measure

31

* @returns Measurement function

32

*/

33

function createMeasure(element: Element): MeasureFunction;

34

35

/**

36

* Create window-relative measurement function

37

* @param element - Element to measure

38

* @returns Window measurement function

39

*/

40

function createMeasureInWindow(element: Element): MeasureInWindowFunction;

41

42

/**

43

* Create layout measurement function

44

* @param element - Element to measure

45

* @returns Layout measurement function

46

*/

47

function createMeasureLayout(element: Element): MeasureLayoutFunction;

48

49

interface LayoutEvent {

50

nativeEvent: {

51

layout: {

52

x: number;

53

y: number;

54

width: number;

55

height: number;

56

};

57

};

58

}

59

60

type LayoutStrategy = 'native' | 'web';

61

62

interface LayoutMeasurement {

63

x: number;

64

y: number;

65

width: number;

66

height: number;

67

}

68

69

type MeasureFunction = (callback: (x: number, y: number, width: number, height: number, pageX: number, pageY: number) => void) => void;

70

71

type MeasureInWindowFunction = (callback: (x: number, y: number, width: number, height: number) => void) => void;

72

73

type MeasureLayoutFunction = (relativeTo: Element, callback: (left: number, top: number, width: number, height: number) => void) => void;

74

```

75

76

**Usage Examples:**

77

78

```typescript

79

import { useElementLayout, View, Text } from "@tamagui/core";

80

81

function MeasuredComponent() {

82

const [layout, setLayout] = useState(null);

83

84

const handleLayout = (event: LayoutEvent) => {

85

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

86

setLayout({ x, y, width, height });

87

};

88

89

useElementLayout(undefined, handleLayout);

90

91

return (

92

<View onLayout={handleLayout}>

93

<Text>

94

{layout && `Size: ${layout.width}x${layout.height}`}

95

</Text>

96

</View>

97

);

98

}

99

100

// Manual measurement

101

function ManualMeasurement() {

102

const elementRef = useRef(null);

103

104

const measureElement = () => {

105

if (elementRef.current?.measure) {

106

elementRef.current.measure((x, y, width, height, pageX, pageY) => {

107

console.log('Element measurements:', { x, y, width, height, pageX, pageY });

108

});

109

}

110

};

111

112

return (

113

<View ref={elementRef}>

114

<button onClick={measureElement}>Measure Me</button>

115

</View>

116

);

117

}

118

```

119

120

### Pressability System

121

122

React Native pressability system for handling touch interactions with smooth press states.

123

124

```typescript { .api }

125

/**

126

* Hook for React Native-style pressability (native platform only)

127

* @param events - Event handlers for press interactions

128

* @returns Pressability props to spread on components

129

*/

130

function usePressability(events?: PressabilityEvents): PressabilityConfig;

131

132

interface PressabilityEvents {

133

/** Called when press begins */

134

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

135

/** Called when press ends */

136

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

137

/** Called when press completes */

138

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

139

/** Called when press is cancelled */

140

onPressCancel?: (event: PressEvent) => void;

141

/** Called when long press is detected */

142

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

143

/** Hit area expansion */

144

hitSlop?: HitSlop;

145

/** Delay before onPressIn */

146

delayPressIn?: number;

147

/** Delay before onPressOut */

148

delayPressOut?: number;

149

/** Delay before onLongPress */

150

delayLongPress?: number;

151

/** Minimum press duration */

152

minPressDuration?: number;

153

}

154

155

interface PressabilityConfig {

156

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

157

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

158

onResponderGrant?: (event: ResponderEvent) => void;

159

onResponderMove?: (event: ResponderEvent) => void;

160

onResponderRelease?: (event: ResponderEvent) => void;

161

onResponderTerminate?: (event: ResponderEvent) => void;

162

onStartShouldSetResponder?: () => boolean;

163

onMoveShouldSetResponder?: () => boolean;

164

}

165

166

interface PressEvent {

167

nativeEvent: {

168

locationX: number;

169

locationY: number;

170

pageX: number;

171

pageY: number;

172

target: any;

173

timestamp: number;

174

};

175

}

176

177

interface HitSlop {

178

top?: number;

179

left?: number;

180

bottom?: number;

181

right?: number;

182

}

183

```

184

185

**Usage Examples:**

186

187

```typescript

188

import { usePressability, View, Text } from "@tamagui/core";

189

190

function PressableButton({ onPress, children }) {

191

const pressability = usePressability({

192

onPress,

193

onPressIn: () => console.log('Press started'),

194

onPressOut: () => console.log('Press ended'),

195

onLongPress: () => console.log('Long press detected'),

196

hitSlop: { top: 10, left: 10, bottom: 10, right: 10 },

197

delayLongPress: 500,

198

});

199

200

return (

201

<View

202

{...pressability}

203

style={{

204

padding: 16,

205

backgroundColor: '#007AFF',

206

borderRadius: 8,

207

}}

208

>

209

<Text style={{ color: 'white', textAlign: 'center' }}>

210

{children}

211

</Text>

212

</View>

213

);

214

}

215

```

216

217

### Responder Events

218

219

React Native responder event system for advanced touch handling.

220

221

```typescript { .api }

222

/**

223

* Hook for React Native responder events (web platform)

224

* @param stateRef - Component state reference

225

* @param props - Component props with responder events

226

*/

227

function useResponderEvents(

228

stateRef: React.MutableRefObject<any>,

229

props?: ResponderEventProps

230

): void;

231

232

interface ResponderEventProps {

233

/** Should respond to move events */

234

onMoveShouldSetResponder?: (event: ResponderEvent) => boolean;

235

/** Should respond to move events (capture phase) */

236

onMoveShouldSetResponderCapture?: (event: ResponderEvent) => boolean;

237

/** Responder granted */

238

onResponderGrant?: (event: ResponderEvent) => void;

239

/** Responder rejected */

240

onResponderReject?: (event: ResponderEvent) => void;

241

/** Responder started */

242

onResponderStart?: (event: ResponderEvent) => void;

243

/** Responder moved */

244

onResponderMove?: (event: ResponderEvent) => void;

245

/** Responder ended */

246

onResponderEnd?: (event: ResponderEvent) => void;

247

/** Responder released */

248

onResponderRelease?: (event: ResponderEvent) => void;

249

/** Responder terminated */

250

onResponderTerminate?: (event: ResponderEvent) => void;

251

/** Responder termination requested */

252

onResponderTerminationRequest?: (event: ResponderEvent) => boolean;

253

/** Should respond to start events */

254

onStartShouldSetResponder?: (event: ResponderEvent) => boolean;

255

/** Should respond to start events (capture phase) */

256

onStartShouldSetResponderCapture?: (event: ResponderEvent) => boolean;

257

/** Should respond to scroll events */

258

onScrollShouldSetResponder?: (event: ResponderEvent) => boolean;

259

/** Should respond to scroll events (capture phase) */

260

onScrollShouldSetResponderCapture?: (event: ResponderEvent) => boolean;

261

/** Should respond to selection change events */

262

onSelectionChangeShouldSetResponder?: (event: ResponderEvent) => boolean;

263

/** Should respond to selection change events (capture phase) */

264

onSelectionChangeShouldSetResponderCapture?: (event: ResponderEvent) => boolean;

265

}

266

267

interface ResponderEvent {

268

nativeEvent: {

269

changedTouches: Touch[];

270

identifier: number;

271

locationX: number;

272

locationY: number;

273

pageX: number;

274

pageY: number;

275

target: any;

276

timestamp: number;

277

touches: Touch[];

278

};

279

}

280

```

281

282

### Platform-Specific Optimizations

283

284

Functions and components for React Native performance optimizations.

285

286

```typescript { .api }

287

/**

288

* Create optimized view for React Native platform

289

* @param children - Child components

290

* @param props - View props

291

* @param baseViews - Base React Native components

292

* @returns Optimized React Native view

293

*/

294

function createOptimizedView(

295

children: React.ReactNode,

296

props: Record<string, any>,

297

baseViews: BaseViews

298

): React.ReactElement;

299

300

/**

301

* Get base React Native components

302

* @returns Object with React Native base components

303

*/

304

function getBaseViews(): BaseViews;

305

306

/**

307

* Add React Native version-specific valid styles

308

*/

309

function addNativeValidStyles(): void;

310

311

interface BaseViews {

312

View: React.ComponentType<any>;

313

Text: React.ComponentType<any>;

314

StyleSheet: any;

315

TextAncestor: React.ComponentType<any> | undefined;

316

Pressable: React.ComponentType<any>;

317

}

318

```

319

320

### Style Injection (Development)

321

322

Style injection utilities for development mode (web platform).

323

324

```typescript { .api }

325

/**

326

* Inject CSS styles dynamically for development mode

327

* @param options - Injection options

328

*/

329

function injectStyles(options: InjectStylesOptions): void;

330

331

interface InjectStylesOptions {

332

/** File path for CSS identification */

333

filePath: string;

334

/** CSS string to inject */

335

css: string;

336

}

337

```

338

339

**Usage Examples:**

340

341

```typescript

342

import { injectStyles } from "@tamagui/core";

343

344

// Development-time style injection

345

if (process.env.NODE_ENV === 'development') {

346

injectStyles({

347

filePath: 'components/Button.tsx',

348

css: `

349

.debug-button {

350

border: 2px solid red !important;

351

}

352

`,

353

});

354

}

355

```

356

357

### React Native Props Support

358

359

Enhanced components with full React Native prop support.

360

361

```typescript { .api }

362

/**

363

* Enhanced View component with React Native props

364

*/

365

declare const View: TamaguiComponent<

366

TamaDefer,

367

TamaguiElement,

368

RNTamaguiViewNonStyleProps,

369

StackStyleBase,

370

{}

371

>;

372

373

/**

374

* Enhanced Text component with React Native text props

375

*/

376

declare const Text: TamaguiComponent<

377

TamaDefer,

378

TamaguiTextElement,

379

RNTamaguiTextNonStyleProps,

380

TextStylePropsBase,

381

{}

382

>;

383

384

interface RNTamaguiViewNonStyleProps extends StackNonStyleProps {

385

// React Native View props

386

/** Accessibility properties */

387

accessible?: boolean;

388

accessibilityActions?: AccessibilityAction[];

389

accessibilityLabel?: string;

390

accessibilityLabelledBy?: string;

391

accessibilityRole?: AccessibilityRole;

392

accessibilityState?: AccessibilityState;

393

accessibilityValue?: AccessibilityValue;

394

accessibilityHint?: string;

395

accessibilityLanguage?: string;

396

397

/** Android-specific props */

398

collapsable?: boolean;

399

focusable?: boolean;

400

401

/** Layout and interaction */

402

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

403

onStartShouldSetResponder?: (event: ResponderEvent) => boolean;

404

onMoveShouldSetResponder?: (event: ResponderEvent) => boolean;

405

onResponderGrant?: (event: ResponderEvent) => void;

406

onResponderMove?: (event: ResponderEvent) => void;

407

onResponderRelease?: (event: ResponderEvent) => void;

408

onResponderTerminate?: (event: ResponderEvent) => void;

409

onResponderTerminationRequest?: (event: ResponderEvent) => boolean;

410

411

/** Pointer events */

412

pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only';

413

414

/** Test IDs */

415

testID?: string;

416

nativeID?: string;

417

418

/** Hit testing */

419

hitSlop?: HitSlop;

420

421

/** Remove clipped subviews (performance) */

422

removeClippedSubviews?: boolean;

423

}

424

425

interface RNTamaguiTextNonStyleProps extends TextNonStyleProps {

426

// React Native Text props

427

/** Text selection */

428

selectable?: boolean;

429

selectionColor?: string;

430

431

/** Text styling */

432

allowFontScaling?: boolean;

433

maxFontSizeMultiplier?: number;

434

minimumFontScale?: number;

435

suppressHighlighting?: boolean;

436

437

/** Text measurement */

438

adjustsFontSizeToFit?: boolean;

439

numberOfLines?: number;

440

ellipsizeMode?: 'head' | 'middle' | 'tail' | 'clip';

441

442

/** Text events */

443

onTextLayout?: (event: TextLayoutEvent) => void;

444

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

445

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

446

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

447

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

448

449

/** Accessibility */

450

accessible?: boolean;

451

accessibilityLabel?: string;

452

accessibilityRole?: AccessibilityRole;

453

accessibilityState?: AccessibilityState;

454

}

455

```

456

457

### Platform Detection

458

459

Constants and utilities for platform-specific behavior.

460

461

```typescript { .api }

462

/** Web platform detection */

463

declare const isWeb: boolean;

464

465

/** Server environment detection */

466

declare const isServer: boolean;

467

468

/** Client environment detection */

469

declare const isClient: boolean;

470

471

/** Android platform detection */

472

declare const isAndroid: boolean;

473

474

/** iOS platform detection */

475

declare const isIos: boolean;

476

477

/** Touch capability detection */

478

declare const isTouchable: boolean;

479

480

/** Web touch capability detection */

481

declare const isWebTouchable: boolean;

482

483

/**

484

* SSR-safe useLayoutEffect hook

485

*/

486

declare const useIsomorphicLayoutEffect: typeof React.useLayoutEffect;

487

```

488

489

**Usage Examples:**

490

491

```typescript

492

import { isWeb, isAndroid, isIos, View, Text } from "@tamagui/core";

493

494

function PlatformSpecificComponent() {

495

return (

496

<View>

497

{isWeb && <Text>Web platform</Text>}

498

{isAndroid && <Text>Android platform</Text>}

499

{isIos && <Text>iOS platform</Text>}

500

</View>

501

);

502

}

503

504

// Platform-specific styling

505

const PlatformView = styled(View, {

506

backgroundColor: '$background',

507

508

...isWeb && {

509

cursor: 'pointer',

510

userSelect: 'none',

511

},

512

513

...isAndroid && {

514

elevation: 4,

515

},

516

517

...isIos && {

518

shadowOpacity: 0.3,

519

shadowRadius: 4,

520

shadowOffset: { width: 0, height: 2 },

521

},

522

});

523

```

524

525

## Types

526

527

```typescript { .api }

528

interface AccessibilityAction {

529

name: string;

530

label?: string;

531

}

532

533

type AccessibilityRole =

534

| 'none'

535

| 'button'

536

| 'link'

537

| 'search'

538

| 'image'

539

| 'keyboardkey'

540

| 'text'

541

| 'adjustable'

542

| 'imagebutton'

543

| 'header'

544

| 'summary'

545

| 'alert'

546

| 'checkbox'

547

| 'combobox'

548

| 'menu'

549

| 'menubar'

550

| 'menuitem'

551

| 'progressbar'

552

| 'radio'

553

| 'radiogroup'

554

| 'scrollbar'

555

| 'spinbutton'

556

| 'switch'

557

| 'tab'

558

| 'tablist'

559

| 'timer'

560

| 'toolbar';

561

562

interface AccessibilityState {

563

disabled?: boolean;

564

selected?: boolean;

565

checked?: boolean | 'mixed';

566

busy?: boolean;

567

expanded?: boolean;

568

}

569

570

interface AccessibilityValue {

571

min?: number;

572

max?: number;

573

now?: number;

574

text?: string;

575

}

576

577

interface TextLayoutEvent {

578

nativeEvent: {

579

lines: TextLayoutLine[];

580

};

581

}

582

583

interface TextLayoutLine {

584

text: string;

585

x: number;

586

y: number;

587

width: number;

588

height: number;

589

descender: number;

590

capHeight: number;

591

baseline: number;

592

xHeight: number;

593

}

594

```