feat: improve creator cabinet navigation
CI / test (push) Failing after 14s
CI / test (pull_request) Failing after 14s

This commit is contained in:
m
2026-08-21 03:43:58 +03:00
parent 4055319eb6
commit 301e5d0b27
4 changed files with 46 additions and 4 deletions
+3
View File
@@ -233,6 +233,9 @@ func TestConsoleAndSecurityHeaders(t *testing.T) {
response := httptest.NewRecorder()
handler.ServeHTTP(response, request)
if response.Code != http.StatusOK || !strings.Contains(response.Body.String(), "Домовой") ||
!strings.Contains(response.Body.String(), "К содержимому") ||
!strings.Contains(response.Body.String(), "aria-current=\"page\"") ||
!strings.Contains(response.Body.String(), "section-nav-link") ||
!strings.Contains(response.Body.String(), "satisfaction-dialog") || !strings.Contains(response.Body.String(), "Подтверждаю переход") ||
!strings.Contains(response.Body.String(), "action-history") || !strings.Contains(response.Body.String(), "Журнал действий") ||
!strings.Contains(response.Body.String(), "advisory-form") || !strings.Contains(response.Body.String(), "Спросить Домового") ||
+9 -3
View File
@@ -21,11 +21,13 @@
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html { background: var(--base); color: var(--ink); font-family: var(--sans); }
html { background: var(--base); color: var(--ink); font-family: var(--sans); scroll-behavior: smooth; }
body { margin: 0; min-width: 320px; min-height: 100vh; background: radial-gradient(circle at 73% -10%, rgba(83, 123, 101, .13), transparent 38%), var(--base); }
button, input, textarea { font: inherit; }
button { color: inherit; }
button:focus-visible, input:focus-visible, textarea:focus-visible { outline: 2px solid var(--signal-bright); outline-offset: 3px; }
button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible { outline: 2px solid var(--signal-bright); outline-offset: 3px; }
.skip-link { position: fixed; top: 10px; left: 10px; z-index: 30; padding: 10px 13px; color: #11150f; background: var(--signal-bright); font: 600 10px/1 var(--mono); text-decoration: none; transform: translateY(-160%); transition: transform .18s; }
.skip-link:focus { transform: translateY(0); }
.grain { position: fixed; inset: 0; pointer-events: none; opacity: .045; z-index: 10; background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.16'/%3E%3C/svg%3E"); }
.eyebrow, .rail-index { margin: 0 0 12px; color: var(--signal); font: 600 11px/1 var(--mono); letter-spacing: .18em; text-transform: uppercase; }
@@ -92,7 +94,7 @@ button:focus-visible, input:focus-visible, textarea:focus-visible { outline: 2px
.secondary-button { height: 42px; margin-top: 20px; color: #11150f; background: var(--signal); font-size: 12px; }
.section-nav { display: grid; gap: 3px; margin-top: 4px; }
.section-nav-link { display: grid; grid-template-columns: 28px 1fr; gap: 2px 10px; padding: 11px 10px; border-left: 2px solid transparent; color: var(--muted); text-decoration: none; transition: background .18s, border-color .18s, color .18s; }
.section-nav-link:hover, .section-nav-link:focus-visible, .section-nav-link.active { border-left-color: var(--signal); color: var(--ink); background: rgba(201,168,95,.07); outline: 0; }
.section-nav-link:hover, .section-nav-link:focus-visible, .section-nav-link.active, .section-nav-link[aria-current="page"] { border-left-color: var(--signal); color: var(--ink); background: rgba(201,168,95,.07); outline: 0; }
.section-nav-link span { grid-row: 1 / span 2; color: var(--signal); font: 9px/1.4 var(--mono); }
.section-nav-link b { font: 600 11px/1.2 var(--sans); }
.section-nav-link small { color: var(--faint); font: 9px/1.2 var(--mono); }
@@ -101,6 +103,7 @@ button:focus-visible, input:focus-visible, textarea:focus-visible { outline: 2px
.session-stamp strong { overflow: hidden; color: var(--muted); font: 10px/1.4 var(--mono); text-overflow: ellipsis; }
.workspace { grid-column: 2; grid-row: 2; width: min(100%, 1740px); justify-self: start; padding: 42px clamp(24px, 3vw, 48px) 64px; min-width: 0; }
.workspace > section { scroll-margin-top: 94px; }
.workspace-head { display: flex; align-items: end; justify-content: space-between; gap: 24px; margin-bottom: 34px; }
.workspace-head h1 { margin: 0; font: 400 clamp(34px, 4vw, 50px)/1 var(--serif); letter-spacing: -.035em; }
.last-update { color: var(--faint); font: 10px/1.4 var(--mono); text-align: right; }
@@ -353,6 +356,9 @@ html[data-reduced-motion="true"] *, html[data-reduced-motion="true"] *::before,
.session-stamp { margin-top: 8px; grid-template-columns: auto 1fr; align-items: center; }
.session-stamp span { margin: 0; }
.workspace { padding: 30px 16px 50px; }
.section-nav { display: flex; gap: 6px; margin: 10px -18px -24px; padding: 10px 18px; overflow-x: auto; border-top: 1px solid var(--line-soft); background: #0e1512; scrollbar-width: thin; }
.section-nav-link { min-width: 142px; padding: 10px; border-left: 0; border-bottom: 2px solid transparent; }
.section-nav-link:hover, .section-nav-link:focus-visible, .section-nav-link.active, .section-nav-link[aria-current="page"] { border-left-color: transparent; border-bottom-color: var(--signal); }
.workspace-head { align-items: start; flex-direction: column; }
.last-update { text-align: left; }
.signal-strip { grid-template-columns: 1fr; }
+32
View File
@@ -19,6 +19,38 @@ let lastAuthorizedActionID = "";
let advisoryPolicy = {Mode: "deterministic", ExternalEgress: false, AcknowledgementRequired: false};
let uiSettings = {density: "comfortable", refresh: "off", motion: false};
const sectionNavLinks = Array.from(document.querySelectorAll(".section-nav-link"));
const cabinetSections = ["overview", "diagnostics", "operations", "settings"]
.map((id) => byId(id))
.filter(Boolean);
function setActiveSection(id) {
sectionNavLinks.forEach((link) => {
const active = link.getAttribute("href") === `#${id}`;
link.classList.toggle("active", active);
if (active) link.setAttribute("aria-current", "page");
else link.removeAttribute("aria-current");
});
}
if ("IntersectionObserver" in window) {
const sectionObserver = new IntersectionObserver((entries) => {
const visible = entries.filter((entry) => entry.isIntersecting)
.sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0];
if (visible) setActiveSection(visible.target.id);
}, {rootMargin: "-18% 0px -64% 0px", threshold: [0, .25, .6, 1]});
cabinetSections.forEach((section) => sectionObserver.observe(section));
}
sectionNavLinks.forEach((link) => link.addEventListener("click", () => {
const id = link.getAttribute("href").slice(1);
setActiveSection(id);
}));
window.addEventListener("hashchange", () => {
const id = window.location.hash.slice(1);
if (cabinetSections.some((section) => section.id === id)) setActiveSection(id);
});
function setText(id, value, fallback = "—") {
byId(id).textContent = value === undefined || value === null || value === "" ? fallback : String(value);
}
+2 -1
View File
@@ -9,6 +9,7 @@
<link rel="stylesheet" href="/assets/console.css?v=20260821-context">
</head>
<body>
<a class="skip-link" href="#overview">К содержимому</a>
<div class="grain" aria-hidden="true"></div>
<main id="login-view" class="login-shell">
@@ -81,7 +82,7 @@
<div class="context-actions"><button class="secondary-button" type="submit">Загрузить контекст</button><button id="reset-context" class="text-button" type="button">Сбросить</button></div>
</form>
<nav class="section-nav" aria-label="Навигация по кабинету">
<a class="section-nav-link active" href="#overview"><span>01</span><b>Состояние</b><small>фокус и сигналы</small></a>
<a class="section-nav-link active" aria-current="page" href="#overview"><span>01</span><b>Состояние</b><small>фокус и сигналы</small></a>
<a class="section-nav-link" href="#diagnostics"><span>02</span><b>Проверки</b><small>доступность и границы</small></a>
<a class="section-nav-link" href="#operations"><span>03</span><b>Операции</b><small>ожидания и действия</small></a>
<a class="section-nav-link" href="#settings"><span>04</span><b>Настройки</b><small>интерфейс и обновление</small></a>