Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 9 additions & 20 deletions src/app/(landing)/_components/landing-animations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { cn } from "@/lib/utils";

type GSAPInstance = (typeof import("gsap"))["gsap"];
type GSAPContext = ReturnType<GSAPInstance["context"]>;

let gsapRegistration: Promise<GSAPInstance> | null = null;

const ensureGsapWithScrollTrigger = async () => {
Expand Down Expand Up @@ -53,14 +52,13 @@ const LandingSections = ({ sections }: LandingSectionsProps) => {
const sectionElements = Array.from(
container.querySelectorAll<HTMLElement>("[data-landing-section]")
);

if (sectionElements.length === 0) return;

if (prefersReducedMotion) {
sectionElements.forEach((section) => {
section
.querySelectorAll<HTMLElement>(
"[data-landing-section-text],[data-landing-section-image]"
"[data-landing-section-text-inner],[data-landing-section-image-inner]"
)
.forEach((el) => {
el.style.opacity = "1";
Expand All @@ -74,15 +72,15 @@ const LandingSections = ({ sections }: LandingSectionsProps) => {
sectionElements.forEach((section) => {
const layout = section.dataset.landingSectionLayout ?? "default";
const text = section.querySelector<HTMLElement>(
"[data-landing-section-text]"
"[data-landing-section-text-inner]"
);
const image = section.querySelector<HTMLElement>(
"[data-landing-section-image]"
"[data-landing-section-image-inner]"
);
if (!text || !image) return;

const textFromX = layout === "reverse" ? 80 : -80;
const imageFromX = layout === "reverse" ? -80 : 80;
const textFromX = layout === "reverse" ? 40 : -40;
const imageFromX = layout === "reverse" ? -40 : 40;

gsap.set(text, { opacity: 0, x: textFromX });
gsap.set(image, { opacity: 0, x: imageFromX });
Expand All @@ -93,28 +91,19 @@ const LandingSections = ({ sections }: LandingSectionsProps) => {
start: "top 80%",
end: "bottom 20%",
toggleActions: "play none none reverse",
fastScrollEnd: true,
},
});

timeline
.to(
text,
{
x: 0,
opacity: 1,
duration: 0.5,
ease: "power2.out",
},
{ x: 0, opacity: 1, duration: 0.4, ease: "power1.out" },
0
)
.to(
image,
{
x: 0,
opacity: 1,
duration: 0.5,
ease: "power2.out",
},
{ x: 0, opacity: 1, duration: 0.4, ease: "power1.out" },
0.1
);
});
Expand All @@ -134,7 +123,7 @@ const LandingSections = ({ sections }: LandingSectionsProps) => {
id="landing-sections"
ref={containerRef}
className={cn(
"flex flex-col items-center pt-16",
"flex flex-col items-center overflow-x-hidden pt-16",
"gap-12 pc:gap-24",
"tablet:scroll-mt-[70px] pc:scroll-mt-[70px]"
)}
Expand Down
6 changes: 3 additions & 3 deletions src/app/(landing)/_components/landing-floating-cta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ const LandingFloatingCTA = ({ footerId }: LandingFloatingCTAProps) => {
return (
<div
className={cn(
"pointer-events-auto fixed inset-x-0 bottom-6 z-50 px-4 transition-all duration-300",
"flex-center animate-in fade-in slide-in-from-bottom-4 duration-300",
"pointer-events-none fixed inset-x-0 bottom-6 z-50 px-4 transition-all duration-300",
"flex-center animate-in fade-in slide-in-from-bottom-4",
"pc:bottom-10 pc:justify-center pc:px-10"
)}
>
Expand All @@ -64,7 +64,7 @@ const LandingFloatingCTA = ({ footerId }: LandingFloatingCTAProps) => {
label="와인 보러가기"
scroll={true}
className={cn(
"h-[54px] w-[260px] select-none px-8",
"pointer-events-auto h-[54px] w-[260px] select-none px-8",
"tablet:w-[320px]",
"pc:h-[60px] pc:w-[260px]"
)}
Expand Down
48 changes: 27 additions & 21 deletions src/app/(landing)/_components/landing-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import Image from "next/image";
import { cn } from "@/lib/utils";
import { LandingSectionData } from "../_types";

/**
* 랜딩 페이지 기능 소개 섹션
* 애니메이션은 상위 컨테이너에서 제어
*/
const LandingSection = ({
title,
subtitle,
Expand All @@ -20,51 +16,61 @@ const LandingSection = ({
data-landing-section
data-landing-section-layout={layout}
className={cn(
"flex w-full max-w-6xl flex-col items-start gap-8",
"flex w-full max-w-6xl select-none flex-col items-start gap-8",
isReverse
? "pc:flex-row-reverse pc:items-center pc:gap-36"
: "pc:flex-row pc:items-center pc:gap-36"
)}
>
{/* 텍스트 영역 */}
<div
data-landing-section-text
className={cn(
"flex flex-col gap-4 text-left pc:flex-1",
"pl-4 pr-8",
"pc:px-0 pc:pl-4 pc:pr-8",
"tablet:pl-8 tablet:pr-8"
"tablet:pl-8 tablet:pr-8",
"overflow-hidden"
)}
>
<h2
className={cn("flex flex-col", "text-heading-lg pc:text-heading-lg")}
<div
data-landing-section-text-inner
className="flex flex-col gap-4 text-left will-change-transform"
>
{title.map((line, index) => (
<span key={index}>{line}</span>
))}
</h2>
<div className="flex flex-col text-gray-700">
{subtitle.map((line, index) => (
<span key={index}>{line}</span>
))}
<h2
className={cn(
"flex flex-col",
"text-heading-lg pc:text-heading-lg"
)}
>
{title.map((line, index) => (
<span key={index}>{line}</span>
))}
</h2>
<div className="flex flex-col text-gray-700">
{subtitle.map((line, index) => (
<span key={index}>{line}</span>
))}
</div>
</div>
</div>

{/* 이미지 영역 */}
<div
data-landing-section-image
className={cn(
"w-full pc:w-[680px]",
isReverse ? "pr-4 tablet:pr-8" : "pl-4 tablet:pl-8",
"pc:px-0"
"pc:px-0",
"overflow-hidden"
)}
>
<div className="relative aspect-[145/94] w-full overflow-hidden">
<div
data-landing-section-image-inner
className="relative aspect-[145/94] w-full overflow-hidden will-change-transform"
>
<Image
src={imgSrc}
alt={imgAlt}
fill
priority
sizes="(min-width: 1024px) 725px, 100vw"
className="object-cover"
/>
Expand Down