디자인디테일

This commit is contained in:
koreacomp5
2025-11-01 23:16:22 +09:00
parent f84111b9cc
commit 27cf98eef2
20 changed files with 735 additions and 384 deletions

View File

@@ -1,10 +1,12 @@
"use client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import Image from "next/image";
import { SelectedBanner } from "@/app/components/SelectedBanner";
type Banner = { id: string; title: string; imageUrl: string; linkUrl?: string | null };
type SubItem = { id: string; name: string; href: string };
export function HeroBanner() {
export function HeroBanner({ subItems, activeSubId }: { subItems?: SubItem[]; activeSubId?: string }) {
const [banners, setBanners] = useState<Banner[]>([]);
const [activeIndex, setActiveIndex] = useState(0);
const [isHovered, setIsHovered] = useState(false);
@@ -65,7 +67,7 @@ export function HeroBanner() {
const translatePercent = useMemo(() => (numSlides > 0 ? -(activeIndex * 100) : 0), [activeIndex, numSlides]);
if (numSlides === 0) return null;
if (numSlides === 0) return <SelectedBanner height={224} />;
return (
<section
@@ -88,7 +90,7 @@ export function HeroBanner() {
) : (
<Image src={banner.imageUrl} alt={banner.title} fill priority className="object-cover" />
)}
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/60 via-black/10 to-transparent" />
{/* Figma 스타일: 오버레이 제거 */}
<div className="absolute bottom-3 left-4 right-4 md:bottom-5 md:left-6 md:right-6">
<h2 className="line-clamp-2 text-lg font-semibold md:text-2xl">{banner.title}</h2>
</div>
@@ -96,26 +98,44 @@ export function HeroBanner() {
))}
</div>
{/* Controls */}
{/* Pagination - Figma 스타일: 활성은 주황 바, 비활성은 회색 점 (배너 위에 오버랩) */}
{numSlides > 1 && (
<>
<button
type="button"
aria-label="Previous slide"
onClick={goPrev}
className="absolute left-2 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/40 p-2 text-white backdrop-blur transition hover:bg-black/60 focus:outline-none focus:ring-2 focus:ring-white/60"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="h-5 w-5"><path d="M15.75 19.5 8.25 12l7.5-7.5" /></svg>
</button>
<button
type="button"
aria-label="Next slide"
onClick={goNext}
className="absolute right-2 top-1/2 z-10 -translate-y-1/2 rounded-full bg-black/40 p-2 text-white backdrop-blur transition hover:bg-black/60 focus:outline-none focus:ring-2 focus:ring-white/60"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="h-5 w-5"><path d="M8.25 4.5 15.75 12l-7.5 7.5" /></svg>
</button>
</>
<div className="pointer-events-auto absolute bottom-3 left-1/2 -translate-x-1/2 z-10 flex items-center gap-[6px]">
{banners.map((_, i) => (
<button
key={i}
aria-label={`Go to slide ${i + 1}`}
aria-current={activeIndex === i ? "true" : undefined}
onClick={() => goTo(i)}
className={
activeIndex === i
? "h-[4px] w-[18px] rounded-full bg-[#F94B37]"
: "h-[6px] w-[6px] rounded-full bg-[rgba(255,255,255,0.6)] hover:bg-white"
}
/>
))}
</div>
)}
</div>
{/* 분리된 하단 블랙 바: 높이 58px, 중앙 서브카테고리 */}
<div className="mt-2 h-[58px] bg-black rounded-xl flex items-center justify-center px-2">
{Array.isArray(subItems) && subItems.length > 0 && (
<div className="flex items-center gap-[8px] overflow-x-auto no-scrollbar">
{subItems.map((s) => (
<a
key={s.id}
href={s.href}
className={
s.id === activeSubId
? "px-3 h-[28px] rounded-full bg-[#F94B37] text-white text-[12px] leading-[28px] whitespace-nowrap"
: "px-3 h-[28px] rounded-full bg-transparent text-white/85 hover:text-white border border-white/30 text-[12px] leading-[28px] whitespace-nowrap"
}
>
{s.name}
</a>
))}
</div>
)}
</div>
@@ -126,20 +146,7 @@ export function HeroBanner() {
</div>
)} */}
{/* Pagination */}
{numSlides > 1 && (
<div className="absolute bottom-3 left-1/2 -translate-x-1/2 z-10 flex gap-2">
{banners.map((_, i) => (
<button
key={i}
aria-label={`Go to slide ${i + 1}`}
aria-current={activeIndex === i ? "true" : undefined}
onClick={() => goTo(i)}
className={`h-2 w-2 rounded-full transition ${activeIndex === i ? "bg-white" : "bg-white/40 hover:bg-white/70"}`}
/>
))}
</div>
)}
</section>
);
}