[251103] fix: VoiceResult Dropdown

🕐 커밋 시간: 2025. 11. 03. 18:18:30

📊 변경 통계:
  • 총 파일: 5개
  • 추가: +128줄
  • 삭제: -28줄

📝 수정된 파일:
  ~ com.twin.app.shoptime/src/components/TDropDown/TDropDown.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/SearchResults.new.v2.module.less
  ~ com.twin.app.shoptime/src/views/SearchPanel/components/TDropDown/TDropDown.jsx
  ~ com.twin.app.shoptime/src/views/SearchPanel/components/TestDropDown/TestDropDown.jsx

🔧 주요 변경 내용:
  • UI 컴포넌트 아키텍처 개선
  • 중간 규모 기능 개선
This commit is contained in:
2025-11-03 18:18:30 +09:00
parent 95124f51cf
commit df0e83c3a5
5 changed files with 128 additions and 28 deletions

View File

@@ -19,6 +19,7 @@ export default memo(function TDropDown({
scrollTop,
selectedIndex,
size,
width,
...rest
}) {
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
@@ -36,7 +37,11 @@ export default memo(function TDropDown({
}, [onClose]);
const _onChange = useCallback((event) => {
console.log('[TDropDown] 🔥 _onChange 호출됨! event:', event);
console.log('[TDropDown] event.selected:', event.selected);
console.log('[TDropDown] onSelect 콜백 존재:', !!onSelect);
if (onSelect) {
console.log('[TDropDown] ✅ onSelect 콜백 실행 중...');
onSelect({ selected: event.selected });
}
}, [onSelect]);
@@ -57,6 +62,9 @@ export default memo(function TDropDown({
onBlur={handleStopScrolling}
onOpen={_onOpen}
onClose={_onClose}
style={width === 'small' ? { width: '240px', minWidth: '240px' } :
width === 'medium' ? { width: '320px', minWidth: '320px' } :
width === 'large' ? { width: '400px', minWidth: '400px' } : undefined}
aria-disabled={countryCode && countryCode !== "US"}
aria-label={children}
{...rest}

View File

@@ -14,7 +14,6 @@ import { hideShopperHouseError } from '../../actions/searchActions';
import CustomImage from '../../components/CustomImage/CustomImage';
import TButtonTab, { LIST_TYPE } from '../../components/TButtonTab/TButtonTab';
import TDropDown from '../../components/TDropDown/TDropDown';
import TestDropDown from './components/TestDropDown/TestDropDown';
import TVirtualGridList from '../../components/TVirtualGridList/TVirtualGridList';
import { panel_names } from '../../utils/Config';
import { $L } from '../../utils/helperMethods';
@@ -372,6 +371,17 @@ const SearchResultsNew = ({
}
}, [onSearchInputFocus, howAboutTheseMode]);
// 🎯 floatLayer에 드롭다운 스타일 클래스 추가 (MyOrders와 동일한 패턴)
useEffect(() => {
const c = document.getElementById("floatLayer");
if (c) {
c.classList.add("searchResults_dropdown");
return () => {
c.classList.remove("searchResults_dropdown");
};
}
}, []);
// HowAboutThese API 응답 받으면 RESPONSE → SMALL 모드로 전환
useEffect(() => {
console.log('[HowAboutThese] 🔍 2. useEffect 실행');
@@ -447,7 +457,7 @@ const SearchResultsNew = ({
const displayedData = useMemo(() => {
if (!currentData) return [];
return currentData.slice(0, visibleCount);
}, [currentData, visibleCount]);
}, [currentData, visibleCount, dropDownTab]);
// 더 불러올 데이터가 있는지 확인
const hasMore = currentData && visibleCount < currentData.length;
@@ -513,6 +523,13 @@ const SearchResultsNew = ({
[]
);
// 🎯 탭 영역을 Spotlight 컨테이너로 감싸기 (MyOrders와 동일한 패턴)
// 드롭다운이 열렸을 때 포커스가 아래로 튕겨나가지 않도록 함
const TabContainer = useMemo(
() => SpotlightContainerDecorator({ enterTo: 'last-focused' }, 'div'),
[]
);
// ❌ [251026] DEPRECATED: 탭 키다운 핸들러 - Spotlight 속성으로 대체됨
// Spotlight의 data-spotlight-up 속성으로 처리하도록 변경
// 기존 코드 보존 (향후 필요시 참고용)
@@ -739,7 +756,7 @@ const SearchResultsNew = ({
{/* 메인 컨텐츠 영역 */}
<div className={css.itemBox}>
<div className={css.tabContainer}>
<TabContainer className={css.tabContainer}>
<TButtonTab
contents={buttonTabList}
onItemClick={handleButtonTabClick}
@@ -751,26 +768,21 @@ const SearchResultsNew = ({
{/* 필터링 dropdown - ShopperHouse 데이터가 있을 때 정렬 옵션 표시 */}
{tab === 0 && hasShopperHouseItems && (
<>
<TDropDown
className={classNames(
css.dropdown,
styleChange === true ? css.categoryDropdown : null
)}
onOpen={handleStyle}
onClose={handleStyleOut}
onSelect={handleSelectFilter}
selectedIndex={dropDownTab}
width="small"
>
{filterMethods}
</TDropDown>
{/* TestDropDown - 테스트용 드롭다운 */}
<TestDropDown className={css.dropdown} />
</>
<TDropDown
className={classNames(
css.dropdown,
styleChange === true ? css.categoryDropdown : null
)}
onOpen={handleStyle}
onClose={handleStyleOut}
onSelect={handleSelectFilter}
selectedIndex={dropDownTab}
width="small"
>
{filterMethods}
</TDropDown>
)}
</div>
</TabContainer>
{/* 아이템/쇼 컨텐츠 */}
{tab === 0 && <ItemCard itemInfo={displayedData} />}

View File

@@ -395,6 +395,79 @@
}
}
}
}
// floatLayer 드롭다운 스타일 관리 (MyOrders와 동일한 패턴)
// 6개 항목을 모두 표시 (각 항목 약 63px + 여백)
[class="searchResults_dropdown"] {
> div > div[id] > div:nth-child(2) {
-webkit-filter: none !important;
filter: none !important;
> div:nth-child(1) {
height: 380px !important;
width: 270px !important;
margin-top: 0 !important;
border-radius: 0 0 6px 6px !important;
background-color: #f5f5f5 !important;
overflow-y: auto !important;
> div {
width: 270px !important;
height: auto !important;
border-radius: 0 !important;
padding-top: 0 !important;
color: #333 !important;
background-color: white !important;
> div {
color: #333 !important;
background-color: white !important;
> div {
color: #333 !important;
background-color: white !important;
> div {
padding: 0 !important;
color: #333 !important;
background-color: white !important;
&:first-child {
> div:nth-child(1) {
border-radius: 6px 6px 0 0 !important;
overflow: hidden;
&:focus {
border-radius: 0 !important;
}
> div:first-child {
will-change: unset !important;
}
}
}
&:last-child {
> div:nth-child(1) {
border-radius: 0 0 6px 6px !important;
overflow: hidden;
&:focus {
border-radius: 0 0 6px 6px !important;
}
}
}
> div:nth-child(1) {
height: 63px !important;
padding: 20px 19px !important;
background-color: white !important;
color: #333 !important;
&:focus {
background-color: #c70850 !important;
color: white !important;
box-shadow: 0 0 22px 0 rgba(0, 0, 0, 0.5);
}
}
}
}
}
}
}
}
}
.searchBox {
.buttonContainer {
width: 100%;
display: flex;

View File

@@ -19,6 +19,7 @@ export default memo(function TDropDown({
scrollTop,
selectedIndex,
size,
width,
...rest
}) {
const { handleScrollReset, handleStopScrolling } = useScrollReset(scrollTop);
@@ -57,6 +58,9 @@ export default memo(function TDropDown({
onBlur={handleStopScrolling}
onOpen={_onOpen}
onClose={_onClose}
style={width === 'small' ? { width: '240px', minWidth: '240px' } :
width === 'medium' ? { width: '320px', minWidth: '320px' } :
width === 'large' ? { width: '400px', minWidth: '400px' } : undefined}
aria-disabled={countryCode && countryCode !== "US"}
aria-label={children}
{...rest}

View File

@@ -6,13 +6,15 @@ const TestDropDown = ({ className }) => {
const testOptions = ['Option 1', 'Option 2', 'Option 3'];
const [selectedIndex, setSelectedIndex] = useState(0);
const handleSelect = useCallback((selected) => {
const newSelectedIndex = selected.selected;
console.log('[TestDropDown] Selected:', newSelectedIndex, testOptions[newSelectedIndex]);
setSelectedIndex(newSelectedIndex);
}, [testOptions]);
const handleSelect = useCallback(({ selected }) => {
console.log('[TestDropDown] 🎯 선택됨 - index:', selected, 'text:', testOptions[selected]);
console.log('[TestDropDown] 이전 selectedIndex:', selectedIndex, '→ 새로운:', selected);
setSelectedIndex(selected);
}, [testOptions, selectedIndex]);
console.log('[TestDropDown] Rendering with selectedIndex:', selectedIndex);
console.log('[TestDropDown] 렌더링 - selectedIndex:', selectedIndex);
console.log('[TestDropDown] testOptions:', testOptions);
console.log('[TestDropDown] children으로 전달될 값:', testOptions);
return (
<TDropDown
@@ -20,6 +22,7 @@ const TestDropDown = ({ className }) => {
onSelect={handleSelect}
selectedIndex={selectedIndex}
size="small"
direction="above"
>
{testOptions}
</TDropDown>