fix: 로그아웃을 사이드바 하단 상시 노출 버튼으로 변경
기존 드롭다운 메뉴 안에 숨어 보이지 않던 로그아웃을 항상 노출되는 버튼으로 변경한다. - 사용자 프로필 행은 표시 전용, 아래에 로그아웃 버튼 상시 노출(빨강 호버) - 접힘 시 아이콘만 표시 - 미사용 드롭다운(menuOpen·me-menu·me-overlay) 로직/스타일 제거 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,9 +35,6 @@ const activeNav = computed<'tasks' | 'projects'>(() =>
|
||||
// 현재 로그인 사용자(프로필 아바타는 UserAvatar 가 이미지/placeholder 로 표시)
|
||||
const me = computed(() => authStore.user)
|
||||
|
||||
// 사용자 메뉴 토글
|
||||
const menuOpen = ref(false)
|
||||
|
||||
// --- 알림(실시간 SSE) ---
|
||||
const notiStore = useNotificationStore()
|
||||
const {
|
||||
@@ -73,7 +70,6 @@ onMounted(() => {
|
||||
|
||||
// 로그아웃 → 알림 스트림 해제 후 로그인 화면으로
|
||||
async function onLogout() {
|
||||
menuOpen.value = false
|
||||
notiStore.disconnect()
|
||||
await authStore.logout()
|
||||
await router.push('/login')
|
||||
@@ -198,14 +194,9 @@ async function onLogout() {
|
||||
><path d="M15 18l-6-6 6-6" /></svg>
|
||||
<span>사이드바 접기</span>
|
||||
</button>
|
||||
<button
|
||||
class="side-me"
|
||||
type="button"
|
||||
<div
|
||||
class="side-user"
|
||||
:title="me?.name ?? '사용자'"
|
||||
:aria-label="`${me?.name ?? '사용자'} 메뉴`"
|
||||
aria-haspopup="menu"
|
||||
:aria-expanded="menuOpen"
|
||||
@click="menuOpen = !menuOpen"
|
||||
>
|
||||
<UserAvatar
|
||||
:url="me?.avatarUrl"
|
||||
@@ -215,27 +206,29 @@ async function onLogout() {
|
||||
<span class="side-me-name">{{ me?.name }}</span>
|
||||
<span class="side-me-email">{{ me?.email }}</span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div
|
||||
v-if="menuOpen"
|
||||
class="me-menu side-menu"
|
||||
role="menu"
|
||||
>
|
||||
<button
|
||||
class="me-action"
|
||||
type="button"
|
||||
role="menuitem"
|
||||
@click="onLogout"
|
||||
>
|
||||
로그아웃
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
v-if="menuOpen"
|
||||
class="me-overlay"
|
||||
@click="menuOpen = false"
|
||||
/>
|
||||
|
||||
<button
|
||||
class="logout-btn"
|
||||
type="button"
|
||||
title="로그아웃"
|
||||
aria-label="로그아웃"
|
||||
@click="onLogout"
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
||||
<path d="M16 17l5-5-5-5" />
|
||||
<path d="M21 12H9" />
|
||||
</svg>
|
||||
<span>로그아웃</span>
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -451,7 +444,7 @@ async function onLogout() {
|
||||
.shell.collapsed .nav-item span {
|
||||
display: none;
|
||||
}
|
||||
.shell.collapsed .side-me {
|
||||
.shell.collapsed .side-user {
|
||||
justify-content: center;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
@@ -459,6 +452,14 @@ async function onLogout() {
|
||||
.shell.collapsed .side-me-text {
|
||||
display: none;
|
||||
}
|
||||
.shell.collapsed .logout-btn {
|
||||
justify-content: center;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.shell.collapsed .logout-btn span {
|
||||
display: none;
|
||||
}
|
||||
.shell.collapsed .collapse-btn {
|
||||
justify-content: center;
|
||||
padding-left: 0;
|
||||
@@ -470,11 +471,6 @@ async function onLogout() {
|
||||
.shell.collapsed .collapse-btn svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
/* 접힘 상태에서 사용자 메뉴는 레일 오른쪽으로 펼침 */
|
||||
.shell.collapsed .side-menu {
|
||||
left: 0.5rem;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
@@ -569,25 +565,44 @@ async function onLogout() {
|
||||
flex-shrink: 0;
|
||||
transition: transform 0.18s ease;
|
||||
}
|
||||
.side-me {
|
||||
.side-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5625rem;
|
||||
width: 100%;
|
||||
padding: 0.4375rem 0.5rem;
|
||||
}
|
||||
.side-user > :first-child {
|
||||
width: 1.875rem;
|
||||
height: 1.875rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
/* 로그아웃 — 항상 노출되는 버튼 */
|
||||
.logout-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.6875rem;
|
||||
width: 100%;
|
||||
margin-top: 0.25rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: var(--radius);
|
||||
color: var(--text-2);
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
text-align: left;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.side-me:hover {
|
||||
background: #f1f2f4;
|
||||
.logout-btn:hover {
|
||||
background: var(--red-weak);
|
||||
color: var(--red);
|
||||
}
|
||||
.side-me > :first-child {
|
||||
width: 1.875rem;
|
||||
height: 1.875rem;
|
||||
.logout-btn svg {
|
||||
width: 1.125rem;
|
||||
height: 1.125rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.side-me-text {
|
||||
@@ -823,43 +838,6 @@ async function onLogout() {
|
||||
z-index: 55;
|
||||
}
|
||||
|
||||
/* 사용자 드롭다운(사이드바 하단 → 위로 펼침) */
|
||||
.me-menu {
|
||||
position: absolute;
|
||||
z-index: 60;
|
||||
min-width: 11rem;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||
overflow: hidden;
|
||||
}
|
||||
.side-menu {
|
||||
left: 0.625rem;
|
||||
right: 0.625rem;
|
||||
bottom: calc(100% - 0.25rem);
|
||||
}
|
||||
.me-action {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 0.625rem 0.875rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: 0.844rem;
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
}
|
||||
.me-action:hover {
|
||||
background: #f1f2f4;
|
||||
}
|
||||
/* 메뉴 바깥 클릭 감지용 투명 오버레이 */
|
||||
.me-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 55;
|
||||
}
|
||||
|
||||
/* 햄버거(모바일 전용) / 드로어 배경 — 데스크톱에서는 숨김 */
|
||||
.hamburger {
|
||||
display: none;
|
||||
@@ -896,7 +874,8 @@ async function onLogout() {
|
||||
/* 접힘 축소 규칙 무효화(드로어는 항상 펼친 모양) */
|
||||
.shell.collapsed .brand,
|
||||
.shell.collapsed .nav-item,
|
||||
.shell.collapsed .side-me,
|
||||
.shell.collapsed .side-user,
|
||||
.shell.collapsed .logout-btn,
|
||||
.shell.collapsed .collapse-btn {
|
||||
justify-content: flex-start;
|
||||
padding-left: 0.75rem;
|
||||
@@ -904,7 +883,7 @@ async function onLogout() {
|
||||
}
|
||||
.shell.collapsed .brand-name,
|
||||
.shell.collapsed .nav-item span,
|
||||
.shell.collapsed .side-me-text {
|
||||
.shell.collapsed .logout-btn span {
|
||||
display: inline;
|
||||
}
|
||||
.shell.collapsed .side-me-text {
|
||||
@@ -913,6 +892,10 @@ async function onLogout() {
|
||||
.shell.collapsed .brand {
|
||||
padding-left: 1.125rem;
|
||||
}
|
||||
.shell.collapsed .side-user {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
.sidebar-backdrop {
|
||||
display: block;
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user