Compare commits

...

3 Commits

6 changed files with 83 additions and 8 deletions

View File

@@ -1,5 +1,14 @@
# 의사결정 이력 # 의사결정 이력
## 2026-04-02 v1.3.92
- 왼쪽 레일 활성 메뉴도 로그인 토글과 같은 이동형 배경 문법을 쓰는 편이 앱 전체 인터랙션 언어를 더 일관되게 만든다고 판단했다.
## 2026-04-02 v1.3.91
- 로그인/회원가입 탭은 즉시 배경 교체보다, 선택 배경이 실제로 이동하는 토글 문법이 더 직관적이고 상태 전환이 잘 읽힌다고 판단했다.
## 2026-04-02 v1.3.90
- 경고 수준의 CSS 진단이라도 실제 의미 없는 속성이나 벤더 전용 속성 누락이라면 바로 정리해 두는 편이 이후 유지보수 피로를 줄인다고 판단했다.
## 2026-04-02 v1.3.89 ## 2026-04-02 v1.3.89
- 더 이상 참조되지 않는 Vite 기본 자산과 레거시 public 아이콘 묶음은 남겨둘수록 혼동만 커지므로, 실제 사용 파일만 남기고 정리하는 편이 맞다고 판단했다. - 더 이상 참조되지 않는 Vite 기본 자산과 레거시 public 아이콘 묶음은 남겨둘수록 혼동만 커지므로, 실제 사용 파일만 남기고 정리하는 편이 맞다고 판단했다.
- 공유용 썸네일은 코드 수정과 별개로 시각 자산 손질이 자주 일어날 수 있으므로, 이번처럼 워크트리에 이미 반영된 최신 이미지 수정본은 함께 릴리스에 포함하는 편이 맞다고 정리했다. - 공유용 썸네일은 코드 수정과 별개로 시각 자산 손질이 자주 일어날 수 있으므로, 이번처럼 워크트리에 이미 반영된 최신 이미지 수정본은 함께 릴리스에 포함하는 편이 맞다고 정리했다.

View File

@@ -1,6 +1,9 @@
# 할 일 및 이슈 # 할 일 및 이슈
## 단기 확인 ## 단기 확인
- 왼쪽 레일 활성 배경은 공용 인디케이터가 이동하는 방식으로 바뀌었으므로, 홈/내 티어표/즐겨찾기/설정 전환과 레일 접힘 상태 양쪽에서 위치 보정이 자연스러운지 한 번 더 QA한다.
- 로그인 화면 상단 토글은 이동형 인디케이터로 바뀌었으므로, 데스크톱과 모바일에서 `로그인 / 회원가입` 전환 애니메이션이 어색하지 않고 포커스/클릭 상태도 자연스러운지 한 번 더 QA한다.
- 관리자 카드 설명 줄임은 `line-clamp` 표준 속성까지 함께 선언했으므로, 실제 브라우저별 표시 차이가 없는지 한 번 더 QA한다.
- 사용하지 않는 기본 자산을 정리했으므로, 배포본에서 누락 참조 없이 파비콘/공유 썸네일/좌측 레일 아이콘이 정상 노출되는지 한 번 더 QA한다. - 사용하지 않는 기본 자산을 정리했으므로, 배포본에서 누락 참조 없이 파비콘/공유 썸네일/좌측 레일 아이콘이 정상 노출되는지 한 번 더 QA한다.
- 공유 썸네일 `og-card`는 이번에 이미지 수정본까지 함께 반영했으므로, 실제 메신저 미리보기에서 최신 그림이 캐시 갱신 후 정상 노출되는지 한 번 더 QA한다. - 공유 썸네일 `og-card`는 이번에 이미지 수정본까지 함께 반영했으므로, 실제 메신저 미리보기에서 최신 그림이 캐시 갱신 후 정상 노출되는지 한 번 더 QA한다.
- 홈페이지 공유 메타와 새 `og-card.png`는 이번에 처음 붙였으므로, 카카오톡/디스코드/슬랙/모바일 브라우저에서 제목·설명·썸네일이 기대대로 보이는지 한 번 더 QA한다. - 홈페이지 공유 메타와 새 `og-card.png`는 이번에 처음 붙였으므로, 카카오톡/디스코드/슬랙/모바일 브라우저에서 제목·설명·썸네일이 기대대로 보이는지 한 번 더 QA한다.

