Skip to main content

Overview

The HapticTab component is a wrapper around React Navigation’s PlatformPressable that adds haptic feedback when pressing tab buttons on iOS devices. It provides subtle tactile feedback to enhance the user experience when switching between tabs.

Import

import { HapticTab } from '@/components/haptic-tab';

Props

props
BottomTabBarButtonProps
required
All props from React Navigation’s BottomTabBarButtonProps are passed through to the underlying PlatformPressable component.

Usage

In Tab Navigator

The HapticTab component is used as the tabBarButton in the tab navigator configuration. From src/app/(tabs)/_layout.tsx:
import { Tabs } from 'expo-router';
import { HapticTab } from '@/components/haptic-tab';
import { IconSymbol } from '@/components/ui/icon-symbol';
import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';

export default function TabLayout() {
  const colorScheme = useColorScheme();

  return (
    <Tabs
      screenOptions={{
        tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
        headerShown: false,
        tabBarButton: HapticTab,
      }}>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
        }}
      />
      <Tabs.Screen
        name="explore"
        options={{
          title: 'Explore',
          tabBarIcon: ({ color }) => (
            <IconSymbol size={28} name="paperplane.fill" color={color} />
          ),
        }}
      />
    </Tabs>
  );
}

Platform Behavior

iOS

On iOS devices, the component triggers a light haptic feedback using Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light) when the user presses down on a tab button. This provides subtle tactile feedback that aligns with iOS design patterns.

Android and Web

On Android and web platforms, the component behaves like a standard pressable button without haptic feedback, as these platforms don’t have the same haptic feedback APIs or conventions.

Implementation Details

The component wraps the press event and adds haptic feedback before calling the original onPressIn handler:
import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs';
import { PlatformPressable } from '@react-navigation/elements';
import * as Haptics from 'expo-haptics';

export function HapticTab(props: BottomTabBarButtonProps) {
  return (
    <PlatformPressable
      {...props}
      onPressIn={(ev) => {
        if (process.env.EXPO_OS === 'ios') {
          Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
        }
        props.onPressIn?.(ev);
      }}
    />
  );
}

Haptic Feedback Styles

The component uses ImpactFeedbackStyle.Light, which is the most subtle haptic feedback option. Expo Haptics provides three impact styles:
  • Light: Subtle feedback for light interactions (used in HapticTab)
  • Medium: Moderate feedback for standard interactions
  • Heavy: Strong feedback for significant interactions

Build docs developers (and LLMs) love