diff --git a/apps/web/src/app/[locale]/mypage/(github-custom)/LinePersonaSelect.tsx b/apps/web/src/app/[locale]/mypage/(github-custom)/LinePersonaSelect.tsx index 2136dd1b..1814dc32 100644 --- a/apps/web/src/app/[locale]/mypage/(github-custom)/LinePersonaSelect.tsx +++ b/apps/web/src/app/[locale]/mypage/(github-custom)/LinePersonaSelect.tsx @@ -3,7 +3,7 @@ import React, { useState } from 'react'; import { useTranslations } from 'next-intl'; import { cn } from '@gitanimals/ui-tailwind'; -import { DialogV2, ScrollArea } from '@gitanimals/ui-tailwind'; +import { DialogV2 } from '@gitanimals/ui-tailwind'; import { ExpandIcon } from 'lucide-react'; import { SelectPersonaList } from '../PersonaList'; @@ -31,25 +31,25 @@ export const LinePersonaSelect = ({ selectPersona, onChangePersona }: Props) => - - onChangePersona(persona.id)} - /> - + onChangePersona(persona.id)} + > + + setIsExtend(false)}> - + - - {t('line-type-select-pet')} - onChangePersona(persona.id)} > - - - + + {t('line-type-select-pet')} + + + + diff --git a/apps/web/src/app/[locale]/mypage/PersonaList.tsx b/apps/web/src/app/[locale]/mypage/PersonaList.tsx index 8b1a035d..4090cda9 100644 --- a/apps/web/src/app/[locale]/mypage/PersonaList.tsx +++ b/apps/web/src/app/[locale]/mypage/PersonaList.tsx @@ -101,10 +101,9 @@ function Grid() { // ─── InventoryGrid (Embla carousel + dynamic grid) ───────────────── const MAX_DOTS = 5; -const NAV_HEIGHT = 44; // arrows + dots bar +const NAV_HEIGHT = 40; // arrows(24px) + gap(8px) /** 다이얼로그 크롬: 제목(50) + 검색(40) + 필터(40) + 패딩/갭(30) + nav(44) */ const DIALOG_CHROME_HEIGHT = 204; -const INLINE_CHROME_HEIGHT = NAV_HEIGHT; function useInventoryGrid( totalItems: number, @@ -134,17 +133,27 @@ function useInventoryGrid( if (width < minItemSize * 2) return; const nextCols = Math.max(Math.floor((width + gap) / (minItemSize + gap)), 1); - // rows: 뷰포트 높이에서 크롬 높이를 뺀 가용 영역 기반 - // 실제 아이템 높이를 측정하여 정확한 행 수 계산 - const firstItem = el.querySelector('[class*="grid"] > button'); - const measuredHeight = firstItem ? firstItem.getBoundingClientRect().height : 0; - const itemHeight = measuredHeight > 0 ? measuredHeight : minItemSize; + // rows: 가용 높이 기반. 아이템이 aspect-square이므로 컬럼 너비 = 아이템 높이 + const colWidth = (width - (nextCols - 1) * gap) / nextCols; + const itemHeight = colWidth; const rowHeight = itemHeight + gap; const vh = window.innerHeight; - const chrome = mode === 'dialog' ? DIALOG_CHROME_HEIGHT : INLINE_CHROME_HEIGHT; - const dialogHeight = mode === 'dialog' ? vh * 0.9 : vh; - const availableHeight = dialogHeight - chrome; + let availableHeight: number; + if (mode === 'dialog') { + availableHeight = vh * 0.9 - DIALOG_CHROME_HEIGHT; + } else { + // inline: 컨테이너에 flex-1 min-h-0이 설정되어 있으므로 + // clientHeight가 부모 flex에 의해 제한된 실제 높이 + const containerHeight = el.clientHeight; + if (containerHeight > 0) { + availableHeight = containerHeight - NAV_HEIGHT; + } else { + // 초기 렌더링 시 높이가 0일 수 있음 → fallback + const rect = el.getBoundingClientRect(); + availableHeight = vh - rect.top - NAV_HEIGHT; + } + } const nextRows = availableHeight > 0 ? Math.min(Math.max(Math.floor(availableHeight / rowHeight), minRows), maxRows) : minRows; @@ -225,11 +234,11 @@ function InventoryGrid({ minRows = 2, maxRows = 10, minItemSize = 64, gap = 4, m } return ( -
+
{!ready ? null : ( <> {/* Navigation: arrows left, dots right */} -
+
diff --git a/apps/web/src/app/[locale]/mypage/layout.tsx b/apps/web/src/app/[locale]/mypage/layout.tsx index dbde086b..8f63696c 100644 --- a/apps/web/src/app/[locale]/mypage/layout.tsx +++ b/apps/web/src/app/[locale]/mypage/layout.tsx @@ -19,10 +19,10 @@ async function MypageLayout({ children }: { children: React.ReactNode }) {
- - - + + + + + + + +