UI Components for React Navigation providing headers, buttons, and layout components with cross-platform support
—
React hooks and context providers for accessing navigation state, dimensions, header information, and frame size tracking.
Hook to access the current header height from the HeaderHeightContext, useful for positioning content relative to the header.
/**
* Hook to access current header height from context
* @returns Current header height in pixels
* @throws Error if used outside HeaderHeightContext provider
*/
function useHeaderHeight(): number;Usage Examples:
import { useHeaderHeight } from "@react-navigation/elements";
// Basic usage
function ContentWithHeaderOffset() {
const headerHeight = useHeaderHeight();
return (
<ScrollView
style={{ flex: 1 }}
contentInset={{ top: headerHeight }}
>
<Text>Content offset by header height</Text>
</ScrollView>
);
}
// Positioning floating elements
function FloatingActionButton() {
const headerHeight = useHeaderHeight();
return (
<View
style={{
position: 'absolute',
top: headerHeight + 20,
right: 20,
width: 56,
height: 56,
borderRadius: 28,
backgroundColor: '#007AFF'
}}
>
<Icon name="plus" color="white" />
</View>
);
}
// Conditional layout based on header height
function AdaptiveLayout() {
const headerHeight = useHeaderHeight();
const isCompactHeader = headerHeight < 100;
return (
<View style={{ flex: 1, paddingTop: headerHeight }}>
{isCompactHeader ? (
<CompactLayout />
) : (
<ExpandedLayout />
)}
</View>
);
}Hook for tracking frame size changes with optional throttling, providing current dimensions and selector-based updates.
/**
* Hook for tracking frame size with optional throttling
* @param selector - Function to select specific values from frame
* @param throttle - Whether to throttle frame updates (default: false)
* @returns Selected value from current frame dimensions
*/
function useFrameSize<T>(
selector: (frame: Frame) => T,
throttle?: boolean
): T;
interface Frame {
width: number;
height: number;
}Usage Examples:
import { useFrameSize } from "@react-navigation/elements";
// Get current frame width
function ResponsiveComponent() {
const width = useFrameSize(frame => frame.width);
return (
<View style={{
flexDirection: width > 768 ? 'row' : 'column'
}}>
<Text>Responsive layout based on width: {width}px</Text>
</View>
);
}
// Get both width and height
function FullFrameInfo() {
const dimensions = useFrameSize(frame => ({
width: frame.width,
height: frame.height,
aspectRatio: frame.width / frame.height
}));
return (
<View>
<Text>Width: {dimensions.width}px</Text>
<Text>Height: {dimensions.height}px</Text>
<Text>Aspect Ratio: {dimensions.aspectRatio.toFixed(2)}</Text>
</View>
);
}
// Throttled updates for performance
function ThrottledFrameSize() {
const width = useFrameSize(
frame => frame.width,
true // Throttle updates
);
return (
<Text>
Throttled width updates: {width}px
</Text>
);
}
// Conditional rendering based on frame size
function AdaptiveContent() {
const isLandscape = useFrameSize(
frame => frame.width > frame.height
);
return (
<View style={{ flex: 1 }}>
{isLandscape ? (
<LandscapeLayout />
) : (
<PortraitLayout />
)}
</View>
);
}Provider component that enables frame size tracking for useFrameSize hook by monitoring and providing device dimensions.
/**
* Provider for frame size tracking context
* @param initialFrame - Initial frame dimensions
* @param children - Child components that will have access to frame size
* @param style - Optional style for the provider container
*/
function FrameSizeProvider(props: {
initialFrame: Frame;
children: React.ReactNode;
style?: StyleProp<ViewStyle>;
}): React.ReactElement;
interface Frame {
width: number;
height: number;
}Usage Examples:
import { FrameSizeProvider, useFrameSize } from "@react-navigation/elements";
// Basic provider setup
function App() {
const initialFrame = { width: 375, height: 812 }; // iPhone dimensions
return (
<FrameSizeProvider initialFrame={initialFrame}>
<ResponsiveApp />
</FrameSizeProvider>
);
}
// Nested providers automatically avoid double-wrapping
function NestedProviders({ children }) {
const frame1 = { width: 768, height: 1024 };
const frame2 = { width: 1024, height: 768 };
return (
<FrameSizeProvider initialFrame={frame1}>
<FrameSizeProvider initialFrame={frame2}>
{children} {/* Only one provider is active */}
</FrameSizeProvider>
</FrameSizeProvider>
);
}
// Using with safe area frame
import { useSafeAreaFrame } from 'react-native-safe-area-context';
function SafeAreaFrameProvider({ children }) {
const safeAreaFrame = useSafeAreaFrame();
return (
<FrameSizeProvider initialFrame={safeAreaFrame}>
{children}
</FrameSizeProvider>
);
}Context providing back button state and navigation information for header components.
/**
* Context for back button state and navigation info
* @type React context providing back button configuration or undefined
*/
const HeaderBackContext: React.Context<{
/** Back button title (usually previous screen title) */
title: string | undefined;
/** Back button href for web navigation */
href: string | undefined;
} | undefined>;Usage Examples:
import { HeaderBackContext } from "@react-navigation/elements";
import { useContext } from "react";
// Accessing back context
function CustomHeaderComponent() {
const backContext = useContext(HeaderBackContext);
return (
<View>
{backContext && (
<Text>Back to: {backContext.title || 'Previous Screen'}</Text>
)}
</View>
);
}
// Providing back context
<HeaderBackContext.Provider value={{ title: "Settings", href: undefined }}>
<HeaderContent />
</HeaderBackContext.Provider>Context providing the current header height for layout calculations and positioning.
/**
* Context for current header height
* @type React context providing header height in pixels or undefined
*/
const HeaderHeightContext: React.Context<number | undefined>;Usage Examples:
import { HeaderHeightContext } from "@react-navigation/elements";
import { useContext } from "react";
// Manual context access (prefer useHeaderHeight hook)
function ManualHeaderHeight() {
const headerHeight = useContext(HeaderHeightContext);
return (
<View style={{ paddingTop: headerHeight || 0 }}>
<Text>Content with header padding</Text>
</View>
);
}
// Providing header height context
<HeaderHeightContext.Provider value={88}>
<ScreenContent />
</HeaderHeightContext.Provider>Context indicating whether the header is currently shown, useful for layout adjustments.
/**
* Context for header visibility state
* @type React context providing boolean indicating if header is shown
*/
const HeaderShownContext: React.Context<boolean>;Usage Examples:
import { HeaderShownContext } from "@react-navigation/elements";
import { useContext } from "react";
// Accessing header shown state
function ConditionalContent() {
const isHeaderShown = useContext(HeaderShownContext);
return (
<View style={{
paddingTop: isHeaderShown ? 0 : 20
}}>
<Text>
Header is {isHeaderShown ? 'shown' : 'hidden'}
</Text>
</View>
);
}
// Providing header shown context
<HeaderShownContext.Provider value={true}>
<ScreenWithHeader />
</HeaderShownContext.Provider>
// Combined with other contexts
function FullHeaderContext({ children, headerHeight, isShown, backInfo }) {
return (
<HeaderHeightContext.Provider value={headerHeight}>
<HeaderShownContext.Provider value={isShown}>
<HeaderBackContext.Provider value={backInfo}>
{children}
</HeaderBackContext.Provider>
</HeaderShownContext.Provider>
</HeaderHeightContext.Provider>
);
}Combine useFrameSize with breakpoints for responsive design:
function useResponsiveLayout() {
return useFrameSize(frame => {
const { width } = frame;
if (width < 480) return 'mobile';
if (width < 768) return 'tablet';
if (width < 1024) return 'desktop';
return 'large';
});
}
function ResponsiveComponent() {
const layout = useResponsiveLayout();
const styles = {
mobile: { padding: 16, fontSize: 14 },
tablet: { padding: 24, fontSize: 16 },
desktop: { padding: 32, fontSize: 18 },
large: { padding: 40, fontSize: 20 }
};
return (
<View style={styles[layout]}>
<Text>Layout: {layout}</Text>
</View>
);
}Combine header height with scroll views for proper content positioning:
function HeaderAwareScrollView({ children }) {
const headerHeight = useHeaderHeight();
const isHeaderShown = useContext(HeaderShownContext);
return (
<ScrollView
style={{ flex: 1 }}
contentContainerStyle={{
paddingTop: isHeaderShown ? headerHeight : 0
}}
scrollIndicatorInsets={{
top: isHeaderShown ? headerHeight : 0
}}
>
{children}
</ScrollView>
);
}Use frame size changes to monitor performance:
function PerformanceMonitor() {
const frameChanges = useRef(0);
useFrameSize(frame => {
frameChanges.current += 1;
console.log(`Frame changed ${frameChanges.current} times:`, frame);
return frame;
});
return null; // This is just for monitoring
}The hooks include proper error handling when used outside their providers:
// useHeaderHeight will throw if used outside HeaderHeightContext
function ComponentWithErrorHandling() {
try {
const headerHeight = useHeaderHeight();
return <Text>Header height: {headerHeight}</Text>;
} catch (error) {
return <Text>No header context available</Text>;
}
}Install with Tessl CLI
npx tessl i tessl/npm-react-navigation--elements