From 9f143d4a8914a5a1771ef774be3ae8113f0247ec Mon Sep 17 00:00:00 2001 From: zenn Date: Tue, 7 Apr 2026 13:45:50 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8C=93=EA=B8=80=20UI=20=ED=86=A4=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/history.md | 3 + docs/todo.md | 2 + docs/update.md | 7 ++ .../src/components/TierListCommentsCard.vue | 71 +++++++++++++++---- frontend/src/views/CommentInboxView.vue | 22 ++++-- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/docs/history.md b/docs/history.md index 69c7b6b..5c58ee8 100644 --- a/docs/history.md +++ b/docs/history.md @@ -1,5 +1,8 @@ # 의사결정 이력 +## 2026-04-07 v1.1.5 +- 댓글 UI는 정보를 구분하기 위해 모든 레이어에 border를 두기보다, 큰 카드만 최소 테두리를 두고 내부는 surface 톤과 그림자 차이로 나누는 방향이 더 낫다고 판단했다. 댓글/답글 구조는 구분보다 과밀감이 먼저 느껴지면 안 되므로 이 원칙을 유지한다. + ## 2026-04-07 v1.1.4 - 댓글 관리함은 단순 목록보다 `무슨 티어표에서`, `원래 어떤 댓글이 있었고`, `새로 무엇이 달렸는지`를 한눈에 이해하는 정보 구조가 중요하다고 판단했다. 그래서 썸네일 + 스레드 비교 블록을 기본 카드 문법으로 채택했다. - 댓글 본문과 답글도 단순 들여쓰기보다 카드/말풍선/연결선으로 관계를 보여주는 쪽이 최신 UI 감각에 더 맞는다고 보고, reply depth 1단 구조에 맞춘 시각 문법을 적용했다. diff --git a/docs/todo.md b/docs/todo.md index 76bc2a0..e1fcf59 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,6 +1,8 @@ # 할 일 및 이슈 ## 단기 확인 +- `v1.1.5` 이후 댓글 카드/댓글 관리 카드에서 보더가 과해 보이지 않고, surface/shadow 중심 레이어가 다크/라이트 모드 모두에서 자연스러운지 확인한다. +- 댓글 등록/답글 등록 버튼이 실제 저장 CTA 톤으로 보이고 hover/disabled 상태도 다른 저장 버튼들과 이질감이 없는지 확인한다. - `v1.1.4` 이후 댓글 관리 카드에서 티어표 썸네일, 원댓글/새 댓글 비교 블록이 데스크톱과 모바일에서 모두 자연스럽게 보이는지 확인한다. - 댓글 스레드 카드 리디자인 후 답글 연결선, 배지, 본문 말풍선 배경이 라이트/다크 모드 모두에서 과하지 않게 보이는지 확인한다. - `v1.1.3` 이후 답글 작성 시 입력창이 열리자마자 포커스를 받고, 포커스 전에도 카드/입력 경계가 분명하게 보이는지 다크/라이트 모드 모두에서 확인한다. diff --git a/docs/update.md b/docs/update.md index 5ed9916..5bfa8de 100644 --- a/docs/update.md +++ b/docs/update.md @@ -1,5 +1,12 @@ # 업데이트 로그 +## 2026-04-07 v1.1.5 +- 댓글 카드에서 과도하게 겹치던 보더 문법을 줄이고, 배경 톤과 그림자 중심으로 레이어를 구분하도록 다시 정리했다. 바깥 카드, 댓글 본문, 답글 입력 영역은 border 대신 surface/shadow 조합으로 읽히게 했다. +- 댓글 관리 카드의 티어표 썸네일은 항상 `16:9` 비율로 고정되도록 수정했다. 화면 크기에 따라 높이만 달라지고 이미지 인상 자체는 바뀌지 않게 맞췄다. +- 댓글 등록/답글 등록 버튼은 컴포넌트 내부에서도 실제 `btn--save` 스타일이 적용되도록 공통 save CTA 문법을 직접 정의해, 에디터 저장 버튼과 같은 톤으로 보이게 했다. +- `commentsCard__desc` 안내 문구 폰트 크기를 `12px`로 줄여 본문보다 덜 강조되게 정리했다. +- 확인: `npm run build` + ## 2026-04-07 v1.1.4 - 댓글 관리 카드 디자인을 확장했다. 각 카드에 해당 티어표 썸네일을 붙이고, `원래 댓글`과 `새 댓글/새 답글`을 한 번에 비교해서 볼 수 있게 스레드 블록 구조로 바꿨다. - 댓글 알림 조회 API는 이제 티어표 썸네일과 부모 댓글 내용을 함께 내려준다. 답글 알림에서는 어떤 댓글에 어떤 답글이 달렸는지 바로 읽을 수 있다. diff --git a/frontend/src/components/TierListCommentsCard.vue b/frontend/src/components/TierListCommentsCard.vue index 48203cd..5e1de53 100644 --- a/frontend/src/components/TierListCommentsCard.vue +++ b/frontend/src/components/TierListCommentsCard.vue @@ -371,6 +371,8 @@ onBeforeUnmount(() => { .commentsCard__desc { margin: 0; color: var(--theme-text-muted); + font-size: 12px; + line-height: 1.55; } .commentsCard__count { @@ -393,19 +395,13 @@ onBeforeUnmount(() => { color: var(--theme-text); } -.commentsComposer, -.commentsLoginCta, -.commentItem, -.commentItem--reply { - border: 1px solid var(--theme-card-border); - background: var(--theme-surface); -} - .commentsComposer, .commentsLoginCta { margin-bottom: 18px; padding: 16px; border-radius: 22px; + background: color-mix(in srgb, var(--theme-surface) 88%, var(--theme-surface-soft)); + box-shadow: inset 0 1px 0 color-mix(in srgb, white 5%, transparent); } .commentsComposer__input { @@ -414,11 +410,13 @@ onBeforeUnmount(() => { resize: vertical; padding: 14px 16px; border-radius: 18px; - border: 1px solid var(--theme-field-border); + border: 0; background: var(--theme-input-bg); color: var(--theme-text); box-sizing: border-box; - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--theme-field-border) 45%, transparent); + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--theme-field-border) 38%, transparent), + 0 10px 24px rgba(0, 0, 0, 0.05); } .commentsComposer__input--reply { @@ -477,6 +475,9 @@ onBeforeUnmount(() => { margin-left: 28px; border-radius: 20px; background: linear-gradient(180deg, color-mix(in srgb, var(--theme-accent) 6%, var(--theme-surface)) 0%, var(--theme-surface) 100%); + box-shadow: + inset 0 1px 0 color-mix(in srgb, white 4%, transparent), + 0 10px 24px rgba(0, 0, 0, 0.06); } .commentItem--reply::before { @@ -591,7 +592,9 @@ onBeforeUnmount(() => { padding: 14px 15px; border-radius: 18px; background: color-mix(in srgb, var(--theme-input-bg) 82%, var(--theme-surface)); - border: 1px solid color-mix(in srgb, var(--theme-card-border) 76%, transparent); + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--theme-card-border) 28%, transparent), + 0 8px 18px rgba(0, 0, 0, 0.04); white-space: pre-wrap; word-break: break-word; line-height: 1.6; @@ -601,8 +604,8 @@ onBeforeUnmount(() => { margin-top: 14px; padding: 14px; border-radius: 18px; - border: 1px solid var(--theme-card-border); background: color-mix(in srgb, var(--theme-surface) 76%, var(--theme-surface-soft)); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--theme-card-border) 24%, transparent); } .commentsComposer__submit { @@ -610,6 +613,50 @@ onBeforeUnmount(() => { min-height: 42px; } +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 42px; + padding: 10px 16px; + border-radius: 14px; + border: 1px solid color-mix(in srgb, var(--theme-border) 78%, transparent); + background: color-mix(in srgb, var(--theme-surface-soft) 88%, transparent); + color: var(--theme-text); + cursor: pointer; + font-size: 14px; + font-weight: 800; + transition: transform 160ms ease, background 160ms ease, box-shadow 160ms ease; +} + +.btn:hover { + transform: translateY(-1px); +} + +.btn:disabled { + opacity: 0.58; + cursor: default; + transform: none; +} + +.btn--save { + min-width: 112px; + background: rgba(96, 165, 250, 0.22); + border-color: rgba(96, 165, 250, 0.36); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.08), + 0 10px 18px rgba(59, 130, 246, 0.14); +} + +.btn--save:hover { + background: rgba(96, 165, 250, 0.3); +} + +.btn--ghost { + background: color-mix(in srgb, var(--theme-surface-soft) 86%, transparent); +} + @media (max-width: 860px) { .commentsCard { padding: 20px; diff --git a/frontend/src/views/CommentInboxView.vue b/frontend/src/views/CommentInboxView.vue index 2dc4147..d2b7641 100644 --- a/frontend/src/views/CommentInboxView.vue +++ b/frontend/src/views/CommentInboxView.vue @@ -246,13 +246,17 @@ watch(unreadOnly, loadInbox) .commentInboxCard { border-radius: 22px; - border: 1px solid var(--theme-card-border); - background: var(--theme-surface); + background: linear-gradient(180deg, color-mix(in srgb, var(--theme-surface) 92%, var(--theme-surface-soft)) 0%, var(--theme-surface) 100%); overflow: hidden; + box-shadow: + inset 0 1px 0 color-mix(in srgb, white 5%, transparent), + 0 14px 28px rgba(0, 0, 0, 0.06); } .commentInboxCard--unread { - border-color: color-mix(in srgb, var(--theme-accent) 48%, var(--theme-card-border)); + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--theme-accent) 38%, transparent), + 0 14px 28px rgba(0, 0, 0, 0.08); } .commentInboxCard__body { @@ -271,11 +275,11 @@ watch(unreadOnly, loadInbox) .commentInboxCard__thumbWrap { width: 100%; - aspect-ratio: 16 / 10; + aspect-ratio: 16 / 9; border-radius: 18px; overflow: hidden; background: var(--theme-thumb-fallback-bg); - border: 1px solid color-mix(in srgb, var(--theme-card-border) 78%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--theme-card-border) 26%, transparent); } .commentInboxCard__thumb, @@ -391,13 +395,17 @@ watch(unreadOnly, loadInbox) .commentInboxCard__threadBlock { padding: 14px 15px; border-radius: 18px; - border: 1px solid var(--theme-card-border); background: color-mix(in srgb, var(--theme-surface) 88%, var(--theme-surface-soft)); + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--theme-card-border) 20%, transparent), + 0 8px 18px rgba(0, 0, 0, 0.04); } .commentInboxCard__threadBlock--accent { - border-color: color-mix(in srgb, var(--theme-accent) 38%, var(--theme-card-border)); background: color-mix(in srgb, var(--theme-accent) 10%, var(--theme-surface)); + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--theme-accent) 24%, transparent), + 0 10px 20px rgba(59, 130, 246, 0.08); } .commentInboxCard__threadLabel {