# useBottomTabOverflow

> A hook that returns the appropriate bottom tab bar height for iOS devices to handle safe area insets and overflow scenarios.

**BNA UI** — a React Native / Expo component library.
These components render through `react-native`, not the DOM: there are no HTML
elements, no Tailwind classes and no Radix primitives. Source is copied into your
project and imported through `@/components/ui/*`, `@/components/charts/*`,
`@/hooks/*` and `@/theme/*`. Colours come from the `useColor` hook rather than
hardcoded hex; sizing tokens (`HEIGHT`, `FONT_SIZE`, `BORDER_RADIUS`, `CORNERS`)
come from `@/theme/globals`.

- Docs: https://ui.ahmedbna.com/docs/hooks/useBottomTabOverflow
- Markdown: https://ui.ahmedbna.com/docs/hooks/useBottomTabOverflow.md
- Structured JSON (props, usage, source, examples): https://ui.ahmedbna.com/r/ai/useBottomTabOverflow.json
- Install payload (source plus every file it imports): https://ui.ahmedbna.com/r/useBottomTabOverflow.json
- Install: `npx bna-ui add useBottomTabOverflow`
- npm dependencies: `expo-router`

---

## Installation

### CLI

```bash
npx bna-ui add useBottomTabOverflow
```

### Manual

**1.** This hook reads from expo-router's tab context, so no additional
dependencies are needed beyond expo-router itself.

**2.** Copy and paste the following code into your project.

```ts
// hooks/useBottomTabOverflow.ts
import { BottomTabBarHeightContext } from 'expo-router/js-tabs';
import { useContext } from 'react';
import { Platform } from 'react-native';

// Reads the tab bar height off its context rather than calling
// `useBottomTabBarHeight()`, for two reasons: the hook must run
// unconditionally to satisfy the rules of hooks (the React Compiler is strict
// about this), and the context returns `undefined` outside a tab navigator
// where the hook would throw. Only iOS needs the inset — Android's tab bar is
// opaque, so content is never underneath it.
export function useBottomTabOverflow() {
  const tabBarHeight = useContext(BottomTabBarHeightContext);
  return Platform.OS === 'ios' ? (tabBarHeight ?? 0) : 0;
}
```

**3.** Update the import paths to match your project setup.

## Usage

```tsx
import { useBottomTabOverflow } from '@/hooks/useBottomTabOverflow';
```

```tsx
export function MyScreen() {
  const tabOverflow = useBottomTabOverflow();

  return (
    <View style={{ paddingBottom: tabOverflow }}>{/* Your content */}</View>
  );
}
```

## API Reference

### useBottomTabOverflow

Returns the appropriate bottom tab bar height for handling overflow scenarios.

#### Returns

| Type     | Description                                                                                                      |
| -------- | ---------------------------------------------------------------------------------------------------------------- |
| `number` | The bottom tab bar height on iOS, or 0 on Android. Reads `BottomTabBarHeightContext` from `expo-router/js-tabs`. |

## Platform Behavior

### iOS

- Returns the tab bar height from `expo-router`'s `BottomTabBarHeightContext`, falling back to `0` outside a tab navigator
- Updates dynamically if the tab bar height changes

### Android

- Returns 0 as Android handles bottom tabs differently
- Android's bottom navigation typically doesn't overlap with content

## Use Cases

This hook is particularly useful when you need to:

- Prevent content from being hidden behind bottom tab bars on iOS
- Add appropriate padding to scrollable content
- Handle safe area insets in screens with bottom navigation
- Position floating action buttons or other fixed elements above the tab bar
- Ensure modal content doesn't overlap with navigation elements

## Best Practices

### Performance

- The hook is lightweight (a single `useContext` read) and safe to use in multiple components
- Consider memoizing dependent calculations to avoid unnecessary re-renders

### Usage Patterns

- Use this hook in screens that have scrollable content or fixed positioned elements
- Combine with `useSafeAreaInsets` for complete safe area handling
- Consider using it in modal screens that might overlap with tab bars

### Example: Complete Safe Area Handling

```tsx
import { useBottomTabOverflow } from '@/hooks/useBottomTabOverflow';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

export function CompleteScreen() {
  const tabOverflow = useBottomTabOverflow();
  const insets = useSafeAreaInsets();

  return (
    <ScrollView
      style={{ flex: 1 }}
      contentContainerStyle={{
        paddingTop: insets.top,
        paddingBottom: Math.max(insets.bottom, tabOverflow),
        paddingHorizontal: 16,
      }}
    >
      {/* Your content */}
    </ScrollView>
  );
}
```

### Example: Fixed Position Element

```tsx
import { useBottomTabOverflow } from '@/hooks/useBottomTabOverflow';

export function ScreenWithFAB() {
  const tabOverflow = useBottomTabOverflow();

  return (
    <View style={{ flex: 1 }}>
      {/* Main content */}
      <View style={{ flex: 1 }}>{/* Content */}</View>

      {/* Fixed position FAB */}
      <TouchableOpacity
        style={{
          position: 'absolute',
          bottom: 16 + tabOverflow,
          right: 16,
          width: 56,
          height: 56,
          borderRadius: 28,
          backgroundColor: '#007AFF',
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        <Text style={{ color: 'white', fontSize: 24 }}>+</Text>
      </TouchableOpacity>
    </View>
  );
}
```

## Dependencies

- `expo-router` - Provides `BottomTabBarHeightContext` via `expo-router/js-tabs`
- `react-native` - Required for Platform detection

## Accessibility

The hook helps maintain proper accessibility by:

- Ensuring content is not hidden behind navigation elements
- Maintaining proper touch targets for interactive elements
- Supporting screen readers by keeping content visible and accessible
