답글 입력 UX 정리

This commit is contained in:
2026-04-07 13:31:00 +09:00
parent db037c6163
commit 173f547d8b
4 changed files with 58 additions and 3 deletions

View File

@@ -38,6 +38,7 @@ const replyDrafts = ref({})
const openedReplyComposerId = ref('')
const submittingTargetId = ref('')
const deletingCommentId = ref('')
const replyInputRefs = ref({})
let activeCommentRetryTimer = 0
const totalCommentCount = computed(() =>
@@ -169,8 +170,33 @@ async function deleteComment(commentId) {
}
}
function toggleReplyComposer(commentId) {
openedReplyComposerId.value = openedReplyComposerId.value === commentId ? '' : commentId
function registerReplyInput(commentId, element) {
if (!commentId) return
if (element) {
replyInputRefs.value[commentId] = element
return
}
delete replyInputRefs.value[commentId]
}
async function focusReplyInput(commentId) {
if (!commentId) return
await nextTick()
const target = replyInputRefs.value[commentId]
if (target && typeof target.focus === 'function') {
target.focus()
const value = target.value || ''
if (typeof target.setSelectionRange === 'function') {
target.setSelectionRange(value.length, value.length)
}
}
}
async function toggleReplyComposer(commentId) {
const nextId = openedReplyComposerId.value === commentId ? '' : commentId
openedReplyComposerId.value = nextId
if (!nextId) return
await focusReplyInput(nextId)
}
watch(() => props.tierListId, loadComments, { immediate: true })
@@ -254,6 +280,7 @@ onBeforeUnmount(() => {
<div v-if="openedReplyComposerId === comment.id && props.canWrite" class="replyComposer">
<textarea
v-model="replyDrafts[comment.id]"
:ref="(element) => registerReplyInput(comment.id, element)"
class="commentsComposer__input commentsComposer__input--reply"
maxlength="2000"
rows="2"
@@ -261,7 +288,7 @@ onBeforeUnmount(() => {
/>
<div class="commentsComposer__footer">
<span class="commentsComposer__hint">{{ (replyDrafts[comment.id] || '').length }}/2000</span>
<button class="btn btn--save btn--small" type="button" :disabled="!(replyDrafts[comment.id] || '').trim() || submittingTargetId === comment.id" @click="submitComment(comment.id)">
<button class="btn btn--save commentsComposer__submit" type="button" :disabled="!(replyDrafts[comment.id] || '').trim() || submittingTargetId === comment.id" @click="submitComment(comment.id)">
답글 등록
</button>
</div>
@@ -385,10 +412,20 @@ onBeforeUnmount(() => {
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);
}
.commentsComposer__input--reply {
min-height: 72px;
background: color-mix(in srgb, var(--theme-input-bg) 82%, var(--theme-surface-soft));
}
.commentsComposer__input:focus {
outline: none;
border-color: color-mix(in srgb, var(--theme-accent) 60%, var(--theme-field-border));
box-shadow:
inset 0 0 0 1px color-mix(in srgb, var(--theme-accent) 52%, transparent),
0 0 0 3px color-mix(in srgb, var(--theme-accent) 16%, transparent);
}
.commentsComposer__footer,
@@ -508,6 +545,15 @@ onBeforeUnmount(() => {
.replyComposer {
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));
}
.commentsComposer__submit {
min-width: 112px;
min-height: 42px;
}
@media (max-width: 860px) {