import React, { ReactNode } from 'react'; import { cn } from '@/lib/utils'; import { getViewport } from '@/lib/responsive'; interface ResponsiveWrapperProps { children: ReactNode; className?: string; // Visibility control showOn?: ('mobile' | 'tablet' | 'desktop' | 'largeDesktop')[]; hideOn?: ('mobile' | 'tablet' | 'desktop' | 'largeDesktop')[]; // Mobile-specific behavior stackOnMobile?: boolean; centerOnMobile?: boolean; // Padding control padding?: 'none' | 'sm' | 'md' | 'lg' | 'responsive'; // Container control container?: boolean; maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'; } /** * ResponsiveWrapper Component * Provides comprehensive responsive behavior for any content */ export function ResponsiveWrapper({ children, className = '', showOn, hideOn, stackOnMobile = false, centerOnMobile = false, padding = 'md', container = false, maxWidth = 'xl', }: ResponsiveWrapperProps) { // Get visibility classes const getVisibilityClasses = () => { let classes = ''; if (showOn) { // Hide by default, show only on specified breakpoints classes += 'hidden '; if (showOn.includes('mobile')) classes += 'xs:block '; if (showOn.includes('tablet')) classes += 'md:block '; if (showOn.includes('desktop')) classes += 'lg:block '; if (showOn.includes('largeDesktop')) classes += 'xl:block '; } if (hideOn) { // Show by default, hide on specified breakpoints if (hideOn.includes('mobile')) classes += 'xs:hidden '; if (hideOn.includes('tablet')) classes += 'md:hidden '; if (hideOn.includes('desktop')) classes += 'lg:hidden '; if (hideOn.includes('largeDesktop')) classes += 'xl:hidden '; } return classes; }; // Get mobile-specific classes const getMobileClasses = () => { let classes = ''; if (stackOnMobile) { classes += 'flex-col xs:flex-row '; } if (centerOnMobile) { classes += 'items-center xs:items-start text-center xs:text-left '; } return classes; }; // Get padding classes const getPaddingClasses = () => { switch (padding) { case 'none': return ''; case 'sm': return 'px-3 py-2 xs:px-4 xs:py-3'; case 'md': return 'px-4 py-3 xs:px-6 xs:py-4'; case 'lg': return 'px-5 py-4 xs:px-8 xs:py-6'; case 'responsive': return 'px-4 py-3 xs:px-6 xs:py-4 md:px-8 md:py-6 lg:px-10 lg:py-8'; default: return 'px-4 py-3'; } }; // Get container classes if needed const getContainerClasses = () => { if (!container) return ''; const maxWidthClasses = { sm: 'max-w-sm', md: 'max-w-md', lg: 'max-w-lg', xl: 'max-w-xl', '2xl': 'max-w-2xl', '3xl': 'max-w-3xl', full: 'max-w-full', }; return `mx-auto ${maxWidthClasses[maxWidth]} w-full`; }; const wrapperClasses = cn( // Base classes 'responsive-wrapper', // Visibility getVisibilityClasses(), // Mobile behavior getMobileClasses(), // Padding getPaddingClasses(), // Container getContainerClasses(), // Custom classes className ); return
{children}
; } /** * ResponsiveGrid Wrapper * Creates responsive grid layouts with mobile-first approach */ interface ResponsiveGridProps { children: ReactNode; className?: string; // Column configuration columns?: { mobile?: number; tablet?: number; desktop?: number; largeDesktop?: number; }; gap?: 'none' | 'sm' | 'md' | 'lg' | 'responsive'; // Mobile stacking stackMobile?: boolean; // Alignment alignItems?: 'start' | 'center' | 'end' | 'stretch'; justifyItems?: 'start' | 'center' | 'end' | 'stretch'; } export function ResponsiveGrid({ children, className = '', columns = {}, gap = 'md', stackMobile = false, alignItems = 'start', justifyItems = 'start', }: ResponsiveGridProps) { const getGridColumns = () => { if (stackMobile) { return `grid-cols-1 sm:grid-cols-2 md:grid-cols-${columns.tablet || 3} lg:grid-cols-${columns.desktop || 4}`; } const mobile = columns.mobile || 1; const tablet = columns.tablet || 2; const desktop = columns.desktop || 3; const largeDesktop = columns.largeDesktop || 4; return `grid-cols-${mobile} sm:grid-cols-${tablet} md:grid-cols-${desktop} lg:grid-cols-${largeDesktop}`; }; const getGapClasses = () => { switch (gap) { case 'none': return 'gap-0'; case 'sm': return 'gap-2 sm:gap-3 md:gap-4'; case 'md': return 'gap-3 sm:gap-4 md:gap-6 lg:gap-8'; case 'lg': return 'gap-4 sm:gap-6 md:gap-8 lg:gap-12'; case 'responsive': return 'gap-2 xs:gap-3 sm:gap-4 md:gap-6 lg:gap-8 xl:gap-12'; default: return 'gap-4'; } }; return (
{children}
); } /** * ResponsiveStack Wrapper * Creates vertical stack that becomes horizontal on larger screens */ interface ResponsiveStackProps { children: ReactNode; className?: string; gap?: 'none' | 'sm' | 'md' | 'lg' | 'responsive'; reverseOnMobile?: boolean; wrap?: boolean; } export function ResponsiveStack({ children, className = '', gap = 'md', reverseOnMobile = false, wrap = false, }: ResponsiveStackProps) { const getGapClasses = () => { switch (gap) { case 'none': return 'gap-0'; case 'sm': return 'gap-2 sm:gap-3 md:gap-4'; case 'md': return 'gap-3 sm:gap-4 md:gap-6 lg:gap-8'; case 'lg': return 'gap-4 sm:gap-6 md:gap-8 lg:gap-12'; case 'responsive': return 'gap-2 xs:gap-3 sm:gap-4 md:gap-6 lg:gap-8'; default: return 'gap-4'; } }; return (
{children}
); } /** * ResponsiveSection Wrapper * Optimized section with responsive padding and max-width */ interface ResponsiveSectionProps { children: ReactNode; className?: string; padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'responsive'; maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | 'full'; centered?: boolean; safeArea?: boolean; } export function ResponsiveSection({ children, className = '', padding = 'responsive', maxWidth = '6xl', centered = true, safeArea = false, }: ResponsiveSectionProps) { const getPaddingClasses = () => { switch (padding) { case 'none': return ''; case 'sm': return 'px-3 py-4 xs:px-4 xs:py-6 md:px-6 md:py-8'; case 'md': return 'px-4 py-6 xs:px-6 xs:py-8 md:px-8 md:py-12'; case 'lg': return 'px-5 py-8 xs:px-8 xs:py-12 md:px-12 md:py-16'; case 'xl': return 'px-6 py-10 xs:px-10 xs:py-14 md:px-16 md:py-20'; case 'responsive': return 'px-4 py-6 xs:px-6 xs:py-8 md:px-8 md:py-12 lg:px-12 lg:py-16 xl:px-16 xl:py-20'; default: return 'px-4 py-6'; } }; const getMaxWidthClasses = () => { const maxWidthMap = { sm: 'max-w-sm', md: 'max-w-md', lg: 'max-w-lg', xl: 'max-w-xl', '2xl': 'max-w-2xl', '3xl': 'max-w-3xl', '4xl': 'max-w-4xl', '5xl': 'max-w-5xl', '6xl': 'max-w-6xl', full: 'max-w-full', }; return maxWidthMap[maxWidth]; }; return (
{children}
); } export default ResponsiveWrapper;