Skip to content

feat(home): Followers bubble UI with People/Followers tab#55

Open
chaaerim wants to merge 25 commits intomainfrom
feat/follower-bubble
Open

feat(home): Followers bubble UI with People/Followers tab#55
chaaerim wants to merge 25 commits intomainfrom
feat/follower-bubble

Conversation

@chaaerim
Copy link
Copy Markdown
Member

@chaaerim chaaerim commented Apr 15, 2026

Summary

  • GitHub API에서 hamsurang organization의 followers 목록을 가져와 circle-packing bubble UI로 표시
  • 기존 People 섹션을 People/Followers 탭 구조로 변경 (GitHub 레포 탭 스타일)
  • People 탭: 기존 멤버 아바타 그리드 + "show more information" 팝오버 유지
  • Followers 탭: 원형 clip-path 버블 UI + "Follow Us" CTA 버튼

Bubble UI 상세

  • 6단계 크기 tier (46/36/28/22/16/10px) circle-packing 알고리즘
  • Featured followers (yejineee, jcha0713) 2명은 항상 큰 버블로 고정 표시
  • 나머지 28명은 페이지 로드마다 랜덤 셔플
  • Featured user가 팔로우를 취소한 경우 랜덤 팔로워로 자동 대체
  • 원형 컨테이너 (clip-path: circle(50%))로 밀집감 있는 레이아웃

파일 구조

  • Followers/circle-pack.ts — 6단계 크기 + featured 지원 packing 알고리즘
  • Followers/FollowersBubble.tsx — 원형 클라이언트 버블 컴포넌트
  • Followers/Followers.constants.ts — featured followers 상수
  • PeopleFollowersTabs/PeopleFollowersTabs.tsx — 탭 전환 클라이언트 컴포넌트
  • PeopleFollowersTabs/PeopleFollowersSection.tsx — 서버 래퍼 컴포넌트

Test plan

  • circle-pack 알고리즘 단위 테스트 (54개 전체 통과)
  • People 탭 기본 활성 확인, 멤버 아바타 클릭 시 프로필 이동
  • Followers 탭 클릭 시 버블 UI 렌더링 확인
  • Featured followers가 항상 큰 버블로 표시되는지 확인
  • 페이지 새로고침 시 비-featured 팔로워 순서 랜덤 변경 확인
  • "Follow Us" 버튼 클릭 시 GitHub 페이지 이동
  • 모바일 반응형 확인

스크린샷

데스크탑

image

모바일

image

🤖 Generated with Claude Code

chaaerim and others added 25 commits April 14, 2026 00:30
Implements getFollowers() with server-only guard, 1-hour revalidation, and graceful error handling. Includes TDD tests covering success and failure cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… issue

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ports

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace separate People and Followers sections with unified tabbed section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The tab component belongs in the left sidebar (aside), not the main content area.
Layout.tsx now renders PeopleFollowersTabs in place of the old People component.
Followers data is fetched client-side since layout is a client component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ow Us button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ple tab

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Featured usernames (defined in Followers.constants.ts) get the largest
bubble size. If a featured user has unfollowed, a random follower fills
the slot.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Featured followers always appear first with large bubbles,
remaining followers are randomly shuffled on each page load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 15, 2026

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

Project Deployment Actions Updated (UTC)
activity.hamsurang.com Ready Ready Preview, Comment Apr 15, 2026 3:21pm
hamsurang.com Ready Ready Preview, Comment Apr 15, 2026 3:21pm
home.hamsurang.com Ready Ready Preview, Comment Apr 15, 2026 3:21pm

Request Review

Comment thread apps/home/app/_shared/components/Followers/Followers.constants.ts
Copy link
Copy Markdown
Member

@minsoo-web minsoo-web left a comment

Choose a reason for hiding this comment

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

리뷰 아주 사소한 것 몇 개 남겼습니다!!

Comment on lines +65 to +74
useEffect(() => {
fetch('https://api.github.com/users/hamsurang/followers?per_page=100')
.then((res) => (res.ok ? res.json() : []))
.then((data: GitHubFollower[]) => {
const { sorted, featuredCount: fc } = sortWithFeatured(data, FEATURED_FOLLOWERS)
setFollowers(sorted)
setFeaturedCount(fc)
})
.catch(() => setFollowers([]))
}, [])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

요게 get-followers.ts의 내용과 다른가요..! 중복되어 따로 관리되고 있는 것 같은데 의도가 있으신지 궁금합니다

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+ serverside에서 데이터를 fetching하고 client 컴포넌트에서 prop으로 받으면 useEffect로 인한 호출도 안 해도 될 것 같은데 어떠세요?!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

전반적으로 svg가 인라인으로 그려지는 것을 icon 패키지로 옮겨서 처리할 수 있을까요?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

이것 별도의 컴포넌트로 분리한 의도가 있으실지 궁금합니당

Comment on lines +29 to +32
<svg viewBox="0 0 16 16" className="w-4 h-4 fill-current" aria-label="GitHub">
<title>GitHub</title>
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
</svg>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Github icon은 이미 icons 패키지에 있는데, 재활용이 어려울까요?

Comment on lines +5 to +14
const res = await fetch('https://api.github.com/users/hamsurang/followers?per_page=100', {
next: { revalidate: 3600 },
})

if (!res.ok) {
console.warn(`[github] Failed to fetch followers: ${res.status}`)
return []
}

return (await res.json()) as GitHubFollower[]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

요것 as 할당하기보다 데이터 형식이 다른지를 가드하는 처리가 있으면 좋을 것 같은데 어떠신가용

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Image

팔로워 컴포넌트가 사용처가 없는 것 같아요...! 의도하신 것일까용

Followers 컴포넌트가 FollowersBubble을 내장하고 있는데, Tab부분에서는 Bubble만 쓰고 있는 것 같아요

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.

2 participants