Files
bookhoard/templates/docs.templ
T
john-okeefe a075a5061f feat(ui): refresh auth, entry, admin, and secondary pages
Apply the new design-system primitives across the remaining pages so the
whole app shares one visual language:

- Auth/entry: redesigned index, login, register (centered card layout,
  SVG icons, semantic tokens)
- Admin: sidebar nav with icons, cohesive admin dashboard/users/library/
  processing-issues/settings (tables use border-line + hover states;
  scan/websocket attributes preserved)
- Secondary: analytics (stat cards), devices, progress, conflicts, queue,
  profile + form/modal all migrated to .card/.btn/.input primitives and
  SVG action icons
- Docs + API explorer + setup wizard + collection/rules/modals +
  unlinked books + book-detail modals: consistent chrome, modal scrims
  use --surface-overlay, close buttons use icon-btn
- reader.templ and error.templ intentionally left unchanged
2026-08-05 16:01:22 -04:00

111 lines
4.2 KiB
Templ
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package templates
import "fmt"
templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{ doc.Title } - Bookhoard Documentation</title>
<link href="/static/style.css" rel="stylesheet"/>
<link rel="stylesheet" href="/static/highlight-dark.min.css"/>
</head>
<body x-data="docs" x-init="initializeSearch(); highlightCurrentPage(); initializeCodeCopyButtons()" class={ "theme-" + user.Theme + " page-docs bg-surface text-content font-sans antialiased" }>
@Header(user, currentPath)
<!-- Mobile Menu Button -->
<button
class="icon-btn lg:hidden fixed top-4 left-4 z-50"
onclick="toggleSidebar()"
aria-label="Toggle menu"
>
@Icon("menu", "h-6 w-6")
</button>
<!-- Search Results Overlay -->
<div id="search-results" class="hidden fixed inset-0 bg-black/95 z-50 overflow-y-auto p-8 transition-opacity duration-200 ease-in-out"></div>
<!-- Sidebar -->
<div class="sidebar fixed left-0 top-0 bottom-0 w-72 bg-surface-raised border-r border-line overflow-y-auto mt-16 lg:translate-x-0 transition-transform duration-300 ease-in-out">
<!-- Search -->
<div class="p-4 border-b border-line">
<input
type="text"
class="search-input input text-sm"
placeholder="Search documentation..."
id="docs-search"
/>
</div>
<!-- Navigation Sections -->
for _, section := range nav.Sections {
<div class="nav-section mb-6">
<div
class="nav-section-title font-semibold text-xs uppercase tracking-wide text-content-muted px-4 py-3 cursor-pointer select-none flex items-center justify-between"
@click="toggleSection($el)"
>
<span>{ section.Title }</span>
<svg class="w-4 h-4 transform transition-transform section-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
if section.Collapsed {
<div class="nav-items hidden" data-collapsed="true">
for _, item := range section.Items {
<a href={ item.URL } class="nav-item block py-2 px-4 pl-8 text-content-muted hover:text-brand text-sm transition-colors no-underline">
<span class="mr-2">{ item.Icon }</span>{ item.Title }
</a>
}
</div>
} else {
<div class="nav-items" data-collapsed="false">
for _, item := range section.Items {
<a href={ item.URL } class="nav-item block py-2 px-4 pl-8 text-content-muted hover:text-brand text-sm transition-colors no-underline">
<span class="mr-2">{ item.Icon }</span>{ item.Title }
</a>
}
</div>
}
</div>
}
</div>
<!-- Main Content -->
<main class="main-content lg:ml-72 p-8 max-w-4xl mx-auto">
<!-- Breadcrumb -->
if len(doc.Breadcrumb) > 0 {
<nav class="breadcrumb flex gap-2 text-sm text-content-muted mb-8" aria-label="Breadcrumb">
for i, crumb := range doc.Breadcrumb {
if i > 0 {
<span class="text-content-muted/50"></span>
}
<a href={ crumb.URL } class="text-brand hover:underline no-underline">{ crumb.Title }</a>
}
</nav>
}
<!-- Title -->
<h1 class="text-3xl font-bold tracking-tight mb-8 text-content">{ doc.Title }</h1>
<!-- Table of Contents -->
if len(doc.TOC) > 0 {
<details class="toc bg-surface-raised p-4 rounded-lg mb-8 border border-line">
<summary class="cursor-pointer hover:opacity-80 transition-opacity">
<strong class="text-content font-semibold">On this page</strong>
<span class="ml-2 text-content-muted text-xs"></span>
</summary>
for _, item := range doc.TOC {
<a
href={ "#" + item.Anchor }
class="toc-item block py-1 text-content-muted hover:text-brand text-sm no-underline"
style={ "margin-left: " + fmt.Sprintf("%drem", item.Level) }
>
{ item.Title }
</a>
}
</details>
}
<!-- Content -->
<div class="prose prose-invert max-w-none">
@UnsafeHTML(doc.Content).ToComponent()
</div>
</main>
</body>
</html>
}