릴리스: v0.1.39 티어표 편집 헤더 레이아웃 정리

This commit is contained in:
2026-03-26 18:24:18 +09:00
parent 5d778e9c20
commit 94152f22b2
4 changed files with 111 additions and 45 deletions

View File

@@ -482,34 +482,41 @@ onUnmounted(() => {
<template>
<section class="head">
<div class="head__meta">
<div class="kicker">{{ gameName || gameId }}</div>
<input v-model="title" class="titleInput" placeholder="티어표 이름을 입력하세요" :readonly="!canEdit" />
<div v-if="untitledWarning" class="titleNotice">{{ untitledWarning }}</div>
<div v-if="canEdit" class="thumbComposer">
<input ref="thumbnailFileEl" type="file" accept="image/*" class="hidden" @change="onThumbnailChange" />
<div class="thumbComposer__preview">
<img v-if="displayThumbnailUrl" class="thumbComposer__image" :src="displayThumbnailUrl" alt="썸네일 미리보기" />
<div v-else class="thumbComposer__empty">썸네일 없음</div>
</div>
<div class="thumbComposer__actions">
<button class="btn btn--ghost" @click="openThumbnailFile">썸네일 선택</button>
<button class="btn btn--danger" :disabled="!pendingThumbnailFile && !thumbnailSrc" @click="clearThumbnail">썸네일 제거</button>
<div class="heroCard">
<div class="heroCard__main">
<input v-model="title" class="titleInput" placeholder="티어표 이름을 입력하세요" :readonly="!canEdit" />
<div v-if="untitledWarning" class="titleNotice">{{ untitledWarning }}</div>
<input
v-model="description"
class="descInput"
placeholder="설명(선택): 이 티어표의 기준/룰"
:readonly="!canEdit"
/>
<div class="hint">
<template v-if="canEdit">
그룹 이름/순서 변경과 아이템 드래그&드롭이 가능합니다. 저장하려면 <b>저장</b> 누르세요.
</template>
<template v-else>
공개된 티어표를 보는 중입니다. 로그인한 작성자만 수정할 있어요.
</template>
</div>
</div>
<input
v-model="description"
class="descInput"
placeholder="설명(선택): 이 티어표의 기준/룰"
:readonly="!canEdit"
/>
<div class="hint">
<template v-if="canEdit">
그룹 이름/순서 변경과 아이템 드래그&드롭이 가능합니다. 저장하려면 <b>저장</b> 누르세요.
</template>
<template v-else>
공개된 티어표를 보는 중입니다. 로그인한 작성자만 수정할 있어요.
</template>
<div class="heroCard__side">
<div class="thumbComposer">
<input ref="thumbnailFileEl" type="file" accept="image/*" class="hidden" @change="onThumbnailChange" />
<div class="thumbComposer__header">
<div class="thumbComposer__eyebrow">대표 썸네일</div>
<div class="thumbComposer__caption">목록 카드 상단에 표시됩니다.</div>
</div>
<div class="thumbComposer__preview">
<img v-if="displayThumbnailUrl" class="thumbComposer__image" :src="displayThumbnailUrl" alt="썸네일 미리보기" />
<div v-else class="thumbComposer__empty">썸네일 없음</div>
</div>
<div v-if="canEdit" class="thumbComposer__actions">
<button class="btn btn--ghost thumbComposer__button" @click="openThumbnailFile">썸네일 선택</button>
<button class="btn btn--danger thumbComposer__button" :disabled="!pendingThumbnailFile && !thumbnailSrc" @click="clearThumbnail">제거</button>
</div>
</div>
</div>
</div>
<div class="actions">
@@ -630,30 +637,41 @@ onUnmounted(() => {
gap: 14px;
padding: 6px 2px 14px;
}
.head__meta {
.heroCard {
display: grid;
gap: 10px;
grid-template-columns: minmax(0, 1.5fr) minmax(280px, 360px);
gap: 18px;
align-items: stretch;
}
.kicker {
font-size: 12px;
opacity: 0.7;
.heroCard__main,
.heroCard__side {
min-width: 0;
}
.heroCard__main {
display: grid;
gap: 12px;
}
.heroCard__side {
display: flex;
}
.titleInput {
width: min(100%, 920px);
width: 100%;
font-size: 22px;
font-weight: 800;
letter-spacing: -0.02em;
padding: 10px 12px;
border-radius: 14px;
padding: 14px 16px;
border-radius: 18px;
border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.07), rgba(255, 255, 255, 0.04));
color: rgba(255, 255, 255, 0.92);
outline: none;
box-sizing: border-box;
}
.descInput {
width: min(100%, 920px);
padding: 10px 12px;
border-radius: 14px;
width: 100%;
min-height: 92px;
padding: 14px 16px;
border-radius: 18px;
border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(0, 0, 0, 0.18);
color: rgba(255, 255, 255, 0.92);
@@ -663,24 +681,47 @@ onUnmounted(() => {
.hint {
opacity: 0.78;
font-size: 13px;
line-height: 1.6;
padding: 0 2px;
}
.titleNotice {
font-size: 13px;
line-height: 1.5;
color: rgba(251, 191, 36, 0.94);
padding: 0 2px;
}
.thumbComposer {
display: grid;
gap: 10px;
width: min(100%, 920px);
width: 100%;
padding: 16px;
border-radius: 22px;
border: 1px solid rgba(255, 255, 255, 0.12);
background:
radial-gradient(circle at top right, rgba(96, 165, 250, 0.12), transparent 46%),
rgba(255, 255, 255, 0.04);
box-sizing: border-box;
}
.thumbComposer__header {
display: grid;
gap: 4px;
}
.thumbComposer__eyebrow {
font-size: 13px;
font-weight: 900;
letter-spacing: 0.02em;
}
.thumbComposer__caption {
font-size: 12px;
opacity: 0.68;
}
.thumbComposer__preview {
width: min(100%, 360px);
width: 100%;
aspect-ratio: 16 / 9;
border-radius: 16px;
border-radius: 18px;
overflow: hidden;
border: 1px solid rgba(255, 255, 255, 0.12);
background: rgba(255, 255, 255, 0.04);
background: rgba(11, 18, 32, 0.78);
}
.thumbComposer__image {
width: 100%;
@@ -693,11 +734,16 @@ onUnmounted(() => {
display: grid;
place-items: center;
color: rgba(255, 255, 255, 0.62);
font-size: 13px;
}
.thumbComposer__actions {
display: flex;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
flex-wrap: wrap;
}
.thumbComposer__button {
width: 100%;
margin-top: 0;
}
.actions {
display: flex;
@@ -774,7 +820,7 @@ onUnmounted(() => {
}
.btn--ghost {
width: 100%;
margin-top: 10px;
margin-top: 0;
}
.layout {
display: grid;
@@ -1073,6 +1119,9 @@ onUnmounted(() => {
border-radius: 14px;
}
@media (max-width: 980px) {
.heroCard {
grid-template-columns: 1fr;
}
.layout {
grid-template-columns: 1fr;
}
@@ -1089,5 +1138,13 @@ onUnmounted(() => {
.row {
grid-template-columns: 150px 1fr;
}
.thumbComposer {
padding: 14px;
border-radius: 18px;
}
.titleInput,
.descInput {
border-radius: 16px;
}
}
</style>