From 5688fd9d9f806cbd081f1636a68e6229f58b6294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9C=A0=EB=B3=91=EC=B2=A0?= Date: Mon, 23 Mar 2026 12:29:51 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20[=EA=B3=B5=ED=86=B5]=20HeaderFavoritesBa?= =?UTF-8?q?r=20=EC=A6=90=EA=B2=A8=EC=B0=BE=EA=B8=B0=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20=EC=8B=9C=20=EA=B9=9C=EB=B9=A1=EC=9E=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/layout/HeaderFavoritesBar.tsx | 51 +++++++++----------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/components/layout/HeaderFavoritesBar.tsx b/src/components/layout/HeaderFavoritesBar.tsx index 9600e0aa..dbbdf6ef 100644 --- a/src/components/layout/HeaderFavoritesBar.tsx +++ b/src/components/layout/HeaderFavoritesBar.tsx @@ -20,10 +20,7 @@ import { useFavoritesStore } from '@/stores/favoritesStore'; import { iconMap } from '@/lib/utils/menuTransform'; import type { FavoriteItem } from '@/stores/favoritesStore'; -// "시스템 대시보드" 기준 텍스트 폭 (7글자 ≈ 80px) const TEXT_DEFAULT_MAX = 80; -const TEXT_EXPANDED_MAX = 200; -const TEXT_SHRUNK_MAX = 28; const OVERFLOW_BTN_WIDTH = 56; const GAP = 6; @@ -94,11 +91,12 @@ export default function HeaderFavoritesBar({ isMobile }: HeaderFavoritesBarProps return () => window.removeEventListener('resize', check); }, []); - // 즐겨찾기 변경 시 측정 리셋 + // 즐겨찾기 변경 시 측정 리셋 (visibleCount는 유지 → 깜빡임 방지) useEffect(() => { measuredRef.current = false; chipWidthsRef.current = []; - setVisibleCount(favorites.length); + // 삭제 시에만 count 보정 (현재 count가 전체보다 크면 맞춤) + setVisibleCount((prev) => Math.min(prev, favorites.length)); }, [favorites.length]); // 모바일/태블릿 ↔ 데스크탑 전환 시 측정 리셋 @@ -106,22 +104,31 @@ export default function HeaderFavoritesBar({ isMobile }: HeaderFavoritesBarProps if (!isMobile && !isTablet) { measuredRef.current = false; chipWidthsRef.current = []; - setVisibleCount(favorites.length); + setVisibleCount((prev) => Math.min(prev, favorites.length)); } }, [isMobile, isTablet, favorites.length]); - // 데스크탑 동적 오버플로: 전체 chip 폭 측정 → 저장 → resize 시 재계산 + // 데스크탑 동적 오버플로: chip 폭 측정 → resize 시 재계산 useEffect(() => { if (isMobile || isTablet) return; const container = containerRef.current; if (!container) return; const calculate = () => { - // 최초: 전체 chip 렌더 상태에서 폭 저장 + // 미측정 칩이 있으면 렌더된 칩에서 폭 수집 if (!measuredRef.current) { const chips = container.querySelectorAll('[data-chip]'); - if (chips.length === favorites.length && chips.length > 0) { - chipWidthsRef.current = Array.from(chips).map((c) => c.offsetWidth); + if (chips.length > 0) { + // 렌더된 칩들의 실제 폭 저장 + const measured = Array.from(chips).map((c) => c.offsetWidth); + // 아직 렌더 안 된 칩(overflow)은 평균 폭으로 추정 + if (measured.length < favorites.length) { + const avgWidth = Math.round(measured.reduce((a, b) => a + b, 0) / measured.length); + while (measured.length < favorites.length) { + measured.push(avgWidth); + } + } + chipWidthsRef.current = measured; measuredRef.current = true; } else { return; @@ -207,14 +214,7 @@ export default function HeaderFavoritesBar({ isMobile }: HeaderFavoritesBarProps <> {visibleItems.map((item) => { const Icon = getIcon(item.iconName); - const isHovered = hoveredId === item.id; - const isOtherHovered = hoveredId !== null && !isHovered; - - const textMaxWidth = isHovered - ? TEXT_EXPANDED_MAX - : isOtherHovered - ? TEXT_SHRUNK_MAX - : TEXT_DEFAULT_MAX; + const isOtherHovered = hoveredId !== null && hoveredId !== item.id; return ( @@ -225,21 +225,16 @@ export default function HeaderFavoritesBar({ isMobile }: HeaderFavoritesBarProps size="sm" onClick={() => handleClick(item)} onMouseEnter={() => setHoveredId(item.id)} - className={`rounded-full text-white h-8 flex items-center overflow-hidden ${ - isOtherHovered ? 'px-2 gap-1 bg-blue-400/70' : 'px-3 gap-1.5 bg-blue-600 hover:bg-blue-700' + className={`rounded-full h-8 flex items-center overflow-hidden px-3 gap-1.5 transition-colors ${ + isOtherHovered + ? 'bg-blue-500/30 text-blue-200' + : 'bg-blue-600 hover:bg-blue-700 text-white' }`} - style={{ - transition: 'all 500ms cubic-bezier(0.25, 0.8, 0.25, 1)', - }} > {Icon && } {item.label}