View File

@@ -1,5 +1,14 @@
# 업데이트 로그 # 업데이트 로그
## 2026-04-02 v1.3.92
- 왼쪽 네비게이션의 활성 메뉴 배경은 개별 항목에 즉시 붙는 방식에서, 공용 인디케이터가 현재 메뉴 위치로 미끄러져 이동하는 토글형 인터랙션으로 정리함.
## 2026-04-02 v1.3.91
- 로그인 화면 상단의 `로그인 / 회원가입` 전환은 선택된 버튼 배경이 즉시 바뀌던 방식에서, 뒤쪽 하이라이트가 토글처럼 좌우로 미끄러져 이동하는 인터랙션으로 정리함.
## 2026-04-02 v1.3.90
- 관리자 화면 CSS 경고를 줄이기 위해 `display: block` 요소에 의미 없던 `vertical-align`을 제거하고, `line-clamp` 표준 속성을 함께 선언해 VS Code 진단을 정리함.
## 2026-04-02 v1.3.89 ## 2026-04-02 v1.3.89
- 현재 코드에서 참조되지 않던 `frontend/public/icons.svg`, `frontend/src/assets/hero.png`, `frontend/src/assets/vite.svg`, `frontend/src/assets/vue.svg`를 삭제해 템플릿 잔재 자산을 정리함. - 현재 코드에서 참조되지 않던 `frontend/public/icons.svg`, `frontend/src/assets/hero.png`, `frontend/src/assets/vite.svg`, `frontend/src/assets/vue.svg`를 삭제해 템플릿 잔재 자산을 정리함.
- 홈페이지 공유용 `og-card.svg`, `og-card.png`는 이번 워크트리에서 직접 수정된 최신 이미지 상태를 그대로 반영해 함께 정리함. - 홈페이지 공유용 `og-card.svg`, `og-card.png`는 이번 워크트리에서 직접 수정된 최신 이미지 상태를 그대로 반영해 함께 정리함.

View File

