Back to skills
SkillHub ClubBuild MobileFull StackTech WriterMobile

expo-docs

Complete documentation for Expo SDK modules. Read docs before working with Expo libraries and when stuck on problems. New things (you don't know about them) include expo-glass. When user mentiones glass use expo-glass.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
1
Hot score
77
Updated
March 20, 2026
Overall rating
C0.9
Composite score
0.9
Best-practice grade
C62.8

Install command

npx @skill-hub/cli install tfunk1030-vibe-expo-docs

Repository

tfunk1030/vibe

Skill path: .claude/skills/expo-docs

Complete documentation for Expo SDK modules. Read docs before working with Expo libraries and when stuck on problems. New things (you don't know about them) include expo-glass. When user mentiones glass use expo-glass.

Open repository

Best for

Primary workflow: Build Mobile.

Technical facets: Full Stack, Tech Writer, Mobile.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: tfunk1030.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install expo-docs into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/tfunk1030/vibe before adding expo-docs to shared team environments
  • Use expo-docs for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: expo-docs
description: Complete documentation for Expo SDK modules. Read docs before working with Expo libraries and when stuck on problems. New things (you don't know about them) include expo-glass. When user mentiones glass use expo-glass.
---

file: [expo-application.md](expo-application.md)
name: Expo Application
description: A universal library that provides information about the native application's ID, app name, and build version at runtime.

file: [expo-audio.md](expo-audio.md)
description: A library that provides an API to implement audio playback and recording in apps.

file: [expo-av.md](expo-av.md)
description: A library that provides an API to implement audio playback and recording in apps.

file: [barometer.md](barometer.md)
A library that provides access to device's barometer sensor.

file: [battery.md](battery.md)
description: A library that provides battery information for the physical device, as well as corresponding event listeners.

file: [expo-blob.md](expo-blob.md)
description: A web standards-compliant Blob implementation for React Native.

file: [blur-view.md](blur-view.md)
description: A React component that blurs everything underneath the view.

file: [brightness.md](brightness.md)  
description: A library that provides access to an API for getting and setting the screen brightness.

file: [calendar.md](calendar.md)
description: A library that provides an API for interacting with the device's system calendars, events, reminders, and associated records.

file: [camera.md](camera.md)
A React component that renders a preview for the device's front or back camera.

file: [cellular.md](cellular.md)
An API that provides information about the user's cellular service provider.

file: [clipboard.md](clipboard.md)
A universal library that allows getting and setting Clipboard content

file: [contacts.md](contacts.md)
A library that provides access to the phone's system contacts.

file: [crypto.md](crypto.md)
A universal library for crypto operations.

file: [device.md](device.md)
A universal library provides access to system information about the physical device.

file: [device-motion.md](device-motion.md)
DeviceMotion from expo-sensors provides access to the device motion and orientation sensors.

file: [document-picker.md](document-picker.md)
A library that provides access to the system's UI for selecting documents from the available providers on the user's device.

file: [file-system.md](file-system.md)
expo-file-system provides access to files and directories stored on a device or bundled as assets into the native project.

file: [glass-effect.md](glass-effect.md)
React components that render native iOS liquid glass effect using UIVisualEffectView. Supports customizable glass styles and tint color.

file: [gl-view.md](gl-view.md)  
A library that provides GLView that acts as an OpenGL ES render target and provides GLContext.

file: [gyroscope.md](gyroscope.md)
A library that provides access to the device's gyroscope sensor.

file: [image-picker.md](image-picker.md)
A library that provides access to the system's UI for selecting images and videos from the phone's library or taking a photo with the camera.

file: [keep-awake.md](keep-awake.md)
A React component that prevents the screen from sleeping when rendered.

file: [light-sensor.md](light-sensor.md)
LightSensor from expo-sensors provides access to the device's light sensor to respond to illuminance changes.

file: [linear-gradient.md](linear-gradient.md)
expo-linear-gradient provides a native React view that transitions between multiple colors in a linear direction.

file: [live-photo.md](live-photo.md)
A library that allows displaying Live Photos on iOS.

file: [location.md](location.md)
A library that provides access to reading geolocation information, polling current location or subscribing location update events from the device.

file: [mail-composer.md](mail-composer.md)
A library that provides functionality to compose and send emails with the system's specific UI.

file: [maps.md](maps.md)
A library that provides access to Google Maps on Android and Apple Maps on iOS.

file: [mesh-gradient.md](mesh-gradient.md)
A module that exposes MeshGradient view from SwiftUI to React Native.

file: [pedometer.md](pedometer.md)
A library that provides access to the device's pedometer sensor.

file: [print.md](print.md)  
expo-print provides an API for Android and iOS (AirPrint) printing functionality.

file: [router.md](router.md)  
A file-based routing library for React Native and web applications.

file: [router-native-tabs.md](router-native-tabs.md)  
An Expo Router submodule that provides native tabs layout. You can use to create native tabs with expo glass.

file: [screen-capture.md](screen-capture.md)  
A library that allows you to protect screens in your app from being captured or recorded.

file: [screen-orientation.md](screen-orientation.md)  
A universal library for managing a device's screen orientation.

file: [secure-store.md](secure-store.md)  
A library that provides a way to encrypt and securely store key-value pairs locally on the device.

file: [sharing.md](sharing.md)  
A library that provides implementing sharing files.

file: [sms.md](sms.md)  
A library that provides access to the system's UI/app for sending SMS messages.

file: [store-review.md](store-review.md)  
A library that provides access to native APIs for in-app reviews.

file: [react-native-reanimated.md](react-native-reanimated.md)
description: A powerful animation library for React Native that provides smooth, performant animations running on the UI thread.

file: [react-native-gesture-handler.md](react-native-gesture-handler.md)
description: A declarative API exposing platform native touch and gesture system to React Native.

file: [react-native-skia.md](react-native-skia.md)
description: High-performance 2D graphics library for React Native using Skia, enabling complex drawings, shaders, and image processing.

---

## Referenced Files

> The following files are referenced in this skill and included for context.

### expo-application.md

```markdown
# Application

_A universal library that provides information about the native application's ID, app name, and build version at runtime._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/application/)

```typescript
import * as Application from 'expo-application';
```

### Constants

- `applicationId` - Bundle ID (iOS) or application ID (Android), `null` on web
- `applicationName` - Human-readable app name displayed on home screen
- `nativeApplicationVersion` - Version string like "1.0.0" for app stores
- `nativeBuildVersion` - Internal build number like "114"

### Methods

- `getInstallationTimeAsync()` - Returns `Date` when app was installed
- `getAndroidId()` - Gets unique device hex string (Android only)
- `getIosApplicationReleaseTypeAsync()` - Returns release type: `UNKNOWN`, `SIMULATOR`, `ENTERPRISE`, `DEVELOPMENT`, `AD_HOC`, `APP_STORE` (iOS only)
- `getInstallReferrerAsync()` - Gets referrer URL from Play Store (Android only)
- `getIosIdForVendorAsync()` - Gets IDFV value (iOS only)

```

### expo-audio.md

```markdown
# Audio

_Modern audio playback and recording API for React Native._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/audio/)

```typescript
import { useAudioPlayer, useAudioPlayerStatus, useAudioRecorder } from 'expo-audio';
```

### Playback with Hooks

```typescript
const player = useAudioPlayer(require('./audio.mp3'));
const status = useAudioPlayerStatus(player);

player.play();
player.pause();
player.seekTo(30);
player.setVolume(0.5);
player.setRate(1.5);
```

Status provides `playing`, `duration`, `currentTime`, and `isBuffering`.

### Recording

```typescript
const recorder = useAudioRecorder(RecordingOptions.HIGH_QUALITY);

await recorder.prepareToRecordAsync();
recorder.record();
await recorder.stop();
const uri = recorder.uri;
```

### Audio Mode

```typescript
import { setAudioModeAsync } from 'expo-audio';

await setAudioModeAsync({
  playsInSilentMode: true,
  shouldRouteThroughEarpiece: false,
});
```

```

### expo-av.md

```markdown
# AV (Deprecated)

_Legacy audio/video playback and recording. Use `expo-audio` and `expo-video` instead._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/av/)

```typescript
import { Audio, Video } from 'expo-av';
```

### Audio Playback

```typescript
const { sound } = await Audio.Sound.createAsync(require('./audio.mp3'), { shouldPlay: true });
await sound.playAsync();
await sound.pauseAsync();
await sound.setPositionAsync(30000);
await sound.unloadAsync();
```

### Recording

```typescript
await Audio.setAudioModeAsync({ allowsRecordingIOS: true, playsInSilentModeIOS: true });
const recording = new Audio.Recording();
await recording.prepareToRecordAsync(Audio.RecordingOptionsPresets.HIGH_QUALITY);
await recording.startAsync();
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
```

### Video Component

```typescript
<Video
  source={{ uri: 'https://example.com/video.mp4' }}
  style={{ width: 300, height: 200 }}
  useNativeControls
  resizeMode={ResizeMode.CONTAIN}
  shouldPlay
  isLooping
/>
```

```

### barometer.md

```markdown
# Barometer

_Access device barometer sensor for atmospheric pressure readings._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/barometer/)

```typescript
import { Barometer } from 'expo-sensors';
```

### Usage

```typescript
const available = await Barometer.isAvailableAsync();

const subscription = Barometer.addListener(({ pressure, relativeAltitude }) => {
  console.log(pressure, 'hPa');
  console.log(relativeAltitude, 'm'); // iOS only
});

Barometer.setUpdateInterval(1000);
subscription.remove();
```

Returns `pressure` in hectopascals (hPa) and `relativeAltitude` in meters (iOS only).

```

### battery.md

```markdown
# Battery

_Get device battery information and subscribe to changes._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/battery/)

```typescript
import * as Battery from 'expo-battery';
```

### Methods

- `getBatteryLevelAsync()` - Returns 0-1 battery level
- `getBatteryStateAsync()` - Returns `UNKNOWN`, `UNPLUGGED`, `CHARGING`, or `FULL`
- `isLowPowerModeEnabledAsync()` - Check if low power mode is on
- `isAvailableAsync()` - Check if battery monitoring available

### Event Listeners

```typescript
Battery.addBatteryLevelListener(({ batteryLevel }) => {});
Battery.addBatteryStateListener(({ batteryState }) => {});
Battery.addLowPowerModeListener(({ lowPowerMode }) => {});
```

Call `.remove()` on subscription to clean up.

```

### expo-blob.md

```markdown
# Blob

_Web standards-compliant Blob implementation for React Native._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/blob/)

```typescript
import { Blob } from 'expo-blob';
```

### Creating Blobs

```typescript
const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
const bufferBlob = new Blob([arrayBuffer], { type: 'application/octet-stream' });
const combined = new Blob([blob1, blob2]);
```

### Reading Blobs

```typescript
const text = await blob.text();
const arrayBuffer = await blob.arrayBuffer();
```

### Properties

- `blob.size` - Size in bytes
- `blob.type` - MIME type
- `blob.slice(start, end, type)` - Create a slice

```

### blur-view.md

```markdown
# BlurView

_A React component that blurs everything underneath it._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/blur-view/)

```typescript
import { BlurView } from 'expo-blur';
```

### Usage

```typescript
<BlurView intensity={50} tint="light" style={StyleSheet.absoluteFill}>
  <Text>Content over blur</Text>
</BlurView>
```

### Props

- `intensity` - Blur intensity 0-100 (default: 50)
- `tint` - `"light"` | `"dark"` | `"default"` | `"extraLight"` | `"regular"` | `"prominent"`
- `blurReductionFactor` - Performance optimization (default: 4)
- `experimentalBlurMethod` - Android: `"none"` | `"dimezisBlurView"`

```

### brightness.md

```markdown
# Brightness

_Control screen brightness programmatically._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/brightness/)

```typescript
import * as Brightness from 'expo-brightness';
```

### Methods

- `requestPermissionsAsync()` - Request permission (iOS needs it)
- `getBrightnessAsync()` - Get current brightness (0-1)
- `setBrightnessAsync(value)` - Set brightness (0-1)
- `getSystemBrightnessAsync()` - Get system brightness
- `setSystemBrightnessAsync(value)` - Set system brightness (Android only)
- `getSystemBrightnessModeAsync()` - Get `AUTOMATIC` or `MANUAL` mode (Android)
- `setSystemBrightnessModeAsync(mode)` - Set brightness mode (Android)

```

### calendar.md

```markdown
# Calendar

_Interact with device calendars, events, and reminders._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/calendar/)

```typescript
import * as Calendar from 'expo-calendar';
```

### Permissions

```typescript
await Calendar.requestCalendarPermissionsAsync();
await Calendar.requestRemindersPermissionsAsync(); // iOS only
```

### Calendars

```typescript
const calendars = await Calendar.getCalendarsAsync(Calendar.EntityTypes.EVENT);
const calendarId = await Calendar.createCalendarAsync({ title: 'My Calendar', ... });
```

### Events

```typescript
const events = await Calendar.getEventsAsync([calendarId], startDate, endDate);

const eventId = await Calendar.createEventAsync(calendarId, {
  title: 'Meeting',
  startDate: new Date(),
  endDate: new Date(),
  location: 'Office',
  alarms: [{ relativeOffset: -30 }],
});

await Calendar.updateEventAsync(eventId, { title: 'Updated' });
await Calendar.deleteEventAsync(eventId);
```

### Reminders (iOS only)

```typescript
const reminders = await Calendar.getRemindersAsync([calendarId], null, startDate, endDate);
await Calendar.createReminderAsync(calendarId, { title: 'Task', dueDate: new Date() });
```

```

### camera.md

```markdown
# Camera

_Camera preview and photo/video capture._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/camera/)

```typescript
import { CameraView, useCameraPermissions } from 'expo-camera';
```

### Permissions

```typescript
const [permission, requestPermission] = useCameraPermissions();
if (!permission?.granted) await requestPermission();
```

### Basic Camera

```typescript
const cameraRef = useRef<CameraView>(null);

<CameraView ref={cameraRef} style={{ flex: 1 }} facing="back">
  <Button onPress={async () => {
    const photo = await cameraRef.current?.takePictureAsync({ quality: 0.8, base64: true });
  }} />
</CameraView>
```

### Video Recording

```typescript
const video = await cameraRef.current?.recordAsync({ maxDuration: 60, quality: '1080p' });
cameraRef.current?.stopRecording();
```

### Barcode Scanning

```typescript
<CameraView
  barcodeScannerSettings={{ barcodeTypes: ['qr', 'ean13'] }}
  onBarcodeScanned={({ type, data }) => console.log(type, data)}
/>
```

```

### cellular.md

```markdown
# Cellular

_Get information about the user's cellular service provider._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/cellular/)

```typescript
import * as Cellular from 'expo-cellular';
```

### Constants

- `carrier` - Carrier name like "Verizon", "AT&T"
- `isoCountryCode` - ISO country code like "us", "gb"
- `mobileCountryCode` - MCC like "310" for US
- `mobileNetworkCode` - Carrier-specific MNC
- `allowsVoip` - Whether VoIP is allowed

### Methods

- `getCellularGenerationAsync()` - Returns generation: `UNKNOWN` (0), `CELLULAR_2G` (1), `CELLULAR_3G` (2), `CELLULAR_4G` (3), `CELLULAR_5G` (4)

```

### clipboard.md

```markdown
# Clipboard

_Read and write to the system clipboard._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/clipboard/)

```typescript
import * as Clipboard from 'expo-clipboard';
```

### String

```typescript
await Clipboard.setStringAsync('Hello');
const text = await Clipboard.getStringAsync();
const hasString = await Clipboard.hasStringAsync();
```

### Image

```typescript
await Clipboard.setImageAsync(base64String);
const image = await Clipboard.getImageAsync({ format: 'png' });
const hasImage = await Clipboard.hasImageAsync();
```

### URL

```typescript
await Clipboard.setUrlAsync('https://expo.dev');
const url = await Clipboard.getUrlAsync();
const hasUrl = await Clipboard.hasUrlAsync();
```

### Listener

```typescript
const subscription = Clipboard.addClipboardListener(({ contentTypes }) => {});
subscription.remove();
```

```

### contacts.md

```markdown
# Contacts

_Access and manage device contacts._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/contacts/)

```typescript
import * as Contacts from 'expo-contacts';
```

### Permissions

```typescript
const { status } = await Contacts.requestPermissionsAsync();
```

### Get Contacts

```typescript
const { data } = await Contacts.getContactsAsync({
  fields: [Contacts.Fields.Name, Contacts.Fields.PhoneNumbers, Contacts.Fields.Emails],
  pageSize: 20,
  sort: Contacts.SortTypes.FirstName,
});

const contact = await Contacts.getContactByIdAsync(id, [Contacts.Fields.Name]);
```

### Manage Contacts

```typescript
const id = await Contacts.addContactAsync({ firstName: 'John', phoneNumbers: [{ number: '555-1234' }] });
await Contacts.updateContactAsync({ id, firstName: 'Jane' });
await Contacts.removeContactAsync(id);
```

### Present Form

```typescript
await Contacts.presentFormAsync(contactId);
await Contacts.presentFormAsync(null, { firstName: 'Pre-filled' });
```

```

### crypto.md

```markdown
# Crypto

_Cryptographic operations including random values and hashing._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/crypto/)

```typescript
import * as Crypto from 'expo-crypto';
```

### Random Values

```typescript
const randomBytes = await Crypto.getRandomBytesAsync(16);
const uuid = Crypto.randomUUID();
```

### Hashing

```typescript
const hash = await Crypto.digestStringAsync(
  Crypto.CryptoDigestAlgorithm.SHA256,
  'Hello, World!'
);
```

Algorithms: `MD5`, `SHA1`, `SHA256`, `SHA384`, `SHA512`

Encodings: `HEX` (default), `BASE64`

```typescript
const base64Hash = await Crypto.digestStringAsync(
  Crypto.CryptoDigestAlgorithm.SHA256,
  'data',
  { encoding: Crypto.CryptoEncoding.BASE64 }
);
```

```

### device.md

```markdown
# Device

_Get system information about the physical device._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/device/)

```typescript
import * as Device from 'expo-device';
```

### Constants

- `brand` - "Apple", "Samsung", "Google"
- `modelName` - "iPhone 14 Pro", "Pixel 7"
- `modelId` - Device model code
- `osName` - "iOS", "Android", "iPadOS"
- `osVersion` - "17.0", "14"
- `deviceName` - User-set name like "John's iPhone"
- `deviceType` - `PHONE` (1), `TABLET` (2), `DESKTOP` (3), `TV` (4)
- `totalMemory` - Total RAM in bytes
- `isDevice` - `true` on physical device, `false` on simulator

### Methods

- `getDeviceTypeAsync()` - Async getter for device type
- `getUptimeAsync()` - Device uptime in milliseconds
- `getMaxMemoryAsync()` - Max memory (Android)

```

### device-motion.md

```markdown
# DeviceMotion

_Access device motion and orientation sensors (accelerometer, gyroscope, magnetometer combined)._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/devicemotion/)

```typescript
import { DeviceMotion } from 'expo-sensors';
```

### Usage

```typescript
const available = await DeviceMotion.isAvailableAsync();

const subscription = DeviceMotion.addListener((data) => {
  data.acceleration;          // { x, y, z } in m/s²
  data.accelerationIncludingGravity;
  data.rotation;              // { alpha, beta, gamma } in degrees
  data.rotationRate;          // { alpha, beta, gamma } in deg/s
  data.orientation;           // Device orientation (0, 90, 180, 270)
});

DeviceMotion.setUpdateInterval(100);
subscription.remove();
```

Rotation: `alpha` is z-axis (0-360°), `beta` is x-axis (-180 to 180°), `gamma` is y-axis (-90 to 90°).

```

### document-picker.md

```markdown
# DocumentPicker

_Select documents from device storage or cloud providers._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/document-picker/)

```typescript
import * as DocumentPicker from 'expo-document-picker';
```

### Pick Documents

```typescript
const result = await DocumentPicker.getDocumentAsync({
  type: '*/*',                    // MIME type filter
  multiple: true,                 // Allow multiple selection
  copyToCacheDirectory: true,     // Copy to app cache
});

if (!result.canceled) {
  result.assets.forEach((file) => {
    file.uri;      // File URI
    file.name;     // File name
    file.size;     // Size in bytes
    file.mimeType; // MIME type
  });
}
```

Type filters: `'*/*'`, `'application/pdf'`, `'image/*'`, or array `['application/pdf', 'text/plain']`

```

### file-system.md

```markdown
# FileSystem

_Access files and directories on the device._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/filesystem/)

```typescript
import * as FileSystem from 'expo-file-system';
```

### Directories

- `FileSystem.documentDirectory` - Persistent storage
- `FileSystem.cacheDirectory` - Cache (can be cleared)
- `FileSystem.bundleDirectory` - Read-only app bundle (iOS)

### Read/Write

```typescript
const content = await FileSystem.readAsStringAsync(uri);
const base64 = await FileSystem.readAsStringAsync(uri, { encoding: FileSystem.EncodingType.Base64 });

await FileSystem.writeAsStringAsync(uri, 'content');
await FileSystem.writeAsStringAsync(uri, base64, { encoding: FileSystem.EncodingType.Base64 });
```

### File Operations

```typescript
const info = await FileSystem.getInfoAsync(uri);  // { exists, size, isDirectory, uri }
await FileSystem.makeDirectoryAsync(uri, { intermediates: true });
const files = await FileSystem.readDirectoryAsync(uri);
await FileSystem.copyAsync({ from, to });
await FileSystem.moveAsync({ from, to });
await FileSystem.deleteAsync(uri, { idempotent: true });
```

### Download/Upload

```typescript
const { uri } = await FileSystem.downloadAsync(url, destUri);
await FileSystem.uploadAsync(url, fileUri, { uploadType: FileSystem.FileSystemUploadType.MULTIPART });
```

```

### glass-effect.md

```markdown
# Glass Effect

_Native iOS liquid glass effect components using UIVisualEffectView. iOS 26+ feature._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/glass-effect/)

```typescript
import { GlassView } from 'expo-glass-effect';
```

### Usage

```typescript
<GlassView glassStyle={GlassStyle.regular} tintColor="#007AFF" style={styles.card}>
  <Text>Content with glass effect</Text>
</GlassView>
```

### Glass Styles

- `GlassStyle.regular` - Default glass effect
- `GlassStyle.thin` - Lighter glass
- `GlassStyle.thick` - More prominent glass
- `GlassStyle.chrome` - Metallic chrome effect
- `GlassStyle.adaptive` - Adapts to content

### Native Bottom Tabs with Glass Effect

For the liquid glass effect on bottom tab bars, use `@bottom-tabs/react-navigation` which provides native tab components. It should already be installed.

[React Native Bottom Tabs Docs](https://incubator.callstack.com/react-native-bottom-tabs/docs/guides/usage-with-expo-router)


**Create layout adapter** in `src/components/bottom-tabs.tsx`:

```typescript
import { withLayoutContext } from 'expo-router';
import {
  createNativeBottomTabNavigator,
  NativeBottomTabNavigationOptions,
  NativeBottomTabNavigationEventMap,
} from '@bottom-tabs/react-navigation';
import { ParamListBase, TabNavigationState } from '@react-navigation/native';

const BottomTabNavigator = createNativeBottomTabNavigator().Navigator;

export const Tabs = withLayoutContext<
  NativeBottomTabNavigationOptions,
  typeof BottomTabNavigator,
  TabNavigationState<ParamListBase>,
  NativeBottomTabNavigationEventMap
>(BottomTabNavigator);
```

**Use in tab layout** `src/app/(tabs)/_layout.tsx`:

```typescript
import { Tabs } from '@/components/bottom-tabs';

export default function TabLayout() {
  return (
    <Tabs>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: () => ({ sfSymbol: 'house' }),
        }}
      />
      <Tabs.Screen
        name="explore"
        options={{
          title: 'Explore',
          tabBarIcon: () => ({ sfSymbol: 'person' }),
        }}
      />
    </Tabs>
  );
}
```

### Platform Behavior

- **iOS 26+**: Full liquid glass effect
- **iOS < 26**: Falls back to blur effect
- **Android**: Falls back to semi-transparent background

```

### gl-view.md

```markdown
# GLView

_OpenGL ES render target for WebGL-style graphics._

[Expo Docs](https://docs.expo.dev/versions/latest/sdk/gl-view/)

```typescript
import { GLView } from 'expo-gl';
```

### Basic Usage

```typescript
<GLView
  style={{ flex: 1 }}
  onContextCreate={(gl) => {
    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.endFrameEXP();  // Required to flush
  }}
/>
```

### Animation Loop

```typescript
const render = () => {
  // Draw frame
  gl.endFrameEXP();
  requestAnimationFrame(render);
};
```

### Snapshot

```typescript
const result = await glViewRef.current?.takeSnapshotAsync({
  format: 'png',
  result: 'file',  // 'file' | 'base64' | 'data-uri'
});
```

Works with Three.js via `expo-three` package.

```

expo-docs | SkillHub