댓글 카드 디자인 개선
This commit is contained in:
@@ -258,7 +258,10 @@ onBeforeUnmount(() => {
|
||||
<img v-if="avatarUrlOf(comment)" class="commentItem__avatar" :src="avatarUrlOf(comment)" :alt="displayNameOf(comment)" draggable="false" />
|
||||
<div v-else class="commentItem__avatar commentItem__avatar--fallback">{{ avatarFallbackOf(comment) }}</div>
|
||||
<div class="commentItem__meta">
|
||||
<div class="commentItem__name">{{ displayNameOf(comment) }}</div>
|
||||
<div class="commentItem__metaTop">
|
||||
<div class="commentItem__name">{{ displayNameOf(comment) }}</div>
|
||||
<span class="commentItem__badge">댓글</span>
|
||||
</div>
|
||||
<div class="commentItem__date">{{ formatDate(comment.createdAt) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -307,7 +310,10 @@ onBeforeUnmount(() => {
|
||||
<img v-if="avatarUrlOf(reply)" class="commentItem__avatar" :src="avatarUrlOf(reply)" :alt="displayNameOf(reply)" draggable="false" />
|
||||
<div v-else class="commentItem__avatar commentItem__avatar--fallback">{{ avatarFallbackOf(reply) }}</div>
|
||||
<div class="commentItem__meta">
|
||||
<div class="commentItem__name">{{ displayNameOf(reply) }}</div>
|
||||
<div class="commentItem__metaTop">
|
||||
<div class="commentItem__name">{{ displayNameOf(reply) }}</div>
|
||||
<span class="commentItem__badge commentItem__badge--reply">답글</span>
|
||||
</div>
|
||||
<div class="commentItem__date">{{ formatDate(reply.createdAt) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -453,18 +459,36 @@ onBeforeUnmount(() => {
|
||||
|
||||
.commentsThread {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.commentItem {
|
||||
padding: 16px;
|
||||
border-radius: 22px;
|
||||
position: relative;
|
||||
padding: 18px 18px 16px;
|
||||
border-radius: 24px;
|
||||
background: linear-gradient(180deg, color-mix(in srgb, var(--theme-surface) 88%, var(--theme-surface-soft)) 0%, var(--theme-surface) 100%);
|
||||
box-shadow:
|
||||
inset 0 1px 0 color-mix(in srgb, white 6%, transparent),
|
||||
0 14px 32px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.commentItem--reply {
|
||||
margin-top: 12px;
|
||||
margin-left: 24px;
|
||||
border-radius: 18px;
|
||||
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%);
|
||||
}
|
||||
|
||||
.commentItem--reply::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 22px;
|
||||
left: -16px;
|
||||
width: 12px;
|
||||
height: calc(100% - 44px);
|
||||
border-left: 2px solid color-mix(in srgb, var(--theme-accent) 36%, var(--theme-card-border));
|
||||
border-bottom: 2px solid color-mix(in srgb, var(--theme-accent) 36%, var(--theme-card-border));
|
||||
border-bottom-left-radius: 14px;
|
||||
}
|
||||
|
||||
.commentItem--highlighted {
|
||||
@@ -507,11 +531,37 @@ onBeforeUnmount(() => {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.commentItem__metaTop {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.commentItem__name {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.commentItem__badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 0 9px;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--theme-surface-soft) 84%, transparent);
|
||||
color: var(--theme-text-muted);
|
||||
font-size: 11px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.commentItem__badge--reply {
|
||||
background: color-mix(in srgb, var(--theme-accent) 15%, var(--theme-surface-soft));
|
||||
color: var(--theme-text);
|
||||
}
|
||||
|
||||
.commentItem__date {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
@@ -538,6 +588,10 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.commentItem__body {
|
||||
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);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
line-height: 1.6;
|
||||
@@ -570,7 +624,12 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.commentItem--reply {
|
||||
margin-left: 12px;
|
||||
margin-left: 14px;
|
||||
}
|
||||
|
||||
.commentItem--reply::before {
|
||||
left: -10px;
|
||||
width: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,6 +20,10 @@ function avatarUrlOf(notification) {
|
||||
return notification.actorAvatarSrc ? toApiUrl(notification.actorAvatarSrc) : ''
|
||||
}
|
||||
|
||||
function tierListThumbnailUrl(notification) {
|
||||
return notification.tierListThumbnailSrc ? toApiUrl(notification.tierListThumbnailSrc) : ''
|
||||
}
|
||||
|
||||
function avatarFallbackOf(notification) {
|
||||
return displayInitialFrom(notification.actorName, notification.actorAccountName, '?')
|
||||
}
|
||||
@@ -38,6 +42,10 @@ function notificationTitle(notification) {
|
||||
return notification.notificationType === 'comment_reply' ? '내 댓글에 답글이 달렸어요.' : '내 티어표에 새 댓글이 달렸어요.'
|
||||
}
|
||||
|
||||
function notificationLead(notification) {
|
||||
return notification.notificationType === 'comment_reply' ? '원래 댓글과 새 답글을 함께 확인해보세요.' : '내 티어표에 새로 남겨진 댓글입니다.'
|
||||
}
|
||||
|
||||
function emitUnreadCount(unread) {
|
||||
if (typeof window === 'undefined') return
|
||||
window.dispatchEvent(new CustomEvent('tier-maker:comment-inbox-updated', { detail: { unreadCount: unread } }))
|
||||
@@ -145,10 +153,26 @@ watch(unreadOnly, loadInbox)
|
||||
:class="{ 'commentInboxCard--unread': !notification.isRead }"
|
||||
>
|
||||
<button class="commentInboxCard__body" type="button" @click="openNotification(notification)">
|
||||
<div class="commentInboxCard__thumbWrap">
|
||||
<img
|
||||
v-if="tierListThumbnailUrl(notification)"
|
||||
class="commentInboxCard__thumb"
|
||||
:src="tierListThumbnailUrl(notification)"
|
||||
:alt="notification.tierListTitle || '티어표 썸네일'"
|
||||
draggable="false"
|
||||
/>
|
||||
<div v-else class="commentInboxCard__thumbFallback">티어표</div>
|
||||
</div>
|
||||
<div class="commentInboxCard__main">
|
||||
<div class="commentInboxCard__titleRow">
|
||||
<div class="commentInboxCard__title">{{ notificationTitle(notification) }}</div>
|
||||
<span v-if="!notification.isRead" class="commentInboxCard__dot" aria-label="안 읽음"></span>
|
||||
<div>
|
||||
<div class="commentInboxCard__title">{{ notificationTitle(notification) }}</div>
|
||||
<div class="commentInboxCard__lead">{{ notificationLead(notification) }}</div>
|
||||
</div>
|
||||
<div class="commentInboxCard__status">
|
||||
<span v-if="!notification.isRead" class="commentInboxCard__dot" aria-label="안 읽음"></span>
|
||||
<span class="commentInboxCard__badge">{{ notification.notificationType === 'comment_reply' ? '답글' : '댓글' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="commentInboxCard__meta">
|
||||
<img
|
||||
@@ -167,7 +191,16 @@ watch(unreadOnly, loadInbox)
|
||||
{{ notification.tierListTitle || '제목 없는 티어표' }}
|
||||
<span class="commentInboxCard__targetMeta">/ {{ notification.topicName || notification.topicSlug || notification.topicId }}</span>
|
||||
</div>
|
||||
<div class="commentInboxCard__content">{{ notification.commentContent }}</div>
|
||||
<div class="commentInboxCard__thread">
|
||||
<div v-if="notification.parentCommentContent" class="commentInboxCard__threadBlock">
|
||||
<div class="commentInboxCard__threadLabel">원래 댓글</div>
|
||||
<div class="commentInboxCard__threadText">{{ notification.parentCommentContent }}</div>
|
||||
</div>
|
||||
<div class="commentInboxCard__threadBlock commentInboxCard__threadBlock--accent">
|
||||
<div class="commentInboxCard__threadLabel">{{ notification.notificationType === 'comment_reply' ? '새 답글' : '새 댓글' }}</div>
|
||||
<div class="commentInboxCard__threadText">{{ notification.commentContent }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</article>
|
||||
@@ -230,20 +263,64 @@ watch(unreadOnly, loadInbox)
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
grid-template-columns: 140px minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.commentInboxCard__thumbWrap {
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 10;
|
||||
border-radius: 18px;
|
||||
overflow: hidden;
|
||||
background: var(--theme-thumb-fallback-bg);
|
||||
border: 1px solid color-mix(in srgb, var(--theme-card-border) 78%, transparent);
|
||||
}
|
||||
|
||||
.commentInboxCard__thumb,
|
||||
.commentInboxCard__thumbFallback {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.commentInboxCard__thumb {
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.commentInboxCard__thumbFallback {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
color: var(--theme-text-faint);
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.commentInboxCard__titleRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.commentInboxCard__title {
|
||||
font-size: 18px;
|
||||
font-size: 17px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.commentInboxCard__lead {
|
||||
margin-top: 6px;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.commentInboxCard__status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.commentInboxCard__dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@@ -252,6 +329,18 @@ watch(unreadOnly, loadInbox)
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.commentInboxCard__badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 28px;
|
||||
padding: 0 12px;
|
||||
border-radius: 999px;
|
||||
background: color-mix(in srgb, var(--theme-accent) 18%, var(--theme-surface-soft));
|
||||
color: var(--theme-text);
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.commentInboxCard__meta {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
@@ -291,13 +380,40 @@ watch(unreadOnly, loadInbox)
|
||||
|
||||
.commentInboxCard__content {
|
||||
margin-top: 10px;
|
||||
color: var(--theme-text-muted);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.commentInboxCard__thread {
|
||||
margin-top: 14px;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.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));
|
||||
}
|
||||
|
||||
.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));
|
||||
}
|
||||
|
||||
.commentInboxCard__threadLabel {
|
||||
font-size: 11px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--theme-text-faint);
|
||||
}
|
||||
|
||||
.commentInboxCard__threadText {
|
||||
margin-top: 8px;
|
||||
color: var(--theme-text);
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
@@ -309,5 +425,9 @@ watch(unreadOnly, loadInbox)
|
||||
.commentInboxPanel {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.commentInboxCard__body {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user