Draw navigation arrows with CSS borders
This commit is contained in:
parent
df68cae94b
commit
06032e6800
7 changed files with 18 additions and 14 deletions
|
|
@ -13,7 +13,7 @@ SharedDocsLib — небольшой Python-фреймворк для докум
|
||||||
- `index.zip`, содержащий только `index.html`;
|
- `index.zip`, содержащий только `index.html`;
|
||||||
- live-preview с перекомпиляцией изменившегося Python-модуля.
|
- live-preview с перекомпиляцией изменившегося Python-модуля.
|
||||||
|
|
||||||
UI не содержит языко-зависимых служебных подписей. Базовый шрифт — `system-ui 16px`; служебные UTF-8-пиктограммы используют Arial, а навигационные стрелки остаются в `system-ui`. AMOLED-тема включена по умолчанию и сохраняется локально после переключения.
|
UI не содержит языко-зависимых служебных подписей. Базовый шрифт — `system-ui 16px`, а служебные UTF-8-пиктограммы используют Arial. Навигационные стрелки отрисовываются CSS-границами без текстовых символов. AMOLED-тема включена по умолчанию и сохраняется локально после переключения.
|
||||||
|
|
||||||
На десктопе компактный header содержит полное название документации, поиск и переключатель темы, а слева постоянно видны header-кнопки и дерево страниц. Поисковый placeholder медленно печатает первые слова случайного названия, добавляет троеточие только в конце и сохраняет готовый текст 5 секунд; при вводе поле раскрывает ранжированные результаты вниз. Проверка manifest выполняется автоматически в фоне без отдельной кнопки обновления.
|
На десктопе компактный header содержит полное название документации, поиск и переключатель темы, а слева постоянно видны header-кнопки и дерево страниц. Поисковый placeholder медленно печатает первые слова случайного названия, добавляет троеточие только в конце и сохраняет готовый текст 5 секунд; при вводе поле раскрывает ранжированные результаты вниз. Проверка manifest выполняется автоматически в фоне без отдельной кнопки обновления.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,4 @@ from .server import build, create_app, run
|
||||||
from .ui import HeaderButton
|
from .ui import HeaderButton
|
||||||
|
|
||||||
__all__ = ["Component", "HeaderButton", "Page", "build", "create_app", "run"]
|
__all__ = ["Component", "HeaderButton", "Page", "build", "create_app", "run"]
|
||||||
__version__ = "0.3.3"
|
__version__ = "0.3.4"
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ button, input { font: inherit; }
|
||||||
button, a { -webkit-tap-highlight-color: transparent; }
|
button, a { -webkit-tap-highlight-color: transparent; }
|
||||||
button { color: inherit; }
|
button { color: inherit; }
|
||||||
.glyph-button, .refresh-glyph { font-family: Arial, sans-serif; }
|
.glyph-button, .refresh-glyph { font-family: Arial, sans-serif; }
|
||||||
.nav-arrow { font-family: system-ui; }
|
|
||||||
|
|
||||||
.app-shell { --desktop-sidebar-width: clamp(270px, 25vw, 400px); display: flex; width: 100%; height: 100%; flex-direction: column; overflow: hidden; background: var(--shell); }
|
.app-shell { --desktop-sidebar-width: clamp(270px, 25vw, 400px); display: flex; width: 100%; height: 100%; flex-direction: column; overflow: hidden; background: var(--shell); }
|
||||||
.desktop-header { position: relative; z-index: 20; display: grid; min-height: 76px; flex: 0 0 76px; grid-template-columns: minmax(260px, 1fr) auto; align-items: center; gap: 18px; padding: 12px 20px; background: var(--shell); }
|
.desktop-header { position: relative; z-index: 20; display: grid; min-height: 76px; flex: 0 0 76px; grid-template-columns: minmax(260px, 1fr) auto; align-items: center; gap: 18px; padding: 12px 20px; background: var(--shell); }
|
||||||
|
|
@ -128,7 +127,9 @@ button { color: inherit; }
|
||||||
.nav-card { display: flex; min-height: 48px; align-items: center; gap: 8px; padding: 7px 20px; border: 0; border-radius: 30px; color: var(--text); background: var(--control); cursor: pointer; }
|
.nav-card { display: flex; min-height: 48px; align-items: center; gap: 8px; padding: 7px 20px; border: 0; border-radius: 30px; color: var(--text); background: var(--control); cursor: pointer; }
|
||||||
.nav-card:hover:not(:disabled) { background: var(--active); }
|
.nav-card:hover:not(:disabled) { background: var(--active); }
|
||||||
.nav-card:disabled { display: none; }
|
.nav-card:disabled { display: none; }
|
||||||
.nav-card small { color: inherit; font-size: 1.3rem; }
|
.nav-arrow { display: block; width: 10px; height: 10px; flex: 0 0 10px; border: 0 solid currentColor; transform: rotate(45deg); }
|
||||||
|
.nav-arrow-previous { border-bottom-width: 2px; border-left-width: 2px; }
|
||||||
|
.nav-arrow-next { border-top-width: 2px; border-right-width: 2px; }
|
||||||
#next-page { color: var(--shell); background: var(--text); }
|
#next-page { color: var(--shell); background: var(--text); }
|
||||||
:root[data-theme="dark"] #next-page { color: #000; background: #eee; }
|
:root[data-theme="dark"] #next-page { color: #000; background: #eee; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,12 +228,12 @@
|
||||||
button.disabled = !page;
|
button.disabled = !page;
|
||||||
button.replaceChildren();
|
button.replaceChildren();
|
||||||
if (!page) return;
|
if (!page) return;
|
||||||
const arrow = document.createElement("small");
|
const arrow = document.createElement("span");
|
||||||
arrow.className = "nav-arrow";
|
arrow.className = `nav-arrow nav-arrow-${direction}`;
|
||||||
arrow.textContent = direction;
|
arrow.setAttribute("aria-hidden", "true");
|
||||||
const title = document.createElement("span");
|
const title = document.createElement("span");
|
||||||
title.textContent = page.title;
|
title.textContent = page.title;
|
||||||
if (direction === "←") button.append(arrow, title);
|
if (direction === "previous") button.append(arrow, title);
|
||||||
else button.append(title, arrow);
|
else button.append(title, arrow);
|
||||||
button.onclick = () => navigate(page.number);
|
button.onclick = () => navigate(page.number);
|
||||||
}
|
}
|
||||||
|
|
@ -260,8 +260,8 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
updateActiveNavigation(page.number);
|
updateActiveNavigation(page.number);
|
||||||
setupNavButton(elements.previous, manifest.pages[index - 1], "←");
|
setupNavButton(elements.previous, manifest.pages[index - 1], "previous");
|
||||||
setupNavButton(elements.next, manifest.pages[index + 1], "→");
|
setupNavButton(elements.next, manifest.pages[index + 1], "next");
|
||||||
elements.pageSurface.scrollTo({ top: 0, behavior: "instant" });
|
elements.pageSurface.scrollTo({ top: 0, behavior: "instant" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "shared-docs-lib"
|
name = "shared-docs-lib"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
description = "Build self-contained, Obsidian-like documentation sites from Python functions."
|
description = "Build self-contained, Obsidian-like documentation sites from Python functions."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,10 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
||||||
assert "elements.pageSurface.scrollTo" in html
|
assert "elements.pageSurface.scrollTo" in html
|
||||||
assert "font-family: system-ui; font-size: 16px" in html
|
assert "font-family: system-ui; font-size: 16px" in html
|
||||||
assert ".glyph-button, .refresh-glyph { font-family: Arial" in html
|
assert ".glyph-button, .refresh-glyph { font-family: Arial" in html
|
||||||
assert ".nav-arrow { font-family: system-ui; }" in html
|
assert ".nav-arrow { display: block; width: 10px; height: 10px; flex: 0 0 10px; border: 0 solid currentColor; transform: rotate(45deg); }" in html
|
||||||
|
assert ".nav-arrow-previous { border-bottom-width: 2px; border-left-width: 2px; }" in html
|
||||||
|
assert ".nav-arrow-next { border-top-width: 2px; border-right-width: 2px; }" in html
|
||||||
|
assert 'arrow.textContent = direction' not in html
|
||||||
assert "--shell: #000000" in html
|
assert "--shell: #000000" in html
|
||||||
assert 'id="desktop-search-input"' in html
|
assert 'id="desktop-search-input"' in html
|
||||||
assert '<header class="desktop-header">' in html
|
assert '<header class="desktop-header">' in html
|
||||||
|
|
@ -165,7 +168,7 @@ def test_all_endpoints_and_self_contained_build(tmp_path):
|
||||||
|
|
||||||
|
|
||||||
def test_build_writes_static_bundle(tmp_path):
|
def test_build_writes_static_bundle(tmp_path):
|
||||||
assert __version__ == "0.3.3"
|
assert __version__ == "0.3.4"
|
||||||
|
|
||||||
@Page("1", "Static page")
|
@Page("1", "Static page")
|
||||||
def static_page():
|
def static_page():
|
||||||
|
|
|
||||||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -452,7 +452,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shared-docs-lib"
|
name = "shared-docs-lib"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "fastapi" },
|
{ name = "fastapi" },
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue