Phase 2: Touch-First CSS + Touch-First JS + Graph-Modal

Touch-First Design (style.css, 17 KB):
- Mobile-First CSS mit Safe-Area-Insets für iOS Dynamic Island
- Bottom-Nav (Files / Search / Graph) auf <768px
- Hamburger-Tree slidet von links rein mit Backdrop
- Graph-Modal als Full-Screen-Overlay mit Title-Bar + Close
- Tap-Targets ≥ 44px (--tap-min)
- Tablet-Mode (768-1023px): 2-Panel + Bottom-Graph 240px
- Desktop (≥1024px): 3-Panel mit Tree 280px / Graph 320px
- Touch-Action-Manipulation verhindert 300ms-Tap-Delay
- Word-wrap + overflow-wrap für Mobile-Content
- Frontmatter-Card als Grid-Layout
- TOC + Backlinks Styling

Touch-First JS (app.js, 21 KB):
- Tree-Render mit auf-/zuklappbaren Ordnern (auto-open concepts/entities)
- Search mit Live-Dropdown, Keyboard-Navigation (↑↓ Enter Esc)
- 3D Graph in Three.js, KEIN Auto-Rotation, drag-to-rotate + wheel-zoom
- Click-zentriert: Click auf Node → navigiert zur Page
- Modal-Close via X-Button oder Escape
- Touch/Click-Handler: pointerdown/move/up + Raycaster
- Backlinks-Section aus data.backlinks
- TOC aus h2/h3-Headings der aktuellen Page
- Hash-anchor highlighting via :target CSS

Template-Patch (generator.py):
- Search-Wrap-Container für absolute Dropdown-Position
- Bottom-Nav mit inner-Flex
- Graph-Modal-Container
- Three.js-CDN-Script im HEAD

Assets werden jetzt aus dem Repo kopiert (style.css, app.js, manifest.json)
statt eingebettete Placeholder-Strings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-19 17:20:34 +00:00
co-authored by Claude
parent b5631986e6
commit d0e4e8ab9e
4 changed files with 1373 additions and 9 deletions
+33 -9
View File
@@ -242,13 +242,16 @@ PAGE_TEMPLATE = """<!DOCTYPE html>
<link rel="stylesheet" href="/__/style.css">
<link rel="manifest" href="/__/manifest.json">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📓</text></svg>">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body class="page-{kind}">
<div class="app-shell">
<header class="app-header">
<button class="icon-btn menu-toggle" aria-label="Toggle tree" data-action="toggle-tree">☰</button>
<a href="/__/index.html" class="brand">📓 Hermes Wiki</a>
<input type="search" id="search" placeholder="Suchen…" aria-label="Search notes">
<div class="search-wrap">
<input type="search" id="search" placeholder="Suchen…" aria-label="Search notes">
</div>
<button class="icon-btn graph-toggle" aria-label="Toggle graph" data-action="toggle-graph">⊕</button>
</header>
<aside class="app-tree" id="tree" aria-label="File tree"></aside>
@@ -265,10 +268,25 @@ PAGE_TEMPLATE = """<!DOCTYPE html>
</main>
<aside class="app-graph" id="graph" aria-label="3D graph"></aside>
<nav class="app-bottom-nav" aria-label="Bottom navigation">
<button data-action="toggle-tree">☰<br><small>Files</small></button>
<button data-action="focus-search">🔍<br><small>Search</small></button>
<button data-action="toggle-graph">⊕<br><small>Graph</small></button>
<div class="app-bottom-nav-inner">
<button data-action="toggle-tree"><span class="icon">☰</span><small>Files</small></button>
<button data-action="focus-search"><span class="icon">🔍</span><small>Search</small></button>
<button data-action="toggle-graph"><span class="icon">⊕</span><small>Graph</small></button>
</div>
</nav>
<div class="graph-modal" aria-label="3D graph (full screen)">
<div class="graph-modal-header">
<span class="graph-modal-title">GRAPH VIEW · Drag to rotate · Tap a node to navigate</span>
<button class="graph-modal-close" aria-label="Close">×</button>
</div>
<div class="graph-modal-canvas"><canvas></canvas></div>
<div class="graph-legend">
<div class="graph-legend-title">Legend</div>
<div class="graph-legend-row"><span class="graph-legend-dot" style="background:#FFD700"></span>Current page</div>
<div class="graph-legend-row"><span class="graph-legend-dot" style="background:#FFD700;opacity:0.8"></span>Connected</div>
<div class="graph-legend-row"><span class="graph-legend-dot" style="background:#6c7086;opacity:0.5"></span>Other notes</div>
</div>
</div>
</div>
<script src="/__/data.js"></script>
<script src="/__/app.js"></script>
@@ -489,13 +507,19 @@ PWA_MANIFEST = """{
def write_assets(site_dir: Path) -> None:
"""Write static assets (CSS, JS, manifest)."""
"""Copy static assets (CSS, JS, manifest) from repo to site dir."""
assets_dir = site_dir / "__"
assets_dir.mkdir(parents=True, exist_ok=True)
(assets_dir / "style.css").write_text(CSS_PLACEHOLDER, encoding="utf-8")
(assets_dir / "app.js").write_text(JS_PLACEHOLDER, encoding="utf-8")
(assets_dir / "manifest.json").write_text(PWA_MANIFEST, encoding="utf-8")
# Index page (redirect to first page or show all)
repo_root = Path(__file__).parent
for asset in ("style.css", "app.js", "manifest.json"):
src = repo_root / asset
if src.exists():
content = src.read_text(encoding="utf-8")
(assets_dir / asset).write_text(content, encoding="utf-8")
else:
log.warning(f"Asset not found in repo: {src}")
# index page (redirect to first page or show all)
index_html = """<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Hermes Wiki</title>
<link rel="stylesheet" href="/__/style.css">