Ramble-FE / components / TopMenuBar / index.tsx
index.tsx
Raw
import { BlurView } from "expo-blur";
import React, { useEffect, useMemo, useState } from "react";
import { Dimensions, Image, StyleSheet } from "react-native";
import { DesktopMenu } from "./DesktopMenu";
import { MobileMenu } from "./MobileMenu";
import { colors } from "./styles";
import { BREAKPOINTS, HEADER_HEIGHT, menuItems } from "./types";

export default function TopMenuBar({ onHoverOut }: { onHoverOut: () => void }) {
    const [width, setWidth] = useState(Dimensions.get('window').width);
    const [menuOpen, setMenuOpen] = useState(false);
    
    const isTabletOrDesktop = useMemo(() => width >= BREAKPOINTS.tablet, [width]);

    const toggleMenu = () => {
        setMenuOpen(prev => !prev);
    };

    const closeMenu = () => {
        setMenuOpen(false);
    };

    useEffect(() => {
        const handler = ({ window }: { window: { width: number } }) => setWidth(window.width);
        const subscription = Dimensions.addEventListener('change', handler);
        
        return () => {
            if (subscription?.remove) {
                subscription.remove();
            }
        };
    }, []);

    return (
        <BlurView 
            style={styles.container} 
            intensity={30} 
            tint="light" 
            onPointerLeave={onHoverOut}
        >
            {/* 로고 */}
            <Image
                source={require("../../assets/images/react-logo.png")} // TODO:   
                style={styles.logo}
                resizeMode="contain"
            />

            {/* 반응형 메뉴 */}
            {isTabletOrDesktop ? (
                <DesktopMenu items={menuItems} />
            ) : (
                <MobileMenu 
                    items={menuItems}
                    isOpen={menuOpen}
                    onToggle={toggleMenu}
                    onClose={closeMenu}
                />
            )}
        </BlurView>
    );
}

const styles = StyleSheet.create({
    container: {
        ...StyleSheet.absoluteFillObject,
        flexDirection: "row",
        alignItems: "center",
        justifyContent: "space-between",
        paddingHorizontal: 10,
        height: HEADER_HEIGHT,
        borderBottomWidth: 1,
        borderBottomColor: colors.border,
        zIndex: 9,
    },
    logo: {
        marginLeft: 10,
        width: 40,
        height: 40,
    },
});