답글 입력 UX 정리
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user