-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat/404-48] ✨ feat: nofound 페이지 구현 & wipCard 추가 (준비중 안내) #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,18 @@ | ||
| "use client"; | ||
|
|
||
| import Image from "next/image"; | ||
|
|
||
| export default function HeroRightMedia() { | ||
| return ( | ||
| <div className="flex-1 hidden md:block"> | ||
| <div className="relative mx-auto aspect-4/3 bg-foreground/20 max-w-lg w-full overflow-hidden rounded-3xl border"> | ||
| {/* 배경 효과 (리퀴드 글래스, 글로우 등은 여기서 스타일링) */} | ||
| <div className="absolute inset-0" aria-hidden /> | ||
| <div className="relative h-full w-full"> | ||
| </div> | ||
| </div> | ||
| <Image | ||
| src="/error/elephant.svg" | ||
| alt="임시" | ||
| width={40} | ||
| height={120} | ||
| className="w-full h-auto select-none drop-shadow-[10px_5px_3px_rgba(0,0,0,0.10)]" | ||
| priority={false} | ||
| /> | ||
|
Comment on lines
+8
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: find public -name "*.svg" -o -name "elephant.svg" -o -name "wip-card.svg" 2>/dev/null | head -20Repository: swallowedB/b-log Length of output: 332 🏁 Script executed: cat -n src/app/\(layout\)/\(shell\)/_components/home/HeroRightMedia.tsxRepository: swallowedB/b-log Length of output: 578 🏁 Script executed: git log --oneline -5 -- src/app/\(layout\)/\(shell\)/_components/home/HeroRightMedia.tsx 2>/dev/null || echo "No git history available"Repository: swallowedB/b-log Length of output: 89 🏁 Script executed: git diff HEAD~1 HEAD -- public/ 2>/dev/null | grep -E "elephant|wip-card" || echo "No recent changes to public/ found"Repository: swallowedB/b-log Length of output: 94 alt 텍스트 개선이 필요합니다 이미지 경로와 파일은 정상적으로 존재하는데, 몇 가지 지점이 있습니다:
🤖 Prompt for AI Agents |
||
| </div> | ||
| ) | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import { SpaceBackground } from "@/components/common/SpaceBackground"; | ||
| import Image from "next/image"; | ||
| import Link from "next/link"; | ||
|
|
||
| export default function NotFound() { | ||
| return ( | ||
| <section className="relative flex flex-col items-center justify-center min-h-screen w-full overflow-hidden px-6"> | ||
| <SpaceBackground /> | ||
|
|
||
| <div className="flex flex-col items-center gap-5 h-full mb-10"> | ||
| <h1> | ||
| <Image | ||
| src="/error/404.svg" | ||
| alt="404" | ||
| width={300} | ||
| height={150} | ||
| priority | ||
| /> | ||
| </h1> | ||
|
|
||
| <Image src="/error/oops.svg" alt="oops" width={220} height={80} /> | ||
|
|
||
| <Image | ||
| className="w-10 aspect-auto" | ||
| src="/error/double-arrow-icon.svg" | ||
| alt="" | ||
| width={40} | ||
| height={40} | ||
| /> | ||
| </div> | ||
|
|
||
| <p className="text-center font-sans text-white/75 font-medium leading-relaxed max-w-[420px]"> | ||
| 보아뱀이 잘못된 페이지를 삼켜버렸어요. | ||
| </p> | ||
| <p className="text-center font-sans text-sm text-white/55 font-medium leading-relaxed max-w-[420px]"> | ||
| 찾으려던 글은 아직 소화되지 않았거나, 존재하지 않는 페이지예요. | ||
| </p> | ||
|
|
||
| <Link | ||
| href="/" | ||
| className="mt-8 inline-flex items-center gap-2 rounded-full border border-white/20 bg-white/5 px-5 py-2 text-sm font-medium text-white/90 backdrop-blur-md transition hover:bg-white/15 hover:border-white/40" | ||
| > | ||
| <span>홈으로 돌아가기</span> | ||
| </Link> | ||
| </section> | ||
| ); | ||
| } | ||
|
Comment on lines
5
to
47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # 프로젝트 구조 확인
git ls-files | head -20Repository: swallowedB/b-log Length of output: 522 🏁 Script executed: # shimmer-text 클래스 검색
rg -n "shimmer-text" --type css --type scssRepository: swallowedB/b-log Length of output: 88 🏁 Script executed: # globals 또는 global 스타일 파일 찾기
fd -e css -e scss | grep -i "global\|style"Repository: swallowedB/b-log Length of output: 333 🏁 Script executed: # app 디렉토리 구조 확인
fd -t f . src/app -type f | head -30Repository: swallowedB/b-log Length of output: 230 🏁 Script executed: # shimmer-text 클래스를 모든 CSS 파일에서 검색
rg "shimmer-text" src/ --type cssRepository: swallowedB/b-log Length of output: 42 🏁 Script executed: # not-found.tsx 파일 내용 확인
cat -n src/app/not-found.tsxRepository: swallowedB/b-log Length of output: 1878 🏁 Script executed: # 루트 레이아웃 확인
cat -n src/app/layout.tsx | head -50Repository: swallowedB/b-log Length of output: 1614 🏁 Script executed: # shimmer-text를 모든 파일에서 검색 (CSS가 아닌 다른 형식일 수도 있음)
rg "shimmer-text" src/Repository: swallowedB/b-log Length of output: 337 🏁 Script executed: # globals.css 전체 내용 확인
cat -n src/app/globals.cssRepository: swallowedB/b-log Length of output: 1584 🏁 Script executed: # tailwind config 파일 확인
fd -e config.ts -e config.js | grep -i tailwindRepository: swallowedB/b-log Length of output: 78 🏁 Script executed: # tailwind.config.ts 또는 tailwind.config.js 확인
cat -n tailwind.config.* 2>/dev/null || echo "No tailwind config found"Repository: swallowedB/b-log Length of output: 409 🏁 Script executed: # 다른 CSS 파일들도 확인 - shimmer-text가 정의되어 있을 수 있음
cat -n src/styles/components/*.cssRepository: swallowedB/b-log Length of output: 10898 🏁 Script executed: # 나머지 CSS 파일 검색
cat -n src/styles/tokens.cssRepository: swallowedB/b-log Length of output: 1012 🏁 Script executed: # MDX 스타일 확인
cat -n src/styles/mdx.cssRepository: swallowedB/b-log Length of output: 3515 🏁 Script executed: # 유틸리티 CSS 파일들 확인
cat -n src/styles/utilities/*.cssRepository: swallowedB/b-log Length of output: 3487 🏁 Script executed: # 전체 repo에서 shimmer 검색
rg "shimmer" --type cssRepository: swallowedB/b-log Length of output: 42
🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| "use client"; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial
이 컴포넌트는 hooks, state, event handlers를 사용하지 않는 순수 프레젠테이셔널 컴포넌트입니다. CSS 애니메이션은 서버 컴포넌트에서도 동작하므로, 현재 구현에 문제는 없지만, 서버 컴포넌트로 변환하면 번들 사이즈를 줄일 수 있습니다. 🤖 Prompt for AI Agents |
||
|
|
||
| import clsx from "clsx"; | ||
|
|
||
| interface SpaceBackgroundProps { | ||
| className?: string; | ||
| } | ||
|
|
||
| export function SpaceBackground({ className }: SpaceBackgroundProps) { | ||
| return ( | ||
| <div | ||
| className={clsx( | ||
| "absolute inset-0 -z-20 overflow-hidden space-bg-gradient", | ||
| className | ||
| )} | ||
| > | ||
| {/* 작은 별 배경 레이어 */} | ||
| <div className="space-bg-stars" /> | ||
|
|
||
| {/* 별똥별들 */} | ||
| <div className="pointer-events-none absolute inset-0 -z-10"> | ||
| <div className="shooting-star shooting-star--1" /> | ||
| <div className="shooting-star shooting-star--2" /> | ||
| <div className="shooting-star shooting-star--3" /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,44 @@ | ||||||||||||||||||||
| "use client"; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| import clsx from "clsx"; | ||||||||||||||||||||
| import { X } from "lucide-react"; | ||||||||||||||||||||
| import Image from "next/image"; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| interface WipFeatureCardProps { | ||||||||||||||||||||
| onClose: () => void; | ||||||||||||||||||||
| className?: string; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| export function WipFeatureCard({ onClose, className }: WipFeatureCardProps) { | ||||||||||||||||||||
| return ( | ||||||||||||||||||||
| <div | ||||||||||||||||||||
| className={clsx("relative w-[min(440px,90vw)]", className)} | ||||||||||||||||||||
| onClick={(e) => e.stopPropagation()} | ||||||||||||||||||||
| > | ||||||||||||||||||||
|
Comment on lines
+14
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 이벤트 전파 방지용 정적 분석에서 지적된 대로, ♻️ 접근성 속성 추가 제안 <div
className={clsx("relative w-[min(440px,90vw)]", className)}
onClick={(e) => e.stopPropagation()}
+ role="presentation"
>📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (2.1.2)[error] 14-17: Static Elements should not be interactive. To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value. (lint/a11y/noStaticElementInteractions) [error] 14-17: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event. Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation. (lint/a11y/useKeyWithClickEvents) 🤖 Prompt for AI Agents |
||||||||||||||||||||
| <button | ||||||||||||||||||||
| type="button" | ||||||||||||||||||||
| onClick={onClose} | ||||||||||||||||||||
| aria-label="준비중 안내 닫기" | ||||||||||||||||||||
| className={clsx( | ||||||||||||||||||||
| "absolute right-8 top-2 z-10 ", | ||||||||||||||||||||
| "inline-flex items-center justify-center", | ||||||||||||||||||||
| "h-7 w-7 rounded-full", | ||||||||||||||||||||
| "text-black/20 hover:text-white", | ||||||||||||||||||||
| "hover:bg-black/10 cursor-pointer", | ||||||||||||||||||||
| "transition rotate-80 " | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# rotate-80 클래스 정의 확인
echo "=== 1. CSS 파일에서 rotate-80 검색 ==="
rg -n "rotate-80" --type css 2>/dev/null || echo "No CSS matches found"
echo -e "\n=== 2. tailwind.config 파일에서 rotate 관련 설정 검색 ==="
fd "tailwind.config" -x cat {} \;
echo -e "\n=== 3. 전체 프로젝트에서 rotate-80 검색 ==="
rg -n "rotate-80" 2>/dev/null || echo "No matches found"
echo -e "\n=== 4. 프로젝트 구조 확인 ==="
ls -la | grep -E "tailwind|css"
find . -maxdepth 2 -name "*.config.*" -o -name "tailwind*" 2>/dev/nullRepository: swallowedB/b-log Length of output: 820 🏁 Script executed: #!/bin/bash
# WipFeatureCard.tsx에서 rotate-80이 사용된 컨텍스트 확인
sed -n '20,35p' src/components/common/WipFeatureCard.tsxRepository: swallowedB/b-log Length of output: 517
🤖 Prompt for AI Agents |
||||||||||||||||||||
| )} | ||||||||||||||||||||
| > | ||||||||||||||||||||
| <X size={16} strokeWidth={3} /> | ||||||||||||||||||||
| </button> | ||||||||||||||||||||
|
|
||||||||||||||||||||
| <Image | ||||||||||||||||||||
| src="/error/wip-card.svg" | ||||||||||||||||||||
| alt="준비 중 안내 카드" | ||||||||||||||||||||
| width={740} | ||||||||||||||||||||
| height={420} | ||||||||||||||||||||
| className="w-full h-auto select-none drop-shadow-[10px_5px_3px_rgba(0,0,0,0.10)]" | ||||||||||||||||||||
| priority={false} | ||||||||||||||||||||
| /> | ||||||||||||||||||||
| </div> | ||||||||||||||||||||
| ); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,51 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "use client"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { AnimatePresence, motion } from "framer-motion"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { createPortal } from "react-dom"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { WipFeatureCard } from "./WipFeatureCard"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface WipFeatureOverlayProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isOpen: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClose: () => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function WipFeatureOverlay({ isOpen, onClose }: WipFeatureOverlayProps) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof document === "undefined") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 하이드레이션 불일치 가능성
♻️ 권장 수정안+"use client";
+
+import { useEffect, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { createPortal } from "react-dom";
import { WipFeatureCard } from "./WipFeatureCard";
interface WipFeatureOverlayProps {
isOpen: boolean;
onClose: () => void;
}
export function WipFeatureOverlay({ isOpen, onClose }: WipFeatureOverlayProps) {
- if (typeof document === "undefined") {
- return null;
- }
+ const [mounted, setMounted] = useState(false);
+
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ if (!mounted) {
+ return null;
+ }
return createPortal(📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return createPortal( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <AnimatePresence> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {isOpen && ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className="fixed inset-0 z-60 flex items-center justify-center" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={onClose} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+20
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 접근성 개선 필요 (키보드 이벤트 및 ARIA 속성) 정적 분석에서 지적한 대로, 백드롭 🔧 접근성 개선 코드+import { useEffect, useState, useCallback } from "react"; export function WipFeatureOverlay({ isOpen, onClose }: WipFeatureOverlayProps) {
+ const handleKeyDown = useCallback(
+ (e: KeyboardEvent) => {
+ if (e.key === "Escape") {
+ onClose();
+ }
+ },
+ [onClose]
+ );
+
+ useEffect(() => {
+ if (isOpen) {
+ document.addEventListener("keydown", handleKeyDown);
+ return () => document.removeEventListener("keydown", handleKeyDown);
+ }
+ }, [isOpen, handleKeyDown]);백드롭 div에 role과 aria 속성 추가: <div
- className="fixed inset-0 z-60 flex items-center justify-center"
- onClick={onClose}
+ role="dialog"
+ aria-modal="true"
+ aria-label="준비중 기능 안내"
+ className="fixed inset-0 z-60 flex items-center justify-center bg-black/30"
+ onClick={onClose}
+ onKeyDown={(e) => e.key === "Escape" && onClose()}
>🧰 Tools🪛 Biome (2.1.2)[error] 20-23: Static Elements should not be interactive. To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value. (lint/a11y/noStaticElementInteractions) [error] 20-23: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event. Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation. (lint/a11y/useKeyWithClickEvents) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <motion.div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| key="wip-notice" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initial={{ opacity: 0, x: "100%" }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animate={{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| opacity: 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x: "0%", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| transition: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| duration: 0.4, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ease: [0.22, 1, 0.36, 1], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit={{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| opacity: 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x: "-100%", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| transition: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| duration: 0.35, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ease: [0.45, 0, 0.55, 1], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <WipFeatureCard onClose={onClose} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </motion.div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </AnimatePresence>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| document.body | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
매직 스트링 사용에 대한 우려
item.label === "PHOTOBOOTH"문자열 비교는 라벨이 변경될 경우 조용히 실패할 수 있습니다. WIP 상태를 dock item 설정에 명시적으로 추가하는 것이 더 안전합니다.♻️ 개선 제안
DOCK_ITEMS설정에isWip?: boolean속성을 추가:🤖 Prompt for AI Agents