@@ -67,6 +67,7 @@ const leftNavItems = computed(() => {
] ]
return items.filter((item) => !item.requiresAuth || (authReady.value && auth.user)) return items.filter((item) => !item.requiresAuth || (authReady.value && auth.user))
}) })
const activeLeftNavIndex = computed(() => leftNavItems.value.findIndex((item) => isRouteActive(item.path)))
const showRightRailAction = computed(() => false) const showRightRailAction = computed(() => false)
const showSettingsGuideButton = computed(() => route.name === 'profile') const showSettingsGuideButton = computed(() => route.name === 'profile')
const guideSteps = [ const guideSteps = [
@@ -446,7 +447,12 @@ function submitGlobalSearch() {
<input v-model="searchQuery" class="searchStub__input" type="search" :placeholder="leftRailCollapsed ? '' : leftRailSearchPlaceholder" /> <input v-model="searchQuery" class="searchStub__input" type="search" :placeholder="leftRailCollapsed ? '' : leftRailSearchPlaceholder" />
</form> </form>
<nav class="leftNav"> <nav
class="leftNav"
:class="{ 'leftNav--hasActive': activeLeftNavIndex >= 0 }"
:style="{ '--left-nav-active-index': String(Math.max(activeLeftNavIndex, 0)) }"
>
<span class="leftNav__indicator" aria-hidden="true"></span>
<RouterLink <RouterLink
v-for="item in leftNavItems" v-for="item in leftNavItems"
:key="item.key" :key="item.key"
@@ -911,19 +917,45 @@ function submitGlobalSearch() {
} }
.leftNav { .leftNav {
--left-nav-gap: 8px;
--left-nav-item-height: 50px;
position: relative;
display: grid; display: grid;
gap: 8px; gap: var(--left-nav-gap);
isolation: isolate;
}
.leftNav__indicator {
position: absolute;
top: 0;
left: 0;
right: 0;
height: var(--left-nav-item-height);
border-radius: 14px;
background: var(--theme-surface-soft-3);
transform: translateY(calc(var(--left-nav-active-index, 0) * (var(--left-nav-item-height) + var(--left-nav-gap))));
transition: transform 240ms ease, opacity 200ms ease;
opacity: 0;
z-index: 0;
pointer-events: none;
}
.leftNav--hasActive .leftNav__indicator {
opacity: 1;
} }
.leftNav__item { .leftNav__item {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
min-height: var(--left-nav-item-height);
gap: 12px; gap: 12px;
padding: 11px 12px; padding: 11px 12px;
border-radius: 14px; border-radius: 14px;
color: var(--theme-text-muted); color: var(--theme-text-muted);
text-decoration: none; text-decoration: none;
transition: background 180ms ease, color 180ms ease, transform 180ms ease; transition: background 180ms ease, color 180ms ease, transform 180ms ease;
z-index: 1;
} }
.leftNav__label { .leftNav__label {
@@ -936,7 +968,6 @@ function submitGlobalSearch() {
.leftNav__item--active, .leftNav__item--active,
.leftNav__item.router-link-active { .leftNav__item.router-link-active {
background: var(--theme-surface-soft-3);
color: var(--theme-text-strong); color: var(--theme-text-strong);
} }
@@ -999,7 +1030,7 @@ function submitGlobalSearch() {
} }
.appShell--leftCollapsed .leftNav { .appShell--leftCollapsed .leftNav {
gap: 10px; --left-nav-gap: 10px;
} }
.appShell--leftCollapsed .leftNav__item { .appShell--leftCollapsed .leftNav__item {

View File

@@ -3891,7 +3891,6 @@ function userAvatarFallback(user) {
display: block; display: block;
width: 100%; width: 100%;
line-height: 0; line-height: 0;
vertical-align: top;
} }
.adminUiScope .templateRequestCard__thumbMeta { .adminUiScope .templateRequestCard__thumbMeta {
display: grid; display: grid;
@@ -4145,6 +4144,7 @@ function userAvatarFallback(user) {
color: var(--theme-text-muted); color: var(--theme-text-muted);
line-height: 1.5; line-height: 1.5;
display: -webkit-box; display: -webkit-box;
line-clamp: 2;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;

View File

@@ -87,7 +87,8 @@ async function submit() {
</section> </section>
<section v-else class="authScreen"> <section v-else class="authScreen">
<div class="authTabs" role="tablist" aria-label="로그인 또는 회원가입"> <div class="authTabs" :class="{ 'authTabs--signup': mode === 'signup' }" role="tablist" aria-label="로그인 또는 회원가입">
<span class="authTabs__indicator" aria-hidden="true"></span>
<button type="button" class="authTabs__button" :class="{ 'authTabs__button--active': mode === 'login' }" @click="mode = 'login'"> <button type="button" class="authTabs__button" :class="{ 'authTabs__button--active': mode === 'login' }" @click="mode = 'login'">
로그인 로그인
</button> </button>
@@ -159,16 +160,37 @@ async function submit() {
} }
.authTabs { .authTabs {
position: relative;
display: inline-flex; display: inline-flex;
gap: 8px; gap: 0;
width: fit-content; width: fit-content;
padding: 6px; padding: 6px;
border-radius: 999px; border-radius: 999px;
border: 1px solid var(--theme-border); border: 1px solid var(--theme-border);
background: var(--theme-pill-bg); background: var(--theme-pill-bg);
isolation: isolate;
}
.authTabs__indicator {
position: absolute;
top: 6px;
left: 6px;
width: calc(50% - 6px);
height: calc(100% - 12px);
border-radius: 999px;
background: rgba(76, 133, 245, 0.22);
box-shadow: inset 0 0 0 1px rgba(120, 169, 255, 0.1);
transform: translateX(0);
transition: transform 220ms ease, background-color 220ms ease, box-shadow 220ms ease;
z-index: 0;
}
.authTabs--signup .authTabs__indicator {
transform: translateX(100%);
} }
.authTabs__button { .authTabs__button {
position: relative;
min-width: 112px; min-width: 112px;
padding: 10px 16px; padding: 10px 16px;
border: 0; border: 0;
@@ -177,10 +199,11 @@ async function submit() {
color: var(--theme-text-muted); color: var(--theme-text-muted);
font-weight: 700; font-weight: 700;
cursor: pointer; cursor: pointer;
transition: color 180ms ease;
z-index: 1;
} }
.authTabs__button--active { .authTabs__button--active {
background: rgba(76, 133, 245, 0.22);
color: var(--theme-text-strong); color: var(--theme-text-strong);
} }