[251211] feat: FeaturedBrandsPanel , TopBannerImage Modal
🕐 커밋 시간: 2025. 12. 11. 14:04:14 📊 변경 통계: • 총 파일: 3개 • 추가: +63줄 • 삭제: -25줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/components/GlobalPopup/GlobalPopup.jsx ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.jsx ~ com.twin.app.shoptime/src/views/FeaturedBrandsPanel/TopBannerImage/TopBannerPopup.module.less 🔧 주요 변경 내용: • UI 컴포넌트 아키텍처 개선 • 소규모 기능 개선
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import React, {
|
import React, {
|
||||||
useCallback,
|
useCallback,
|
||||||
|
useEffect,
|
||||||
useMemo,
|
useMemo,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
@@ -14,6 +15,8 @@ import {
|
|||||||
useSelector,
|
useSelector,
|
||||||
} from 'react-redux';
|
} from 'react-redux';
|
||||||
|
|
||||||
|
import Spotlight from '@enact/spotlight';
|
||||||
|
|
||||||
import { setHidePopup } from '../../actions/commonActions';
|
import { setHidePopup } from '../../actions/commonActions';
|
||||||
import { getPopupConfig } from '../../constants/popupConfig';
|
import { getPopupConfig } from '../../constants/popupConfig';
|
||||||
import usePrevious from '../../hooks/usePrevious';
|
import usePrevious from '../../hooks/usePrevious';
|
||||||
@@ -139,6 +142,18 @@ const GlobalPopup = () => {
|
|||||||
setImageDimensions(dimensions);
|
setImageDimensions(dimensions);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Spotlight 제어: 팝업 오픈/클로즈 시 포커스 트래핑
|
||||||
|
useEffect(() => {
|
||||||
|
if (popupVisible && activePopup === 'topBannerImagePopup') {
|
||||||
|
console.log("[GLOBAL-POPUP] Pausing Spotlight for modal popup");
|
||||||
|
Spotlight.pause();
|
||||||
|
return () => {
|
||||||
|
console.log("[GLOBAL-POPUP] Resuming Spotlight after modal close");
|
||||||
|
Spotlight.resume();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, [popupVisible, activePopup]);
|
||||||
|
|
||||||
// 현재 팝업 설정
|
// 현재 팝업 설정
|
||||||
const currentConfig = useMemo(() => {
|
const currentConfig = useMemo(() => {
|
||||||
if (!activePopup) return null;
|
if (!activePopup) return null;
|
||||||
@@ -231,7 +246,8 @@ const GlobalPopup = () => {
|
|||||||
const popupHeight = '804px';
|
const popupHeight = '804px';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div
|
||||||
|
style={{
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
@@ -242,8 +258,11 @@ const GlobalPopup = () => {
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
zIndex: 9999
|
zIndex: 9999
|
||||||
}}>
|
}}
|
||||||
<div style={{
|
onClick={handlers.handleClose}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
width: popupWidth,
|
width: popupWidth,
|
||||||
height: popupHeight,
|
height: popupHeight,
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
@@ -251,7 +270,9 @@ const GlobalPopup = () => {
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column'
|
flexDirection: 'column'
|
||||||
}}>
|
}}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<TopBannerPopup
|
<TopBannerPopup
|
||||||
title={popupData?.pupBanrImgNm || 'Popup'}
|
title={popupData?.pupBanrImgNm || 'Popup'}
|
||||||
imageUrl={popupData?.pupBanrImgUrl}
|
imageUrl={popupData?.pupBanrImgUrl}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { memo, useCallback, useState } from "react";
|
import React, { memo, useCallback, useState, useEffect, useRef } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { setHidePopup } from "../../../actions/commonActions";
|
import { setHidePopup } from "../../../actions/commonActions";
|
||||||
import css from "./TopBannerPopup.module.less";
|
import css from "./TopBannerPopup.module.less";
|
||||||
@@ -6,6 +6,7 @@ import css from "./TopBannerPopup.module.less";
|
|||||||
const TopBannerPopup = memo(({ title, imageUrl, imageAlt, onImageLoad }) => {
|
const TopBannerPopup = memo(({ title, imageUrl, imageAlt, onImageLoad }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
|
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
|
||||||
|
const closeButtonRef = useRef(null);
|
||||||
|
|
||||||
const handleImageLoad = useCallback((e) => {
|
const handleImageLoad = useCallback((e) => {
|
||||||
const img = e.target;
|
const img = e.target;
|
||||||
@@ -29,6 +30,14 @@ const TopBannerPopup = memo(({ title, imageUrl, imageAlt, onImageLoad }) => {
|
|||||||
dispatch(setHidePopup());
|
dispatch(setHidePopup());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
// 팝업이 마운트되었을 때 Close 버튼에 포커스
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("[TOP-BANNER-POPUP] Component mounted - focusing close button");
|
||||||
|
if (closeButtonRef.current) {
|
||||||
|
closeButtonRef.current.focus();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={css.container}>
|
<div className={css.container}>
|
||||||
{/* Title Section */}
|
{/* Title Section */}
|
||||||
@@ -48,7 +57,12 @@ const TopBannerPopup = memo(({ title, imageUrl, imageAlt, onImageLoad }) => {
|
|||||||
|
|
||||||
{/* Button Section */}
|
{/* Button Section */}
|
||||||
<div className={css.buttonSection}>
|
<div className={css.buttonSection}>
|
||||||
<button className={css.closeButton} onClick={handleClose} aria-label="Close popup">
|
<button
|
||||||
|
ref={closeButtonRef}
|
||||||
|
className={css.closeButton}
|
||||||
|
onClick={handleClose}
|
||||||
|
aria-label="Close popup"
|
||||||
|
>
|
||||||
CLOSE
|
CLOSE
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
@import "../../../style/CommonStyle.module.less";
|
||||||
|
@import "../../../style/utils.module.less";
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -86,12 +89,12 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #6a7278;
|
background: @PRIMARY_COLOR_RED;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 2px solid #fff;
|
background: @PRIMARY_COLOR_RED;
|
||||||
outline-offset: 2px;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
|
|||||||
Reference in New Issue
Block a user