교수자 요약 카드 간격을 분리

This commit is contained in:
Yun Chan 2026-08-29 16:37:10 +09:00
parent ffadc8bd49
commit 5bf89ff4ee
4 changed files with 35 additions and 1 deletions

View file

@ -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/`의 소유권을 유지한다. 국소 구현 소유자는 `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-28 · `/learn` 성장 지표의 라포 헤더에서 중첩 inset surface를 제거해 같은 패널의 일반 헤더 위계와 정렬했다. 토큰 변경 없음.
- 2026-08-29 · `/teach` 검토 큐와 교수자 요약 카드를 `--sp-3` 간격으로 분리해 두 표면의 위계를 복원했다. 토큰 변경 없음.

View file

@ -399,6 +399,14 @@ test.describe("professor console full-sweep", () => {
const kpis = page.locator(".pf-kpi"); const kpis = page.locator(".pf-kpi");
await expect(kpis).toHaveCount(6); 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]> = [ const expected: Array<[string, string]> = [
["검토 대기", "1"], ["검토 대기", "1"],
["위기 알림", "2"], ["위기 알림", "2"],

View file

@ -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<HTMLElement>(".pf-triage");
const summary = strip.querySelector<HTMLElement>(".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) { async function openReviewTabIfPresent(page: Page, label: string) {
const tab = page.locator(".sr-tabs button", { hasText: label }); 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({ await expect(page.locator(".pf-panel, .pf-shell, main").first()).toBeVisible({
timeout: 15_000, timeout: 15_000,
}); });
await expectProfessorSummaryGap(page);
}); });
}); });

View file

@ -40,7 +40,7 @@
order:1; order:1;
display:grid; display:grid;
grid-template-columns:1fr; grid-template-columns:1fr;
gap:0; gap:var(--sp-3);
min-width:0; min-width:0;
} }
.pf-triage{ .pf-triage{