fix(site): 모바일 헤더 재설계 — 크럼이 아니라 브랜드+액션 한 줄(v24)
v23 은 구조(단일 sticky 바)만 맞고 시각적 무게가 틀렸다 — 작은 회색 크럼 텍스트가 52px 바에 혼자 떠 있는 빈약한 헤더였다. 계측이 전부 통과해도 보기에 빈약하면 실패다. - 탑바에 브랜드(가 모노그램 타일+이름)를 이어받게 하고 크럼은 모바일에서 숨김 — 두레 앱바와 같은 문법(브랜드+액션). 화면 이름은 각 뷰 헤드와 활성 탭이 말한다 - 검증: 360/390/412px 오버플로 0·브랜드 노출, 스크롤 800에서 top=0, 탭 전환 scrollY=0, 비전 검수 통과, 시각 기준 갱신 후 verify L0~L6 전 통과 - 스킬 mobile-app-ux.md 규칙 갱신: 크럼 내보내기 금지 + 계측 통과에도 눈으로 봐야 한다
|
|
@ -834,3 +834,10 @@ max-age=0 지정(존 설정이 우선하면 효과는 제한적). **운칙: /wor
|
|||
- **탭 전환 스크롤 잔류** — setCurrentView 는 focus({preventScroll:true}) 였지만 이전 뷰의 window.scrollY 가 그대로 남아, 새 뷰가 짧으면 브라우저가 클램프(600→49)해 헤더가 반쯤 잘리고 길면 화면 중간에 떨어졌다. 뷰마다 크롬 위치가 제각각 = "왔다갔다". 수리: setCurrentView 마지막에 window.scrollTo(0,0) (양앱).
|
||||
- **모바일 헤더 이중 스택** — ≤900에서 브랜드 줄(.side 43px)+크럼 탑바(52px)=95px 크롬이 쌓이고 둘 다 static 이라 스크롤하면 떠내려가며, safe-top 도 없었다. 수리: ≤900에서 .side 숨김(크럼이 브랜드명을 이미 담음 — 중복), .topbar 를 sticky top:0 + safe-top 패딩의 단일 헤더로(두레 앱바와 같은 문법). 데스크톱(>900) 무변경.
|
||||
- 재발 방지: e2e.mjs M5 헤더·스크롤 스위트 10단언(헤더 sticky·상단 박착, 300px+ 스크롤에서 탭 전환 → scrollY=0·헤더 top=0). 시각 기준 갱신(390px 9화면 의도 변경), verify L0~L6 재통과. 스킬 mobile-app-ux.md 에 "뷰 전환은 스크롤을 리셋·헤더는 하나" 규칙 반영.
|
||||
|
||||
## 2026-08-23 — 국소: 모바일 헤더 재설계(v24) — 크럼이 아니라 브랜드다
|
||||
|
||||
v23 스크롤 리셋·단일 헤더에도 사용자 평가가 "여전히 깨져 보인다"였다. 에뮬레이터에서 라이브 URL로 재확인한 결과 구조(단일 sticky 바)는 맞았지만 **시각적 무게가 틀렸다** — 작은 회색 크럼 텍스트("가온 학적부 / 대시보기")가 52px 바에 혼자 떠 있고 브랜드 마크는 사라진, 빈약한 헤더였다. 계측 전부 통과해도 보기에 빈약하면 실패다.
|
||||
- 수리: 모바일 헤더를 **브랜드(가 모노그램 타일+이름)+액션(인쇄·종) 한 줄**로 — 두레 앱바와 같은 문법. 탑바에 브랜드를 이어받게(데스크톱은 사이드바 브랜드, 모바일은 탑바 브랜드 — CSS display 로 한쪽만 노출), 크럼은 모바일에서 숨김(화면 이름은 각 뷰 헤드와 활성 탭이 말한다). min-height 56px, sticky+safe-top 유지.
|
||||
- 검증: 360/390/412px 오버플로 0·브랜드 노출·크럼/사이드 숨김 실측, 스크롤 800에서 탑바 top=0, 탭 전환 scrollY=0. 비전 검수 "확신 있는 앱 헤더·패딩 정상". 시각 기준 갱신(390px), verify L0~L6 재통과.
|
||||
- 스킬 규칙 갱신: "크럼을 헤더로 내보내면 빈약해 보인다 — 모바일 헤더는 브랜드+액션, 계측이 통과해도 눈으로 봐야 한다".
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Noto+Serif+KR:wght@500;600&display=swap"
|
||||
/>
|
||||
<link rel="stylesheet" href="./styles/main.css?v=23" />
|
||||
<link rel="stylesheet" href="./styles/main.css?v=24" />
|
||||
<link
|
||||
rel="icon"
|
||||
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23fafafa'/%3E%3Crect x='6.5' y='6.5' width='19' height='19' rx='4' fill='%23059669'/%3E%3Crect x='10' y='12' width='12' height='1.8' rx='0.9' fill='%23ffffff'/%3E%3Crect x='10' y='15.5' width='8' height='1.8' rx='0.9' fill='%23ffffff' opacity='0.85'/%3E%3Crect x='10' y='19' width='10' height='1.8' rx='0.9' fill='%23ffffff' opacity='0.7'/%3E%3C/svg%3E"
|
||||
|
|
@ -97,6 +97,7 @@
|
|||
|
||||
<main id="main" class="main">
|
||||
<div class="topbar">
|
||||
<a class="brand" href="#main"><span class="brand-mark" aria-hidden="true"></span>가온 학적부</a>
|
||||
<p class="crumb">가온 학적부 <span aria-hidden="true">/</span> <strong id="crumb-view">대시보드</strong></p>
|
||||
<div class="topbar-right">
|
||||
<span class="term-badge mono">2026학년도 1학기 · 3월 2주차</span>
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ h3 { font-size: var(--step-0); font-weight: 500; }
|
|||
background: var(--background);
|
||||
flex: none;
|
||||
}
|
||||
.topbar .brand { display: none; } /* 브랜드는 사이드바에 있다 — 모바일에서만 탑바가 이어받는다 */
|
||||
.crumb { display: flex; align-items: center; gap: var(--space-2); font-size: var(--step-0); color: var(--muted-foreground); }
|
||||
.crumb strong { color: var(--foreground); font-weight: 600; }
|
||||
.topbar-right { display: flex; align-items: center; gap: var(--space-3); }
|
||||
|
|
@ -600,16 +601,18 @@ tbody tr:hover { background: var(--muted); }
|
|||
/* ── 반응형 ── */
|
||||
@media (max-width: 900px) {
|
||||
.app { grid-template-columns: minmax(0, 1fr); }
|
||||
/* 모바일 앱 헤더 — 내비는 바텀 탭으로(HIG·M3). 헤더는 크럼 탑바 하나다:
|
||||
브랜드 줄(사이드)과 크럼이 서로 중복하는 데다 95px 크롬을 쌓아 옥에 끼는 느낌을 냈다.
|
||||
/* 모바일 앱 헤더 — 내비는 바텀 탭으로(HIG·M3). 헤더는 브랜드+액션 한 줄(두레 앱바 문법):
|
||||
화면 이름은 각 뷰 헤드와 활성 탭이 말하므로 크럼은 데스크톱 문법이다.
|
||||
탑바가 sticky 로 상단에 남고, safe-top 으로 노치/상태바를 피한다 */
|
||||
.side { display: none; }
|
||||
.topbar {
|
||||
position: sticky; top: 0; z-index: 40;
|
||||
height: auto; min-height: 52px; min-width: 0;
|
||||
height: auto; min-height: 56px; min-width: 0;
|
||||
padding: 0 max(var(--space-4), var(--safe-right)) 0 max(var(--space-4), var(--safe-left));
|
||||
padding-top: max(0px, var(--safe-top));
|
||||
}
|
||||
.topbar .brand { display: flex; flex: none; padding: 0; }
|
||||
.crumb { display: none; }
|
||||
.main { padding-bottom: calc(72px + var(--safe-bottom)); } /* 바텀 내비 + 홈 인디케이터 확보 */
|
||||
.dash-grid, .cal-layout, .counsel-grid { grid-template-columns: minmax(0, 1fr); }
|
||||
.week-panel { grid-row: auto; }
|
||||
|
|
@ -618,7 +621,6 @@ tbody tr:hover { background: var(--muted); }
|
|||
.view > *:not(.view-head) { margin-inline: var(--space-4); }
|
||||
.headline { gap: var(--space-2); }
|
||||
.term-badge { display: none; }
|
||||
.crumb { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.cal-day { height: 56px; }
|
||||
}
|
||||
@media (max-width: 680px) {
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 52 KiB |
BIN
apps/site/tools/__shots__/diag2-gaon-390-attendance.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
apps/site/tools/__shots__/diag2-gaon-390.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
|
|
@ -1,6 +1,6 @@
|
|||
# E2E 시나리오 게이트 — 2026-08-23 05:48
|
||||
# E2E 시나리오 게이트 — 2026-08-23 06:12
|
||||
|
||||
단언 1754 · 통과 1754 · 실패 0 — **GREEN — 전 단언 통과**
|
||||
단언 1745 · 통과 1745 · 실패 0 — **GREEN — 전 단언 통과**
|
||||
|
||||
| 스위트 | 통과 | 실패 |
|
||||
|---|---|---|
|
||||
|
|
@ -8,8 +8,8 @@
|
|||
| M5 헤더·스크롤 | 10 | 0 |
|
||||
| M320 매트릭스 | 90 | 0 |
|
||||
| M390 매트릭스 | 105 | 0 |
|
||||
| M1 터치타깃 | 222 | 0 |
|
||||
| M2 대비 | 1111 | 0 |
|
||||
| M1 터치타깃 | 231 | 0 |
|
||||
| M2 대비 | 1093 | 0 |
|
||||
| M768 매트릭스 | 90 | 0 |
|
||||
| S7 뒤로 가기 | 6 | 0 |
|
||||
| S7 뒤로 가기·모달 | 5 | 0 |
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
# 검증 리포트 — 2026-08-23 05:48
|
||||
# 검증 리포트 — 2026-08-23 06:12
|
||||
|
||||
게이트: **전 계층 통과 — 배포 가능** · 총 85.9초
|
||||
게이트: **전 계층 통과 — 배포 가능** · 총 88.1초
|
||||
|
||||
| 계층 | 결과 | 항목 | 소요 |
|
||||
|---|---|---|---|
|
||||
| L0-정적/stylelint | PASS | PASS — | 1.4s |
|
||||
| L0-정식/html-validate | PASS | PASS — | 1.2s |
|
||||
| L1-단위/계산로직 | PASS | PASS 41 | 0.0s |
|
||||
| L2-기능/감사 | PASS | PASS 72 | 9.6s |
|
||||
| L2-불변식/렌더 | PASS | PASS 10 | 16.9s |
|
||||
| L3-시각회귀/diff | PASS | PASS 30 | 11.3s |
|
||||
| L4-WebKit | PASS | PASS 8 | 3.5s |
|
||||
| L5-탐색/키보드 | PASS | PASS 14 | 6.3s |
|
||||
| L6-시나리오/E2E | PASS | PASS — | 35.5s |
|
||||
| L0-정적/stylelint | PASS | PASS — | 1.7s |
|
||||
| L0-정식/html-validate | PASS | PASS — | 1.3s |
|
||||
| L1-단위/계산로직 | PASS | PASS 41 | 0.1s |
|
||||
| L2-기능/감사 | PASS | PASS 72 | 10.1s |
|
||||
| L2-불변식/렌더 | PASS | PASS 10 | 17.6s |
|
||||
| L3-시각회귀/diff | PASS | PASS 30 | 11.5s |
|
||||
| L4-WebKit | PASS | PASS 8 | 3.9s |
|
||||
| L5-탐색/키보드 | PASS | PASS 14 | 6.2s |
|
||||
| L6-시나리오/E2E | PASS | PASS — | 35.7s |
|
||||
|
|
|
|||