feat(ui): 디자인 시스템 전면 개편 — 헤더·CSS·아이콘 헬퍼·클라이언트 JS
- style.css: CSS 변수(라이트/다크) 단일 스타일시트로 재작성 - _header.ejs: 스티키 다크 헤더, 실제 role 배지, FOUC 방지 테마 초기화 - helpers.js: icon(Octicon)·identicon(SVG 아바타)·langColor·langFromTags - app.js: 테마·메뉴·모달·검색/정렬/필터·반응 fetch·댓글 답글·이스터에그 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,17 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<html lang="ko" data-aidev-theme="light">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><%= brand %></title>
|
||||
<link rel="stylesheet" href="/public/style.css" />
|
||||
<script>
|
||||
// FOUC 방지: 저장된 테마를 페인트 전에 documentElement 에 적용
|
||||
(function () {
|
||||
try {
|
||||
var t = localStorage.getItem("aidev-theme");
|
||||
if (t === "dark" || t === "light") document.documentElement.setAttribute("data-aidev-theme", t);
|
||||
} catch (e) {}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<a class="brand" href="/"><span>🧠</span><%= brand %></a>
|
||||
<div class="spacer"></div>
|
||||
<% if (user) { %>
|
||||
<span class="who"><%= user.name %> (<%= user.sabun %>)</span>
|
||||
<a class="navlink" href="/logout">로그아웃</a>
|
||||
<% } %>
|
||||
</div>
|
||||
<header class="hdr">
|
||||
<div class="hdr-inner">
|
||||
<a class="brand" href="/" id="brandLink">
|
||||
<span class="brand-mark"><%- icon("code", { size: 22 }) %></span>
|
||||
<span class="brand-name"><%= brand %></span>
|
||||
<span class="brand-sub">사내 개발 포털</span>
|
||||
</a>
|
||||
|
||||
<% if (user) { %>
|
||||
<div class="hdr-search">
|
||||
<span class="hdr-search-ico"><%- icon("search", { size: 15 }) %></span>
|
||||
<input type="search" id="feedSearch" placeholder="프로젝트 검색…" autocomplete="off" />
|
||||
</div>
|
||||
|
||||
<div class="hdr-right">
|
||||
<button class="icon-btn" id="themeToggle" type="button" title="테마 전환" aria-label="테마 전환">
|
||||
<span class="theme-ico theme-ico-moon"><%- icon("moon", { size: 16 }) %></span>
|
||||
<span class="theme-ico theme-ico-sun"><%- icon("sun", { size: 16 }) %></span>
|
||||
</button>
|
||||
|
||||
<% if (user.isAdmin) { %>
|
||||
<span class="admin-pill"><%- icon("lock", { size: 11 }) %>관리자</span>
|
||||
<% } %>
|
||||
|
||||
<div class="usermenu">
|
||||
<button class="usermenu-btn" id="userMenuBtn" type="button" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="who"><%= user.sabun %></span>
|
||||
<%- identicon(user.sabun, 26) %>
|
||||
<span class="caret"><%- icon("caret", { size: 14 }) %></span>
|
||||
</button>
|
||||
<div class="usermenu-pop" id="userMenuPop" hidden>
|
||||
<div class="usermenu-head">
|
||||
<div class="usermenu-label">로그인 계정</div>
|
||||
<div class="usermenu-sabun"><%= user.sabun %></div>
|
||||
<div class="usermenu-role"><%= user.isAdmin ? "관리자 (admin)" : "일반 사용자" %></div>
|
||||
</div>
|
||||
<a class="usermenu-item" href="/logout"><span class="usermenu-ico"><%- icon("signout", { size: 15 }) %></span>로그아웃</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user