diff --git a/apps/web/design.md b/apps/web/design.md index dff5998..bb7288a 100644 --- a/apps/web/design.md +++ b/apps/web/design.md @@ -14,3 +14,4 @@ 국소 구현 소유자는 `src/pages/Admin.tsx`, `src/pages/admin/admin-console.css`, `src/pages/SessionReview.tsx`, `src/pages/session-review/`다. 공통 토큰과 앱 셸은 각각 `src/styles/tokens.css`, `src/components/shell/`의 소유권을 유지한다. - 2026-08-28 · `/learn` 성장 지표의 라포 헤더에서 중첩 inset surface를 제거해 같은 패널의 일반 헤더 위계와 정렬했다. 토큰 변경 없음. +- 2026-08-29 · `/teach` 검토 큐와 교수자 요약 카드를 `--sp-3` 간격으로 분리해 두 표면의 위계를 복원했다. 토큰 변경 없음. diff --git a/apps/web/e2e/full-sweep-professor.spec.ts b/apps/web/e2e/full-sweep-professor.spec.ts index 774d4af..968a15e 100644 --- a/apps/web/e2e/full-sweep-professor.spec.ts +++ b/apps/web/e2e/full-sweep-professor.spec.ts @@ -399,6 +399,14 @@ test.describe("professor console full-sweep", () => { const kpis = page.locator(".pf-kpi"); await expect(kpis).toHaveCount(6); + const triageBox = await page.locator(".pf-triage").boundingBox(); + const summaryBox = await page.getByLabel("교수자 요약").boundingBox(); + expect(triageBox).not.toBeNull(); + expect(summaryBox).not.toBeNull(); + expect( + Math.abs(summaryBox!.y - (triageBox!.y + triageBox!.height) - 12), + "검토 큐와 교수자 요약 카드 사이 간격", + ).toBeLessThanOrEqual(1); const expected: Array<[string, string]> = [ ["검토 대기", "1"], ["위기 알림", "2"], diff --git a/apps/web/e2e/layout-visual-gate.spec.ts b/apps/web/e2e/layout-visual-gate.spec.ts index 9cb68fa..0158e2b 100644 --- a/apps/web/e2e/layout-visual-gate.spec.ts +++ b/apps/web/e2e/layout-visual-gate.spec.ts @@ -313,6 +313,30 @@ async function gateScreen( } } +async function expectProfessorSummaryGap(page: Page) { + const metrics = await page.locator(".pf-signal-strip").evaluate((strip) => { + const triage = strip.querySelector(".pf-triage"); + const summary = strip.querySelector(".pf-kpis"); + if (!triage || !summary) return null; + const triageRect = triage.getBoundingClientRect(); + const summaryRect = summary.getBoundingClientRect(); + return { + actualGap: summaryRect.top - triageRect.bottom, + rowGap: Number.parseFloat(getComputedStyle(strip).rowGap), + }; + }); + const width = page.viewportSize()?.width ?? "unknown"; + expect(metrics, `[professor @ ${width}px] signal cards must be measurable`).not.toBeNull(); + expect( + Math.abs(metrics!.actualGap - 12), + `[professor @ ${width}px] rendered signal-card gap`, + ).toBeLessThanOrEqual(1); + expect( + Math.abs(metrics!.rowGap - 12), + `[professor @ ${width}px] computed signal-card row-gap`, + ).toBeLessThanOrEqual(0.1); +} + /** 리뷰는 모든 폭에서 가로 탭으로 영역을 전환한다. */ async function openReviewTabIfPresent(page: Page, label: string) { const tab = page.locator(".sr-tabs button", { hasText: label }); @@ -684,6 +708,7 @@ test.describe("layout visual gate @single-run", () => { await expect(page.locator(".pf-panel, .pf-shell, main").first()).toBeVisible({ timeout: 15_000, }); + await expectProfessorSummaryGap(page); }); }); diff --git a/apps/web/src/pages/professor.css b/apps/web/src/pages/professor.css index 72dec6d..08f97ed 100644 --- a/apps/web/src/pages/professor.css +++ b/apps/web/src/pages/professor.css @@ -40,7 +40,7 @@ order:1; display:grid; grid-template-columns:1fr; - gap:0; + gap:var(--sp-3); min-width:0; } .pf-triage{