Skip to content

Commit b09e90b

Browse files
authored
Merge pull request #241 from FE9-2/design/landing-fix
design: ๋žœ๋”ฉํŽ˜์ด์ง€ ์ˆ˜์ •
2 parents 36e0f10 + 5729d74 commit b09e90b

File tree

6 files changed

+149
-98
lines changed

6 files changed

+149
-98
lines changed

โ€Žpublic/favicon.icoโ€Ž

1.75 KB
Binary file not shown.

โ€Žpublic/slogan.pngโ€Ž

-90.8 KB
Binary file not shown.

โ€Žpublic/testlogo.pngโ€Ž

-35.7 KB
Binary file not shown.

โ€Žpublic/text_logo.pngโ€Ž

-106 KB
Binary file not shown.

โ€Žsrc/app/(home)/page.tsxโ€Ž

Lines changed: 148 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,20 @@ const bounceAnimation = {
6060
},
6161
};
6262

63+
const backgroundVariants = {
64+
initial: {
65+
backgroundColor: "#1a1a1a",
66+
},
67+
animate: {
68+
backgroundColor: "#2a2a2a",
69+
transition: {
70+
duration: 20,
71+
repeat: Infinity,
72+
repeatType: "reverse" as const,
73+
},
74+
},
75+
};
76+
6377
export default function LandingPage() {
6478
const isLargeScreen = useMediaQuery({ minWidth: 641 });
6579
const [currentSlide, setCurrentSlide] = useState(0);
@@ -71,12 +85,12 @@ export default function LandingPage() {
7185
useEffect(() => {
7286
setIsLoaded(true);
7387
lenisRef.current = new Lenis({
74-
duration: 0.8, // 1.2์—์„œ 0.8๋กœ ๋ณ€๊ฒฝ
75-
easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
88+
duration: 1.2,
89+
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
7690
smoothWheel: true,
7791
wheelMultiplier: 2,
78-
touchMultiplier: 1.2,
79-
infinite: false,
92+
touchMultiplier: 2,
93+
infinite: true,
8094
});
8195

8296
function raf(time: number) {
@@ -87,36 +101,38 @@ export default function LandingPage() {
87101
requestAnimationFrame(raf);
88102

89103
let lastScrollTime = 0;
90-
const scrollThreshold = 500; // ms
104+
const scrollThreshold = 150;
91105

92106
lenisRef.current.on("scroll", ({ progress }: { progress: number }) => {
93107
const currentTime = Date.now();
94108
if (currentTime - lastScrollTime < scrollThreshold) return;
95109

96110
if (!isScrollingRef.current) {
97111
const totalSlides = slides.length;
98-
const newSlideIndex = Math.min(slides.length - 1, Math.max(0, Math.round(progress * (totalSlides - 1))));
112+
const progressPerSlide = 1 / (totalSlides - 1);
113+
const currentProgress = progress / progressPerSlide;
114+
let newSlideIndex = Math.round(currentProgress);
115+
116+
if (progress >= 0.99) {
117+
newSlideIndex = 0;
118+
setTimeout(() => {
119+
lenisRef.current?.scrollTo(0, {
120+
duration: 1.2,
121+
easing: (t) => t * (2 - t),
122+
});
123+
}, 100);
124+
}
99125

100126
if (newSlideIndex !== currentSlide) {
101127
setCurrentSlide(newSlideIndex);
102128
isScrollingRef.current = true;
103-
const targetScroll =
104-
(newSlideIndex / (totalSlides - 1)) *
105-
(isLargeScreen ? containerRef.current!.scrollHeight : containerRef.current!.scrollWidth);
106-
107-
lenisRef.current?.scrollTo(targetScroll, {
108-
immediate: false,
109-
duration: 600, // 800์—์„œ 600์œผ๋กœ ๋ณ€๊ฒฝ
110-
easing: (t: number) => t * (2 - t),
111-
});
112-
113-
lastScrollTime = currentTime;
114129

115130
setTimeout(() => {
116131
isScrollingRef.current = false;
117-
}, 600); // 800์—์„œ 600์œผ๋กœ ๋ณ€๊ฒฝ
132+
}, 200);
118133
}
119134
}
135+
lastScrollTime = currentTime;
120136
});
121137

122138
document.documentElement.style.scrollbarWidth = "none";
@@ -143,34 +159,41 @@ export default function LandingPage() {
143159
<AnimatePresence>
144160
{isLoaded && (
145161
<motion.div
146-
initial={{ opacity: 0 }}
147-
animate={{ opacity: 1 }}
162+
variants={backgroundVariants}
163+
initial="initial"
164+
animate="animate"
148165
exit={{ opacity: 0 }}
149166
transition={{ duration: 1 }}
150167
ref={containerRef}
151-
className={`h-[400vh] min-h-[768px] overflow-hidden bg-gradient-to-br from-[#1a1a1a] to-[#2a2a2a] ${
152-
isLargeScreen ? "" : "flex flex-col"
153-
}`}
168+
className={`relative h-[400vh] min-h-[768px] overflow-hidden ${isLargeScreen ? "" : "flex flex-col"}`}
154169
>
155-
<div className={`fixed inset-0 ${isLargeScreen ? "flex" : "flex flex-col"}`}>
170+
<div className="absolute inset-0 opacity-20">
171+
<div className="particles-container" />
172+
</div>
173+
174+
<motion.div
175+
className={`fixed inset-0 ${isLargeScreen ? "flex" : "flex flex-col"}`}
176+
style={{
177+
backdropFilter: "blur(8px)",
178+
WebkitBackdropFilter: "blur(8px)",
179+
}}
180+
>
156181
<motion.div
157-
className={`relative ${isLargeScreen ? "w-1/2" : "flex h-1/2 w-full items-center justify-center overflow-hidden"}`}
182+
className={`relative ${
183+
isLargeScreen ? "w-1/2" : "flex h-1/2 w-full items-center justify-center overflow-hidden"
184+
}`}
158185
animate={{
159186
width: currentSlide === 0 ? "100%" : isLargeScreen ? "50%" : "100%",
160187
height: currentSlide === 0 ? "100%" : isLargeScreen ? "100%" : "50%",
161188
}}
162189
transition={{ duration: 0.8, ease: "easeInOut" }}
163190
>
164191
<motion.div
165-
className="absolute inset-0 flex items-center justify-center"
166-
initial={{ opacity: 0 }}
192+
className="relative flex h-full w-full items-center justify-center"
167193
animate={{
168-
opacity: 1,
169-
}}
170-
transition={{
171-
duration: 0.8, // Updated transition duration
172-
ease: "easeInOut",
194+
scale: currentSlide === 0 ? 1 : 0.8,
173195
}}
196+
transition={{ duration: 0.8, ease: "easeInOut" }}
174197
>
175198
{currentSlide === 0 ? (
176199
<Image
@@ -179,6 +202,7 @@ export default function LandingPage() {
179202
width={800}
180203
height={800}
181204
className="h-full max-h-[800px] w-full max-w-[800px] object-contain"
205+
priority
182206
/>
183207
) : currentSlide === 4 || currentSlide === 5 ? (
184208
<motion.div
@@ -187,20 +211,20 @@ export default function LandingPage() {
187211
initial={{ opacity: 0, y: 20 }}
188212
animate={{ opacity: 1, y: 0 }}
189213
exit={{ opacity: 0, y: -20 }}
190-
transition={{ duration: 1.2, ease: "easeInOut" }} // Update 1
214+
transition={{ duration: 1.2, ease: "easeInOut" }}
191215
>
192216
<motion.h2
193-
className="mb-2 mt-0 text-center text-xl font-semibold text-gray-100 max-[640px]:mb-1 max-[640px]:px-4 md:mb-4 md:mt-0 md:text-3xl"
217+
className="mb-2 mt-0 text-center text-xl font-semibold text-gray-100 drop-shadow-[0_2px_2px_rgba(0,0,0,0.3)] max-[640px]:mb-1 max-[640px]:px-4 md:mb-4 md:mt-0 md:text-3xl"
194218
initial={{ opacity: 0, y: 20 }}
195219
animate={{ opacity: 1, y: 0 }}
196-
transition={{ delay: 0.3, duration: 0.6 }} // Update 2
220+
transition={{ delay: 0.3, duration: 0.6 }}
197221
>
198222
{slides[currentSlide].blackAreaTitle}
199223
</motion.h2>
200224
<motion.div
201225
initial={{ opacity: 0, y: 20 }}
202226
animate={{ opacity: 1, y: 0 }}
203-
transition={{ delay: 0.4, duration: 0.6 }} // Update 2
227+
transition={{ delay: 0.4, duration: 0.6 }}
204228
className="mb-2 w-full max-w-[600px] max-[640px]:max-w-[75%] max-[640px]:px-4 md:mb-4"
205229
style={{ maxHeight: "calc(100% - 12rem)" }}
206230
>
@@ -221,28 +245,27 @@ export default function LandingPage() {
221245
className="mb-0 max-w-[600px] whitespace-pre-wrap text-center text-sm text-gray-200 max-[640px]:mt-1 max-[640px]:px-4 md:text-xl"
222246
initial={{ opacity: 0, y: 20 }}
223247
animate={{ opacity: 1, y: 0 }}
224-
transition={{ delay: 0.5, duration: 0.6 }} // Update 2
248+
transition={{ delay: 0.5, duration: 0.6 }}
225249
>
226250
{slides[currentSlide].blackAreaContent}
227251
</motion.p>
228252
</motion.div>
229253
) : (
230254
<motion.div
231-
className="absolute inset-0 flex items-center justify-center"
255+
className="relative h-full max-h-[600px] w-full max-w-[600px]"
232256
initial={{ opacity: 0 }}
233257
animate={{ opacity: 1 }}
234258
exit={{ opacity: 0 }}
235-
transition={{ duration: 0.8 }} // Update 3
259+
transition={{ duration: 0.8 }}
236260
>
237-
<div className="relative h-full max-h-[600px] w-full max-w-[600px]">
238-
<Image
239-
src="/brand.png"
240-
alt="Brand Logo"
241-
fill
242-
className="object-contain"
243-
sizes="(max-width: 600px) 100vw, 600px"
244-
/>
245-
</div>
261+
<Image
262+
src="/brand.png"
263+
alt="Brand Logo"
264+
fill
265+
className="object-contain"
266+
sizes="(max-width: 600px) 100vw, 600px"
267+
priority
268+
/>
246269
</motion.div>
247270
)}
248271
</motion.div>
@@ -267,75 +290,103 @@ export default function LandingPage() {
267290
<AnimatePresence mode="wait">
268291
{currentSlide > 0 && (
269292
<motion.div
270-
key={currentSlide}
271-
className={`relative z-40 flex ${
272-
isLargeScreen ? "w-1/2" : "h-1/2 w-full"
273-
} flex-col items-center justify-center p-4 pb-6 pt-4 max-[640px]:px-12 max-[640px]:py-3 md:p-6 md:pb-8 md:pt-6`}
293+
className={`relative z-40 flex ${isLargeScreen ? "w-1/2" : "h-1/2 w-full"}`}
274294
style={{
275295
background: "linear-gradient(135deg, #71db77 0%, #56c45d 100%)",
276296
display: "flex",
277297
flexDirection: "column",
278298
justifyContent: "center",
279299
alignItems: "center",
280300
height: isLargeScreen ? "100%" : "50%",
301+
overflow: "hidden",
281302
}}
282-
initial={{ opacity: 0, [isLargeScreen ? "y" : "x"]: isLargeScreen ? "100%" : "100%" }}
283-
animate={{ opacity: 1, [isLargeScreen ? "y" : "x"]: 0 }}
284-
exit={{ opacity: 0, [isLargeScreen ? "y" : "x"]: isLargeScreen ? "-100%" : "-100%" }}
285-
transition={{ duration: 0.4, ease: "easeInOut" }} // Updated transition duration
303+
initial={{ width: 0 }}
304+
animate={{ width: isLargeScreen ? "50%" : "100%" }}
305+
transition={{ duration: 0.8, ease: "easeInOut" }}
286306
>
287-
<motion.h2
288-
className="mb-2 mt-0 text-center text-xl font-semibold text-[#1a1a1a] max-[640px]:mb-1 max-[640px]:px-4 md:mb-4 md:mt-0 md:text-3xl"
289-
initial={{ opacity: 0, y: 20 }}
290-
animate={{ opacity: 1, y: 0 }}
291-
transition={{ delay: 0.05, duration: 0.3 }} // Updated transition
292-
>
293-
{slides[currentSlide].title}
294-
</motion.h2>
295-
<motion.div
296-
initial={{ opacity: 0, y: 20 }}
297-
animate={{ opacity: 1, y: 0 }}
298-
transition={{ delay: 0.1, duration: 0.3 }} // Updated transition
299-
className="mb-2 w-full max-w-[600px] max-[640px]:max-w-[75%] max-[640px]:px-4 md:mb-4"
300-
style={{ maxHeight: "calc(100% - 12rem)" }}
301-
>
302-
<div
303-
className="relative w-full overflow-hidden rounded-lg shadow-lg"
304-
style={{ paddingBottom: "56.25%" }}
307+
<AnimatePresence mode="wait">
308+
<motion.div
309+
key={currentSlide}
310+
className="flex h-full w-full flex-col items-center justify-center p-4 pb-6 pt-4 max-[640px]:px-12 max-[640px]:py-3 md:p-6 md:pb-8 md:pt-6"
311+
initial={{ y: "100%" }}
312+
animate={{ y: 0 }}
313+
exit={{ y: "-100%" }}
314+
transition={{ duration: 0.4, ease: "easeInOut" }}
305315
>
306-
<Image
307-
src={slides[currentSlide].image || ""}
308-
alt={slides[currentSlide].title || ""}
309-
fill
310-
style={{ objectFit: "cover" }}
311-
sizes="(max-width: 768px) 100vw, 600px"
312-
/>
313-
</div>
314-
</motion.div>
315-
<motion.p
316-
className="mb-0 max-w-[600px] whitespace-pre-wrap text-center text-sm text-[#1a1a1a] max-[640px]:mt-1 max-[640px]:px-4 md:text-xl"
317-
initial={{ opacity: 0, y: 20 }}
318-
animate={{ opacity: 1, y: 0 }}
319-
transition={{ delay: 0.15, duration: 0.3 }} // Updated transition
320-
>
321-
{slides[currentSlide].content}
322-
</motion.p>
316+
<motion.h2
317+
className="mb-2 mt-0 text-center text-xl font-semibold text-[#1a1a1a] max-[640px]:mb-1 max-[640px]:px-4 md:mb-4 md:mt-0 md:text-3xl"
318+
initial={{ opacity: 0, y: 20 }}
319+
animate={{ opacity: 1, y: 0 }}
320+
transition={{ delay: 0.05, duration: 0.3 }}
321+
>
322+
{slides[currentSlide].title}
323+
</motion.h2>
324+
<motion.div
325+
initial={{ opacity: 0, y: 20 }}
326+
animate={{ opacity: 1, y: 0 }}
327+
transition={{ delay: 0.1, duration: 0.3 }}
328+
className="mb-2 w-full max-w-[600px] max-[640px]:max-w-[75%] max-[640px]:px-4 md:mb-4"
329+
style={{ maxHeight: "calc(100% - 12rem)" }}
330+
>
331+
<div
332+
className="relative w-full overflow-hidden rounded-lg shadow-lg transition-shadow duration-300 hover:shadow-2xl"
333+
style={{ paddingBottom: "56.25%" }}
334+
>
335+
<Image
336+
src={slides[currentSlide].image || ""}
337+
alt={slides[currentSlide].title || ""}
338+
fill
339+
style={{ objectFit: "cover" }}
340+
sizes="(max-width: 768px) 100vw, 600px"
341+
className="transition-transform duration-300 hover:scale-105"
342+
/>
343+
</div>
344+
</motion.div>
345+
<motion.p
346+
className="mb-0 max-w-[600px] whitespace-pre-wrap text-center text-sm text-[#1a1a1a] max-[640px]:mt-1 max-[640px]:px-4 md:text-xl"
347+
initial={{ opacity: 0, y: 20 }}
348+
animate={{ opacity: 1, y: 0 }}
349+
transition={{ delay: 0.15, duration: 0.3 }}
350+
>
351+
{slides[currentSlide].content}
352+
</motion.p>
353+
</motion.div>
354+
</AnimatePresence>
323355
</motion.div>
324356
)}
325357
</AnimatePresence>
326-
</div>
358+
</motion.div>
327359

328360
{currentSlide > 0 && (
329-
<div
330-
className={`fixed ${isLargeScreen ? "right-4 top-1/2 -translate-y-1/2 space-y-2" : "bottom-4 left-1/2 flex -translate-x-1/2 space-x-2"}`}
361+
<motion.div
362+
className={`fixed ${
363+
isLargeScreen
364+
? "right-8 top-1/2 -translate-y-1/2 space-y-3"
365+
: "bottom-8 left-1/2 flex -translate-x-1/2 space-x-3"
366+
}`}
331367
>
332368
{slides.slice(1).map((_, index) => (
333-
<div
369+
<motion.div
334370
key={index + 1}
335-
className={`h-4 w-4 rounded-full ${index + 1 === currentSlide ? "bg-[#108b2d]" : "bg-[#f8fff8]"}`}
371+
className="h-3 w-3 cursor-pointer rounded-full border-2 border-white/50"
372+
whileHover={{ scale: 1.2 }}
373+
animate={{
374+
backgroundColor: index + 1 === currentSlide ? "#108b2d" : "transparent",
375+
scale: index + 1 === currentSlide ? 1.2 : 1,
376+
}}
377+
onClick={() => {
378+
if (!isScrollingRef.current) {
379+
const targetScroll =
380+
((index + 1) / (slides.length - 1)) * (containerRef.current?.scrollHeight || 0);
381+
lenisRef.current?.scrollTo(targetScroll, {
382+
duration: 1.2,
383+
easing: (t) => t * (2 - t),
384+
});
385+
}
386+
}}
336387
/>
337388
))}
338-
</div>
389+
</motion.div>
339390
)}
340391
</motion.div>
341392
)}

โ€Žsrc/app/(pages)/(workform)/addform/section/RecruitContentSection.tsxโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22
import BaseInput from "@/app/components/input/text/BaseInput";
33
import BaseTextArea from "@/app/components/input/textarea/BaseTextArea";
4-
import ImageInput from "@/app/components/input/file/ImageInput/ImageInput";
54
import DatePickerInput from "@/app/components/input/dateTimeDaypicker/DatePickerInput";
65
import { cn } from "@/lib/tailwindUtil";
76
import { useFormContext } from "react-hook-form";
@@ -12,6 +11,7 @@ import useUploadImages from "@/hooks/queries/user/me/useImageUpload";
1211
import { formatToLocaleDate } from "@/utils/formatters";
1312
import DotLoadingSpinner from "@/app/components/loading-spinner/DotLoadingSpinner";
1413
import { isDirty } from "zod";
14+
import ImageInput from "@/app/components/input/file/ImageInput/ImageInput";
1515

1616
// ์›Œํฌํผ ๋งŒ๋“ค๊ธฐ - ์‚ฌ์žฅ๋‹˜ - 1-๋ชจ์ง‘๋‚ด์šฉ
1717

0 commit comments

Comments
ย (0)