CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-navigation--elements

UI Components for React Navigation providing headers, buttons, and layout components with cross-platform support

Pending
Overview
Eval results
Files

hooks-contexts.mddocs/

Hooks and Contexts

React hooks and context providers for accessing navigation state, dimensions, header information, and frame size tracking.

Capabilities

useHeaderHeight Hook

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>
  );
}

useFrameSize Hook

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>
  );
}

Context Components

FrameSizeProvider

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>
  );
}

HeaderBackContext

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>

HeaderHeightContext

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>

HeaderShownContext

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>
  );
}

Advanced Usage Patterns

Responsive Layout Hook

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>
  );
}

Header-Aware Scrolling

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>
  );
}

Performance Monitoring

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
}

Context Error Handling

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>;
  }
}

Platform Considerations

Web

  • ResizeObserver: Uses ResizeObserver API for efficient frame size tracking
  • CSS Layout: Frame size updates coordinate with CSS layout changes
  • Performance: Throttled updates prevent excessive re-renders during window resize

Mobile (iOS/Android)

  • Orientation Changes: Automatically handles device orientation changes
  • Safe Area: Frame size accounts for safe area insets
  • Keyboard: Frame updates when software keyboard appears/disappears

Install with Tessl CLI

npx tessl i tessl/npm-react-navigation--elements

docs

header-components.md

hooks-contexts.md

index.md

interactive-components.md

layout-components.md

utility-components.md

utility-functions.md

tile.json