[251111] docs: views - ShopNowContents.jsx, TabContainerV2-Divider-Pro...
🕐 커밋 시간: 2025. 11. 11. 19:49:42 📊 변경 통계: • 총 파일: 2개 • 추가: +2줄 • 삭제: -1줄 📁 추가된 파일: + com.twin.app.shoptime/.docs/player-panel/TabContainerV2-Divider-Problem-Analysis.md 📝 수정된 파일: ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx 🔧 주요 변경 내용: • 개발 문서 및 가이드 개선
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
# TabContainerV2 구분선 문제 분석 및 해결 방안
|
||||
|
||||
## 문제 개요
|
||||
|
||||
PlayerPanel의 TabContainerV2에서 ShopNowContents와 YouMayLikeContents 사이에 세로 구분선을 표시해야 하지만, 현재 TVirtualGridList 구조의 한계로 인해 올바르게 동작하지 않음
|
||||
|
||||
## 현재 구조 분석
|
||||
|
||||
### 1. TabContainerV2 구조
|
||||
- 위치: `src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx`
|
||||
- 3개의 tabIndex로 구성 (0: ShopNow, 1: LiveChannel, 2: ShopNowButton)
|
||||
- version=2에서 ShopNow와 YouMayLike 통합 표시
|
||||
|
||||
### 2. ShopNowContents 구조
|
||||
- 위치: `src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx`
|
||||
- ShopNow 아이템 < 3개일 때 YouMayLike 아이템을 통합하여 표시
|
||||
- combinedItems 배열로 ShopNow + YouMayLike 통합 관리
|
||||
- TVirtualGridList로 가로 방향 렌더링 (itemWidth: 310px, itemHeight: 445px, spacing: 30px)
|
||||
|
||||
### 3. 현재 구분선 구현 로직
|
||||
```javascript
|
||||
// YouMayLike 시작 지점 여부 (구분선 표시)
|
||||
const isYouMayLikeStart = shopNowInfo && index === shopNowInfo.length;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isYouMayLikeStart && <div className={css.youMayLikeDivider} />}
|
||||
<TItemCard {...props} />
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
## 문제 상세
|
||||
|
||||
### 1. TVirtualGridList 구조적 한계
|
||||
- TVirtualGridList는 각 아이템이 고정된 크기를 가짐 (itemWidth: 310px)
|
||||
- renderItem 함수 내에서 추가적인 요소(divider)를 렌더링하면 레이아웃 충돌 발생
|
||||
- divider가 TItemCard와 같은 공간을 차지하려고 하여 빈 TItemCard가 표시되는 현상
|
||||
|
||||
### 2. 포커스 이동 문제
|
||||
- divider가 포커스를 받거나 포커스 이동을 방해하는 현상
|
||||
- 실제 상품과 포커스 위치가 불일치하는 문제
|
||||
|
||||
### 3. 간격 문제
|
||||
- 구분선으로 인해 상품들 간의 간격이 넓어짐
|
||||
- 사용자 경험 저하
|
||||
|
||||
## 해결 방안 분석
|
||||
|
||||
### 방안 1: TItemCard Wrapper 방식 ❌
|
||||
**구현:**
|
||||
```javascript
|
||||
<div className={css.itemWrapper}>
|
||||
<TItemCard {...props} />
|
||||
</div>
|
||||
```
|
||||
|
||||
**CSS:**
|
||||
```css
|
||||
.itemWrapper::before {
|
||||
content: '';
|
||||
width: 2px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.itemWrapper.showDivider::before {
|
||||
opacity: 1;
|
||||
background: rgba(234, 234, 234, 0.3);
|
||||
}
|
||||
```
|
||||
|
||||
**문제점:**
|
||||
- itemWidth를 310px → 327px로 증가시켜야 함
|
||||
- 상품 간 간격이 넓어짐
|
||||
- 포커스와 상품 위치 불일치
|
||||
- 전체 레이아웃 변경 필요
|
||||
|
||||
### 방안 2: Divider 아이템 추가 방식 ❌
|
||||
**구현:**
|
||||
```javascript
|
||||
// combinedItems에 divider 추가
|
||||
items.push({ _type: 'divider' });
|
||||
|
||||
// renderItem에서 처리
|
||||
if (item._type === 'divider') {
|
||||
return <div className={css.youMayLikeDivider} />;
|
||||
}
|
||||
```
|
||||
|
||||
**문제점:**
|
||||
- divider가 TVirtualGridList 아이템으로 인식되어 TItemCard만큼 공간 차지
|
||||
- ShopNow와 YouMayLike 사이 포커스 이동이 막힘
|
||||
- 빈 공간이 생기는 문제 여전히 존재
|
||||
|
||||
### 방안 3: 두 개의 TVirtualGridList 분리 방식 ✅
|
||||
**구현:**
|
||||
```javascript
|
||||
<div className={css.shopNowContainer}>
|
||||
<TVirtualGridList>
|
||||
[ShopNow1][ShopNow2]
|
||||
</TVirtualGridList>
|
||||
</div>
|
||||
|
||||
<div className={css.dividerContainer}>
|
||||
<div className={css.youMayLikeDivider} />
|
||||
</div>
|
||||
|
||||
<div className={css.youMayLikeContainer}>
|
||||
<TVirtualGridList>
|
||||
[YouMayLike1][YouMayLike2]
|
||||
</TVirtualGridList>
|
||||
</div>
|
||||
```
|
||||
|
||||
**장점:**
|
||||
- 구분선을 완벽하게 제어 가능
|
||||
- 각 TVirtualGridList가 독립적으로 동작
|
||||
- 빈 TItemCard 문제 해결
|
||||
- 레이아웃 깨짐 없음
|
||||
- 기존 기능 모두 유지 가능
|
||||
|
||||
**고려사항:**
|
||||
- 포커스 이동 핸들러 구현 필요
|
||||
- ShopNow 마지막 아이템 → 구분선 → YouMayLike 첫 아이템
|
||||
- YouMayLike 첫 아이템 → 구분선 → ShopNow 마지막 아이템
|
||||
- Spotlight 컨테이너 간 이동 수동 처리 필요
|
||||
|
||||
**포커스 이동 구현 예시:**
|
||||
```javascript
|
||||
// ShopNow 마지막 아이템
|
||||
onSpotlightRight={() => Spotlight.focus('divider-element')}
|
||||
|
||||
// 구분선 SpottableDiv
|
||||
<SpottableDiv
|
||||
spotlightId="divider-element"
|
||||
onSpotlightLeft={() => Spotlight.focus('shop-now-last')}
|
||||
onSpotlightRight={() => Spotlight.focus('you-may-like-first')}
|
||||
>
|
||||
<div className={css.youMayLikeDivider} />
|
||||
</SpottableDiv>
|
||||
|
||||
// YouMayLike 첫 아이템
|
||||
onSpotlightLeft={() => Spotlight.focus('divider-element')}
|
||||
```
|
||||
|
||||
## 추천 해결책
|
||||
|
||||
**방안 3: 두 개의 TVirtualGridList 분리 방식**을 추천합니다.
|
||||
|
||||
### 이유
|
||||
1. **근본적인 해결**: TVirtualGridList 구조적 한계를 완전히 회피
|
||||
2. **레이아웃 안정성**: 각 컴포넌트가 독립적으로 동작하여 예측 가능한 결과
|
||||
3. **유지보수성**: 기존 로직을 최소한만 수정하며 명확한 분리
|
||||
4. **사용자 경험**: 포커스 이동이 더 명확하고 직관적
|
||||
|
||||
### 구현 우선순위
|
||||
1. ShopNow TVirtualGridList 분리
|
||||
2. YouMayLike TVirtualGridList 분리
|
||||
3. 구분선 SpottableDiv 추가
|
||||
4. 포커스 이동 핸들러 구현
|
||||
5. 테스트 및 디버깅
|
||||
|
||||
### 영향 범위
|
||||
- **수정 필요 파일**: `ShopNowContents.jsx` 1개
|
||||
- **기존 기능**: 모두 유지 가능
|
||||
- **성능 영향**: 미미 (VirtualGridList 인스턴스 1개 추가)
|
||||
- **사용자 영향**: 없음 (개선된 경험 제공)
|
||||
|
||||
## 관련 파일
|
||||
|
||||
- `src/views/PlayerPanel/PlayerTabContents/v2/TabContainer.v2.jsx`
|
||||
- `src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.jsx`
|
||||
- `src/views/PlayerPanel/PlayerTabContents/TabContents/YouMayLikeContents.jsx`
|
||||
- `src/views/PlayerPanel/PlayerTabContents/TabContents/ShopNowContents.v2.module.less`
|
||||
- `src/components/TVirtualGridList/TVirtualGridList.jsx`
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
import { Job } from '@enact/core/util';
|
||||
@@ -160,7 +161,7 @@ export default function ShopNowContents({
|
||||
|
||||
return (
|
||||
<>
|
||||
{isYouMayLikeStart && <div className={css.youMayLikeDivider} />}
|
||||
{/* {isYouMayLikeStart && <div className={css.youMayLikeDivider} />} */}
|
||||
<TItemCard
|
||||
{...rest}
|
||||
key={prdtId}
|
||||
|
||||
Reference in New Issue
Block a user