COMPONENT LAB
공통/feature 컴포넌트를 회색 와이어프레임 골격으로 단순화해 그리고, 각 영역에 어떤 prop이 채워지는지 점선으로 가리킨다. 왼쪽 설명·인자표·코드와 오른쪽 골격을 함께 보며 "이 prop → 화면의 이 부분" 흐름을 익힌다. 미리보기 우측 상단 와이어프레임 ↔ 실물 토글로 실제 렌더 모습도 바로 확인할 수 있다.
Button - variant 로 색만 갈아끼우는 버튼
네이티브 <button> 을 감싼 공통 버튼. children 이 글자, variant 가 배경/테두리 색을 정한다. disabled 면 흐려지고 클릭이 막힌다. 나머지 button 속성(onClick·type 등)은 그대로 전달된다.
- variant"primary" | "secondary" | "neutral"배경/테두리 색 (기본 primary)
- childrenReactNode버튼 안 글자/아이콘
- disabledboolean흐리게 + 클릭 불가
- ...propsButtonHTMLAttributesonClick·type 등 네이티브 속성
<Button variant="primary" onClick={save}>
저장
</Button>Input - label 유무로 묶음/인라인이 갈리는 입력
label 을 주면 위에 라벨을 단 세로 묶음으로, 없으면 <input> 만 렌더해 flex 행 안 인라인 입력으로 쓴다. theme='hud' 면 어두운 글래스 룩(다크 폼·인증). placeholder·value 등은 네이티브 속성으로 전달.
- labelstring?있으면 라벨 + 입력 세로 묶음, 없으면 input 단독
- theme"light" | "hud"밝은 배경 / 어두운 글래스 (기본 light)
- labelClassNamestring?라벨 색·타이포 덮어쓰기
- ...propsInputHTMLAttributesplaceholder·value·onChange 등
<Input
label="닉네임"
theme="hud"
placeholder="이름을 입력"
/>Select - options 배열이 그대로 목록이 되는 셀렉트
label 은 위 라벨, options(value·label 쌍 배열)가 펼침 목록이 된다. 선택값/변경은 네이티브 select 속성(value·onChange)으로 다룬다.
- labelstring?위 라벨
- options{ value; label }[]각 항목 = 한 <option>
- ...propsSelectHTMLAttributesvalue·onChange 등
<Select
label="정렬"
value={sort}
onChange={onSort}
options={[
{ value: "new", label: "최신순" },
{ value: "like", label: "좋아요순" },
]}
/>ColorBadge - color 로 꽉 찬 단색 배지
color(hex) 가 배경을 꽉 채우고, 글자색은 배경 밝기(YIQ)에 따라 검정/흰색으로 자동 대비된다. children 이 라벨. 직무 라벨 등 캐릭터 색을 입힐 때 쓴다.
- colorstring배경 hex - 글자색 자동 대비
- childrenReactNode배지 글자
- classNamestring?px/py/크기 등 덮어쓰기
<ColorBadge color="#321DFA">
프론트엔드
</ColorBadge>GhostBadge - 반투명 보조 라벨
테두리 + 반투명 채움 + 블러의 직각 배지. 이미지/어두운 배경 위 보조 라벨(연차·성별, 스킬칩)에 쓴다. as='li' 로 주면 목록 항목으로 렌더된다.
- childrenReactNode배지 글자
- as"span" | "li"렌더 태그 (기본 span, 스킬칩 목록은 li)
- classNamestring?px/py/크기 덮어쓰기
<GhostBadge>3년차</GhostBadge>
<GhostBadge as="li">React</GhostBadge>- React
- Spring as
Spinner - size·color 만 받는 로딩 인디케이터
두 겹으로 도는 SF 풍 로딩 표시. size 로 한 변 px, color 로 호 색을 정한다(기본 밝은 회색). 캐릭터 카드 로딩 땐 그 캐릭터 테마색으로 덮어쓴다.
- sizenumber?한 변 px (기본 28)
- colorstring?호 색 (기본 #d4d4d8)
- classNamestring?여백 등 추가
<Spinner size={40} color="#321DFA" />CountStats - 조회·좋아요·댓글 수 한 줄
카드의 세 숫자를 한 줄로 묶어 보여주는 표시 요소. 세 카운트는 필수, 색·글자크기는 화면마다 달라 className 으로 덮어쓴다.
- viewCountnumber조회수
- likeCountnumber좋아요수
- commentCountnumber댓글수
- classNamestring?색·크기 덮어쓰기
<CountStats
viewCount={card.viewCount}
likeCount={card.likeCount}
commentCount={card.commentCount}
/>Pagination - page·totalPages 로 그리는 페이저
page(0-based)·totalPages 로 버튼을 그리고, 클릭하면 onChange(다음 page) 가 불린다. variant 로 표시 방식(compact·numbered·arrows)을 고른다. 페이지가 1개 이하면 렌더하지 않는다.
- pagenumber현재 페이지 (0-based)
- totalPagesnumber전체 페이지 수
- onChange(page) => void버튼 클릭 시 호출
- variant"compact" | "numbered" | "arrows"표시 방식 (기본 compact)
<Pagination
page={page}
totalPages={data.totalPages}
onChange={setPage}
variant="numbered"
/>LikeButton - cardId 로 토글하는 좋아요
cardId 가 좋아요를 보낼 대상 카드, initialLikeCount 가 첫 표시 숫자다. 누르는 즉시 ♡↔♥ 와 카운트가 바뀐다(낙관적 업데이트 - 서버 응답을 기다리지 않고, 실패 시 되돌림). 비로그인 시 /login 으로 보낸다. (서버에 '내 좋아요 여부' 조회가 없어 응답/에러코드로 보정)
- cardIdnumber좋아요 보낼 대상 카드
- initialLikeCountnumber첫 표시 좋아요 수
<LikeButton
cardId={card.id}
initialLikeCount={card.likeCount}
/>CommentItem - comment 한 개 + 본인 액션
comment 객체가 작성자·시간·본문을 채운다. isOwner 면 수정(인라인)/삭제 버튼이 붙고, 수정·삭제는 낙관적으로 즉시 반영된다(useUpdateComment·useDeleteComment 가 ['comments', cardId] 캐시를 갱신). BLINDED 상태면 가린 내용으로 보인다.
- commentComment작성자·시간·본문·상태(cardId 포함)
- isOwnerbooleantrue 면 수정/삭제 버튼 노출
<CommentItem
comment={c}
isOwner={c.authorId === myId}
/>StatBars - stat 5종을 가로 막대로
능력치 객체(stat, 각 0~100)를 5개 가로 막대로 쌓는다. accent 가 채움색(미지정 시 흰색). 상세의 레이더와 같은 데이터를 막대로 한 번 더 보여줘 형태를 달리한다.
- statDevCardStat능력치 5종 (각 0~100)
- accentstring?막대 채움색 hex (기본 흰색)
<StatBars stat={card.stat} accent="#321DFA" />CharacterAvatar - character 로 그리는 캐릭터 이미지
character(타입·성별·이미지 URL)로 캐릭터 그림을 그린다. thumbnail=true 면 목록용 썸네일, false 면 상세용 원본. 업로드 이미지 → 고정 일러스트 → MBTI 라벨 박스 순으로 폴백한다.
- characterPick<MbtiCharacter, …>타입·성별·이름·이미지 URL
- thumbnailboolean?true=썸네일(목록) / false=원본(상세)
- classNamestring?크기·비율 등
<CharacterAvatar
character={card.character}
thumbnail
className="aspect-[3/4] w-40"
/>업로드 → 고정 일러스트 → 라벨 박스 순 폴백
CardSplashPanel - card·rank 로 그리는 풀스크린 카드
풀스크린 목록의 카드 한 장. card 의 타입·이름·직무·이미지가 도형+일러스트+텍스트로 합쳐지고, rank 가 우상단 큰 순번이 된다. 카드 표면은 비워 어두운 배경이 비친다. 이동은 호버 시 뜨는 VIEW MORE 버튼에만 건다.
- cardDevCardSummary타입·이름·직무·이미지 등 요약
- ranknumber전체 기준 순번 (우상단 큰 숫자)
<CardSplashPanel card={card} rank={i + 1} />골격은 실물이 아니라 구조를 단순화한 그림이다 - 정확한 동작/스타일은 각 컴포넌트 파일(src/components/common·src/features/*)이 단일 출처.