bibimbap/src/main/webapp/WEB-INF/views/header.jsp

181 lines
6.1 KiB
Plaintext

<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<jsp:include page="/WEB-INF/views/theme-init.jsp"/>
<%
jakarta.servlet.http.HttpSession headerSession = request.getSession(false);
boolean headerLoggedIn = headerSession != null && headerSession.getAttribute("userId") != null;
String headerProfileHref = request.getContextPath() + (headerLoggedIn ? "/profile" : "/login");
String headerProfileLabel = headerLoggedIn ? "프로필" : "로그인";
%>
<style>
/* 기본(라이트) 헤더 — data-theme 없을 때도 동일 톤 */
.site-header {
--header-bg: #ffffff;
--header-text: #1a1a1a;
--header-muted: rgba(26, 26, 26, 0.55);
--header-border: rgba(0, 0, 0, 0.08);
--header-btn-hover: rgba(0, 0, 0, 0.06);
box-shadow: 0 1px 0 var(--header-border), 0 4px 16px rgba(0, 0, 0, 0.06);
}
html[data-theme="dark"] .site-header {
--header-bg: #1a1a1a;
--header-text: #f5f0e8;
--header-muted: rgba(245, 240, 232, 0.65);
--header-border: rgba(255, 255, 255, 0.06);
--header-btn-hover: rgba(255, 255, 255, 0.08);
box-shadow: 0 1px 0 var(--header-border), 0 8px 24px rgba(0, 0, 0, 0.35);
}
.site-header {
--accent: #e8a54b;
--header-h: 4rem;
background: var(--header-bg);
color: var(--header-text);
position: sticky;
top: 0;
z-index: 100;
}
.site-header__inner {
max-width: 72rem;
margin: 0 auto;
padding: 0 max(1rem, env(safe-area-inset-left)) 0 max(1rem, env(safe-area-inset-right));
height: var(--header-h);
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.site-header__brand {
display: flex;
align-items: center;
gap: 0.75rem;
text-decoration: none;
color: inherit;
font-weight: 600;
letter-spacing: -0.02em;
font-size: 1.125rem;
min-width: 0;
}
.site-header__brand:hover {
color: var(--accent);
}
.site-header__logo {
height: 2.25rem;
width: auto;
display: block;
border-radius: 6px;
object-fit: contain;
flex-shrink: 0;
}
.site-header__actions {
display: flex;
align-items: center;
gap: 0.375rem;
flex-shrink: 0;
}
.site-header__icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.75rem;
height: 2.75rem;
padding: 0;
border: none;
border-radius: 10px;
background: transparent;
color: inherit;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
transition: background 0.15s ease;
}
.site-header__icon-btn:hover {
background: var(--header-btn-hover);
}
.site-header__icon-btn:active {
transform: scale(0.96);
}
.site-header__icon-btn svg {
width: 1.375rem;
height: 1.375rem;
}
.site-header__icon-btn .icon-sun {
display: none;
}
.site-header__icon-btn .icon-moon {
display: block;
}
html[data-theme="dark"] .site-header__icon-btn .icon-moon {
display: none;
}
html[data-theme="dark"] .site-header__icon-btn .icon-sun {
display: block;
}
.site-header__profile {
display: inline-flex;
align-items: center;
justify-content: center;
width: 2.75rem;
height: 2.75rem;
border-radius: 50%;
background: var(--header-btn-hover);
color: var(--header-text);
text-decoration: none;
transition: background 0.15s ease, transform 0.15s ease;
-webkit-tap-highlight-color: transparent;
}
.site-header__profile:hover {
background: var(--accent);
color: #1a1a1a;
}
.site-header__profile:active {
transform: scale(0.96);
}
.site-header__profile svg {
width: 1.35rem;
height: 1.35rem;
}
</style>
<header class="site-header" role="banner">
<div class="site-header__inner">
<a class="site-header__brand" href="${pageContext.request.contextPath}/">
<img class="site-header__logo" src="${pageContext.request.contextPath}/images/logo.png" alt="" width="120" height="36" />
<span>bibimbap</span>
</a>
<div class="site-header__actions">
<button type="button" class="site-header__icon-btn" id="theme-toggle" aria-label="다크 모드로 전환" title="테마 전환">
<%-- 라이트 모드일 때 달(다크로), 다크 모드일 때 해(라이트로) --%>
<svg class="icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
<svg class="icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/>
</svg>
</button>
<a class="site-header__profile" href="<%= headerProfileHref %>" aria-label="<%= headerProfileLabel %>" title="<%= headerProfileLabel %>">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
<circle cx="12" cy="7" r="4"/>
</svg>
</a>
</div>
</div>
</header>
<jsp:include page="/WEB-INF/views/modal.jsp"/>
<script>
(function () {
var btn = document.getElementById('theme-toggle');
if (!btn) return;
function label() {
var dark = document.documentElement.getAttribute('data-theme') === 'dark';
btn.setAttribute('aria-label', dark ? '라이트 모드로 전환' : '다크 모드로 전환');
btn.setAttribute('title', dark ? '라이트 모드' : '다크 모드');
}
label();
btn.addEventListener('click', function () {
var next = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
try { localStorage.setItem('bibimbap-theme', next); } catch (e) {}
label();
});
})();
</script>