Skip to content

[Feat] : SD 캐릭터 PNG 적용 및 빈 상태 캐릭터 컴포넌트·애니메이션 추가 (#235)#249

Merged
GulSam00 merged 3 commits into
developfrom
feat/235-sdCharacterDecoration
Jun 6, 2026
Merged

[Feat] : SD 캐릭터 PNG 적용 및 빈 상태 캐릭터 컴포넌트·애니메이션 추가 (#235)#249
GulSam00 merged 3 commits into
developfrom
feat/235-sdCharacterDecoration

Conversation

@GulSam00

@GulSam00 GulSam00 commented Jun 6, 2026

Copy link
Copy Markdown
Owner

📌 PR 제목

[Feat] : SD 캐릭터 PNG 적용 및 빈 상태 캐릭터 컴포넌트·애니메이션 추가

📌 변경 사항

  • SD 캐릭터 에셋 교체: 기존 SVG 2종 삭제 → AI 생성 PNG 6종(pina1~6.png) 추가
  • SdCharacter 개선
    • 정적 import + placeholder="blur"로 "텍스트 먼저, 이미지 나중" 현상 해소
    • variant 6종(default/greeting/focus/joy/curious/sad)으로 확장, priority prop 추가
  • CharacterMessage 공통 컴포넌트 신규: 캐릭터 + 안내 메시지를 함께 표시. messageReactNode(여러 줄 지원), variant별 애니메이션 적용
  • 빈/로딩 상태 UI 통일
    • 검색: SearchStatus(로딩/결과없음) 신규 분리
    • tosing/SongList·recent 빈 상태를 CharacterMessage 기반으로 교체
  • 캐릭터 애니메이션 추가(globals.css)
    • default/greeting/joy → 위아래 bounce (무한)
    • sad → 좌우 shake (2회 후 정지)
    • prefers-reduced-motion 사용자는 애니메이션 비활성화 (접근성)
  • 사용처 적용: login, not-found, HomePage, SongList, recent

💬 추가 참고 사항

@vercel

vercel Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
singcode Ready Ready Preview, Comment Jun 6, 2026 2:03pm

@GulSam00

GulSam00 commented Jun 6, 2026

Copy link
Copy Markdown
Owner Author

/describe

@GulSam00

GulSam00 commented Jun 6, 2026

Copy link
Copy Markdown
Owner Author

/review

@GulSam00

GulSam00 commented Jun 6, 2026

Copy link
Copy Markdown
Owner Author

/improve

@qodo-code-review

qodo-code-review Bot commented Jun 6, 2026

Copy link
Copy Markdown

Review Summary by Qodo

(Agentic_describe updated until commit 4c9b2e4)

Add SD character PNG assets and CharacterMessage component with animations

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add 6 SD character PNG variants with bounce/shake animations
• Create CharacterMessage component for unified empty/loading states
• Replace icon-based empty states with character-based UI across app
• Add accessibility support via prefers-reduced-motion media query
Diagram
flowchart LR
  A["6 SD Character PNGs<br/>pina1-6.png"] --> B["SdCharacter Component<br/>6 variants"]
  B --> C["CharacterMessage Component<br/>Character + Message"]
  C --> D["Empty/Loading States<br/>login, search, recent, tosing"]
  E["Character Animations<br/>bounce, shake"] --> D
  F["Accessibility<br/>prefers-reduced-motion"] --> E

Loading

Grey Divider

File Changes

1. apps/web/src/globals.css ✨ Enhancement +39/-0

Add character bounce and shake animations

apps/web/src/globals.css


2. apps/web/src/components/SdCharacter.tsx ✨ Enhancement +49/-0

New SD character component with 6 variants

apps/web/src/components/SdCharacter.tsx


3. apps/web/src/components/CharacterMessage.tsx ✨ Enhancement +40/-0

New unified character message component

apps/web/src/components/CharacterMessage.tsx


View more (6)
4. apps/web/src/app/search/SearchStatus.tsx ✨ Enhancement +26/-0

New search status component with character

apps/web/src/app/search/SearchStatus.tsx


5. apps/web/src/app/search/HomePage.tsx ✨ Enhancement +4/-20

Replace icon-based search states with SearchStatus

apps/web/src/app/search/HomePage.tsx


6. apps/web/src/app/tosing/SongList.tsx ✨ Enhancement +11/-3

Replace empty state with CharacterMessage

apps/web/src/app/tosing/SongList.tsx


7. apps/web/src/app/recent/page.tsx ✨ Enhancement +12/-5

Replace empty state with CharacterMessage

apps/web/src/app/recent/page.tsx


8. apps/web/src/app/login/page.tsx Formatting +1/-1

Minor layout adjustment for header spacing

apps/web/src/app/login/page.tsx


9. apps/web/src/app/not-found.tsx Formatting +2/-2

Reduce 404 text size and adjust spacing

apps/web/src/app/not-found.tsx


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Jun 6, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (1)

Context used

Grey Divider


Action required

1. LoginPage missing SD character 📎 Requirement gap ≡ Correctness
Description
apps/web/src/app/login/page.tsx does not render the SD character component, so the
login/onboarding experience lacks the required mascot/decorative element. This fails the compliance
requirement to include the SD character on the login page.
Code

apps/web/src/app/login/page.tsx[R76-82]

  return (
    <div className="bg-background flex h-dvh flex-col justify-center px-4">
      <div className="w-full space-y-6">
-        <div className="space-y-2 text-center">
+        <div className="flex flex-col items-center gap-1">
          <h1 className="text-2xl font-bold">로그인</h1>
          <p className="text-muted-foreground text-sm">로그인해서 더 많은 서비스를 이용하세요</p>
        </div>
Evidence
PR Compliance ID 4 requires the login/onboarding page to render an SD character element. In
login/page.tsx, there is no SdCharacter/CharacterMessage import and the returned JSX only
contains the login UI (heading/form), so the SD character is not present.

Place SD character on login/onboarding page
apps/web/src/app/login/page.tsx[1-16]
apps/web/src/app/login/page.tsx[76-82]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The login page does not render any SD character element, violating the requirement to show the SD character on login/onboarding.

## Issue Context
A new `SdCharacter`/`CharacterMessage` component exists in this PR, but `apps/web/src/app/login/page.tsx` currently only renders the login heading/form without the SD character.

## Fix Focus Areas
- apps/web/src/app/login/page.tsx[1-16]
- apps/web/src/app/login/page.tsx[76-82]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Eager image preload default 🐞 Bug ➹ Performance
Description
SdCharacter defaults priority to true, and CharacterMessage doesn’t pass/allow overriding
it, so empty/loading-state characters will always be preloaded even when conditional or not
initially visible. This can waste bandwidth and compete with more important above-the-fold requests
(e.g., search status inside a scroll container).
Code

apps/web/src/components/SdCharacter.tsx[R28-46]

+export default function SdCharacter({
+  variant = 'default',
+  size = 120,
+  className = '',
+  priority = true,
+}: SdCharacterProps) {
+  const src = SD_CHARACTER_SRC[variant];
+
+  return (
+    <div className={className} aria-hidden="true">
+      <Image
+        src={src}
+        alt=""
+        width={size}
+        height={size * 1.25}
+        className="drop-shadow-md select-none"
+        draggable={false}
+        priority={priority}
+      />
Evidence
The code sets priority to true by default and forwards it to <Image>. CharacterMessage always
renders <SdCharacter ...> without a priority override, and the PR uses CharacterMessage in
empty/loading UI branches (including inside a scrollable container), making preloads likely
unnecessary.

apps/web/src/components/SdCharacter.tsx[28-46]
apps/web/src/components/CharacterMessage.tsx[21-38]
apps/web/src/app/search/HomePage.tsx[218-252]
apps/web/src/app/recent/page.tsx[88-106]
apps/web/src/app/tosing/SongList.tsx[50-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SdCharacter` sets `priority = true` by default, which makes Next/Image preload the asset. Because `CharacterMessage` renders `SdCharacter` without a `priority` prop, all `CharacterMessage` usages implicitly preload images, including empty/loading states.

## Issue Context
These components are used in conditional UI paths (empty list, empty search, etc.). Preloading is best reserved for a single above-the-fold “hero” image.

## Fix Focus Areas
- apps/web/src/components/SdCharacter.tsx[28-46]
- apps/web/src/components/CharacterMessage.tsx[21-38]
- apps/web/src/app/search/HomePage.tsx[218-252]
- apps/web/src/app/recent/page.tsx[88-106]
- apps/web/src/app/tosing/SongList.tsx[50-75]

## Suggested change
- Change `SdCharacter` default to `priority = false`.
- Add an optional `priority?: boolean` prop to `CharacterMessage` and pass it through to `SdCharacter`, so callers can opt-in where appropriate.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

3. ReactNode wrapped in p 🐞 Bug ⚙ Maintainability
Description
CharacterMessage types message as ReactNode but always wraps it in a <p>, which only
supports phrasing/inline content; future callers passing block elements (e.g. <div>, <ul>) will
create invalid HTML and unpredictable layout. Either constrain message usage to inline content or
render with a non-<p> wrapper.
Code

apps/web/src/components/CharacterMessage.tsx[R6-38]

+interface CharacterMessageProps {
+  message: ReactNode;
+  variant?: SdCharacterVariant;
+  size?: number;
+  className?: string;
+}
+
+// variant별 캐릭터 애니메이션 (지정되지 않은 variant는 정적 표시)
+const VARIANT_ANIMATION: Partial<Record<SdCharacterVariant, string>> = {
+  default: 'animate-character-bounce',
+  greeting: 'animate-character-bounce',
+  joy: 'animate-character-bounce',
+  sad: 'animate-character-shake',
+};
+
+export default function CharacterMessage({
+  message,
+  variant = 'default',
+  size = 200,
+  className = '',
+}: CharacterMessageProps) {
+  const animationClassName = VARIANT_ANIMATION[variant];
+
+  return (
+    <div
+      className={cn(
+        'text-muted-foreground flex flex-col items-center justify-center py-6',
+        className,
+      )}
+    >
+      <SdCharacter variant={variant} size={size} className={cn('mb-2', animationClassName)} />
+      <p className="m-2 text-center text-lg">{message}</p>
+    </div>
Evidence
message is declared as ReactNode, but is rendered directly within a <p>, creating a mismatch
between the permissive type and the stricter HTML content model of <p>.

apps/web/src/components/CharacterMessage.tsx[6-38]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`CharacterMessage` accepts `message: ReactNode` but renders it inside a `<p>`. This makes the component easy to misuse because `ReactNode` can include block-level elements that are invalid children of `<p>`.

## Issue Context
Current call sites pass text and `<br />` (fine), but the exported API invites richer content over time.

## Fix Focus Areas
- apps/web/src/components/CharacterMessage.tsx[6-38]

## Suggested change
Pick one:
1) Change `<p>` to `<div>` (or `<div role="text">`) to safely accept any `ReactNode`.
2) Keep `<p>` but change the prop type to something narrower (e.g., `string` or `ReactElement` constrained to phrasing content) and document the constraint.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines 76 to 82
return (
<div className="bg-background flex h-dvh flex-col justify-center px-4">
<div className="w-full space-y-6">
<div className="space-y-2 text-center">
<div className="flex flex-col items-center gap-1">
<h1 className="text-2xl font-bold">로그인</h1>
<p className="text-muted-foreground text-sm">로그인해서 더 많은 서비스를 이용하세요</p>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Loginpage missing sd character 📎 Requirement gap ≡ Correctness

apps/web/src/app/login/page.tsx does not render the SD character component, so the
login/onboarding experience lacks the required mascot/decorative element. This fails the compliance
requirement to include the SD character on the login page.
Agent Prompt
## Issue description
The login page does not render any SD character element, violating the requirement to show the SD character on login/onboarding.

## Issue Context
A new `SdCharacter`/`CharacterMessage` component exists in this PR, but `apps/web/src/app/login/page.tsx` currently only renders the login heading/form without the SD character.

## Fix Focus Areas
- apps/web/src/app/login/page.tsx[1-16]
- apps/web/src/app/login/page.tsx[76-82]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@GulSam00 GulSam00 merged commit 57429fa into develop Jun 6, 2026
2 checks passed
@GulSam00 GulSam00 deleted the feat/235-sdCharacterDecoration branch June 6, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI 미소녀 SD 캐릭터 배치로 서브컬처 도메인 특징 강조

1 participant