All files / components/ui ResponsiveContainer.tsx

100% Statements 13/13
100% Branches 13/13
100% Functions 2/2
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                                                                                                                1x               11x 11x     11x 11x   1x   1x   1x     8x       11x     11x                               11x                         1x  
/**
 * ResponsiveContainer Component
 * 
 * Wrapper component that applies responsive layout properties and safe area insets
 * Ensures consistent mobile-optimized layout across all child components
 * 
 * @module components/ui/ResponsiveContainer
 * @category Mobile UI
 * @korean 반응형컨테이너
 */
 
import React, { CSSProperties } from 'react';
import { useWindowSize } from '../../hooks/useWindowSize';
import { useResponsiveLayout } from '../../hooks/useResponsiveLayout';
 
/**
 * Props for ResponsiveContainer component
 */
export interface ResponsiveContainerProps {
  /** Child components to render */
  readonly children: React.ReactNode;
  /** Whether to apply safe area insets */
  readonly applySafeArea?: boolean;
  /** Padding density */
  readonly padding?: 'none' | 'compact' | 'normal' | 'spacious';
  /** Custom className */
  readonly className?: string;
  /** Custom style overrides */
  readonly style?: CSSProperties;
  /** Test ID for testing */
  readonly testId?: string;
}
 
/**
 * ResponsiveContainer Component
 * 
 * Automatically applies responsive layout properties including:
 * - Safe area insets for mobile devices (notch, home indicator)
 * - Responsive padding based on device size
 * - Touch-friendly spacing
 * 
 * Usage:
 * - Wrap HUD components for automatic mobile optimization
 * - Apply safe area insets to avoid overlap with device UI
 * - Consistent spacing across all screen sizes
 * 
 * @example
 * ```tsx
 * <ResponsiveContainer applySafeArea padding="normal">
 *   <CombatHUD />
 * </ResponsiveContainer>
 * ```
 * 
 * @public
 * @korean 반응형컨테이너
 */
export const ResponsiveContainer: React.FC<ResponsiveContainerProps> = ({
  children,
  applySafeArea = true,
  padding = 'normal',
  className,
  style,
  testId = 'responsive-container',
}) => {
  const { width, height } = useWindowSize();
  const layout = useResponsiveLayout(width, height);
 
  // Calculate padding based on density
  const getPadding = () => {
    switch (padding) {
      case 'none':
        return 0;
      case 'compact':
        return layout.spacing.xs;
      case 'spacious':
        return layout.spacing.lg;
      case 'normal':
      default:
        return layout.spacing.md;
    }
  };
 
  const paddingValue = getPadding();
 
  // Container style with safe area insets
  const containerStyle: CSSProperties = {
    width: '100%',
    height: '100%',
    boxSizing: 'border-box',
    ...(applySafeArea && {
      paddingTop: layout.safeArea.top + paddingValue,
      paddingBottom: layout.safeArea.bottom + paddingValue,
      paddingLeft: layout.safeArea.left + paddingValue,
      paddingRight: layout.safeArea.right + paddingValue,
    }),
    ...(!applySafeArea && padding !== 'none' && {
      padding: paddingValue,
    }),
    ...style,
  };
 
  return (
    <div
      className={className}
      style={containerStyle}
      data-testid={testId}
      data-mobile={layout.isMobile}
      data-landscape={layout.isLandscape}
    >
      {children}
    </div>
  );
};
 
ResponsiveContainer.displayName = 'ResponsiveContainer';