Animate page navigation with content
This commit is contained in:
parent
624f62f25e
commit
825f261354
6 changed files with 19 additions and 12 deletions
|
|
@ -17,7 +17,7 @@ UI не содержит языко-зависимых служебных под
|
|||
|
||||
На десктопе компактный header содержит toggle боковой панели, полное название документации, поиск и переключатель темы. Sidebar по умолчанию открыт, его состояние не сохраняется между загрузками. Поисковый placeholder медленно печатает первые слова случайного названия, добавляет троеточие только в конце и сохраняет готовый текст 5 секунд; при вводе поле раскрывает ранжированные результаты вниз. Проверка manifest выполняется автоматически в фоне без отдельной кнопки обновления.
|
||||
|
||||
На мобильных устройствах используется viewport `100dvh` и нижний dock. Кнопка `☰` заменяет содержимое страницы копией desktop-sidebar, которая выезжает с левой границы экрана. Ввод в нижний поиск заменяет содержимое результатами, расположенными снизу вверх по релевантности. При переходе между страницами контент плавно смещается на 30 px по направлению навигации и меняет прозрачность; тема и обновление на мобильном скрыты.
|
||||
На мобильных устройствах используется viewport `100dvh` и нижний dock. Кнопка `☰` заменяет содержимое страницы копией desktop-sidebar, которая выезжает с левой границы экрана. Ввод в нижний поиск заменяет содержимое результатами, расположенными снизу вверх по релевантности. При переходе между страницами контент вместе с кнопками предыдущей и следующей страницы плавно смещается на 30 px по направлению навигации и меняет прозрачность; тема и обновление на мобильном скрыты.
|
||||
|
||||
## Установка из Git
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
"""Single source of truth for the SharedDocsLib package version."""
|
||||
|
||||
__version__ = "0.4.0"
|
||||
__version__ = "0.4.1"
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ body.desktop-sidebar-collapsed .desktop-sidebar { width: 0; flex-basis: 0; paddi
|
|||
@keyframes refresh-spin { to { transform: rotate(360deg); } }
|
||||
|
||||
.page-surface { min-height: 0; flex: 1; overflow-x: hidden; overflow-y: auto; overscroll-behavior-y: contain; border-radius: 36px 0 0; background: var(--surface); scroll-behavior: smooth; -webkit-overflow-scrolling: touch; }
|
||||
.page-transition { min-width: 0; }
|
||||
.content { width: min(1120px, calc(100% - 72px)); margin: 0 auto; padding: 42px 0 44px; outline: none; }
|
||||
.content > :first-child { margin-top: 0; }
|
||||
.content h1 { margin: 0 0 1.5rem; font-size: clamp(2.15rem, 2.7vw, 3.35rem); font-weight: 400; line-height: 1.08; letter-spacing: -.035em; }
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
mobileSearchButton: document.getElementById("mobile-search-button"),
|
||||
mobileSearchResults: document.getElementById("mobile-search-results"),
|
||||
content: document.getElementById("content"),
|
||||
pageTransition: document.getElementById("page-transition"),
|
||||
pageSurface: document.getElementById("page-surface"),
|
||||
previous: document.getElementById("previous-page"),
|
||||
next: document.getElementById("next-page"),
|
||||
|
|
@ -384,13 +385,13 @@
|
|||
|
||||
const currentIndex = manifest.pages.findIndex((candidate) => candidate.number === currentNumber);
|
||||
const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1;
|
||||
const animate = currentIndex >= 0 && !reducedMotion.matches && typeof elements.content.animate === "function";
|
||||
const animate = currentIndex >= 0 && !reducedMotion.matches && typeof elements.pageTransition.animate === "function";
|
||||
const transitionId = ++pageTransitionId;
|
||||
|
||||
pageAnimation?.cancel();
|
||||
pageAnimation = null;
|
||||
if (animate) {
|
||||
const outgoing = elements.content.animate(
|
||||
const outgoing = elements.pageTransition.animate(
|
||||
[
|
||||
{ opacity: 1, transform: "translateX(0)" },
|
||||
{ opacity: 0, transform: `translateX(${-30 * direction}px)` },
|
||||
|
|
@ -405,7 +406,7 @@
|
|||
|
||||
applyPage(page, index);
|
||||
if (!animate || transitionId !== pageTransitionId) return;
|
||||
const incoming = elements.content.animate(
|
||||
const incoming = elements.pageTransition.animate(
|
||||
[
|
||||
{ opacity: 0, transform: `translateX(${30 * direction}px)` },
|
||||
{ opacity: 1, transform: "translateX(0)" },
|
||||
|
|
|
|||
|
|
@ -51,11 +51,13 @@
|
|||
<section class="workspace">
|
||||
|
||||
<section id="page-surface" class="page-surface">
|
||||
<main id="content" class="content" tabindex="-1"></main>
|
||||
<footer class="page-navigation">
|
||||
<button id="previous-page" class="nav-card"></button>
|
||||
<button id="next-page" class="nav-card"></button>
|
||||
</footer>
|
||||
<div id="page-transition" class="page-transition">
|
||||
<main id="content" class="content" tabindex="-1"></main>
|
||||
<footer class="page-navigation">
|
||||
<button id="previous-page" class="nav-card"></button>
|
||||
<button id="next-page" class="nav-card"></button>
|
||||
</footer>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="mobile-menu-view" class="mobile-view mobile-menu-view">
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
|||
assert html_response.status_code == 200
|
||||
assert "http://127.0.0.1:9000/manifest.json" in html
|
||||
assert "http://127.0.0.1:9000/version" in html
|
||||
assert 'globalThis.COMPILED_FROM_VERSION = "0.4.0";' in html
|
||||
assert 'globalThis.COMPILED_FROM_VERSION = "0.4.1";' in html
|
||||
assert ".content { --custom-test: yes; }" in html
|
||||
assert r'document.body.dataset.customTest = \"yes\";' in html
|
||||
assert 'id="docslib-loading"' in html
|
||||
|
|
@ -177,6 +177,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
|||
assert "--shell: #000000" in html
|
||||
assert 'id="desktop-search-input"' in html
|
||||
assert '<header class="desktop-header">' in html
|
||||
assert 'id="page-transition" class="page-transition"' in html
|
||||
assert 'id="desktop-sidebar-toggle"' in html
|
||||
assert 'aria-label="☰" aria-expanded="true">☰</button>' in html
|
||||
assert '<aside class="desktop-sidebar">' in html
|
||||
|
|
@ -213,6 +214,8 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
|||
assert "animation: mobile-menu-enter .26s" in html
|
||||
assert "transform: translateX(-100%)" in html
|
||||
assert "const direction = currentIndex >= 0 && index < currentIndex ? -1 : 1" in system_js
|
||||
assert 'const outgoing = elements.pageTransition.animate(' in system_js
|
||||
assert 'const incoming = elements.pageTransition.animate(' in system_js
|
||||
assert 'transform: `translateX(${-30 * direction}px)`' in system_js
|
||||
assert 'transform: `translateX(${30 * direction}px)`' in system_js
|
||||
assert 'opacity: 0' in system_js
|
||||
|
|
@ -232,7 +235,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
|||
|
||||
|
||||
def test_build_writes_static_bundle(tmp_path):
|
||||
assert __version__ == "0.4.0"
|
||||
assert __version__ == "0.4.1"
|
||||
|
||||
@Page("1", "Static page")
|
||||
def static_page():
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue