xtablo-source/backend/internal/web/ui/catalog/catalog.templ

88 lines
4.8 KiB
Text

package catalog
// CatalogPage renders the single-page component catalog.
// Layout: fixed 240px sidebar + fluid main content area.
// The catalog uses Tailwind utility classes for its shell — not app.css (D-A04).
// Built with -tags catalog only; never compiled into production binaries.
templ CatalogPage() {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Component Catalog</title>
<link rel="stylesheet" href="/static/tailwind.css"/>
<style>
/* Catalog shell — minimal reset only, no app.css import (D-A04) */
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #f9fafb; color: #111827; }
.catalog-layout { display: flex; min-height: 100vh; }
.catalog-sidebar { width: 240px; flex-shrink: 0; background: #fff; border-right: 1px solid #e5e7eb; position: sticky; top: 0; height: 100vh; overflow-y: auto; padding: 1.5rem 1rem; }
.catalog-sidebar-heading { font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: #6b7280; margin: 0 0 0.75rem 0.5rem; }
.catalog-nav-link { display: block; padding: 0.4rem 0.5rem; border-radius: 0.375rem; text-decoration: none; color: #374151; font-size: 0.875rem; }
.catalog-nav-link:hover { background: #f3f4f6; }
.catalog-main { flex: 1; padding: 2rem 3rem; max-width: 960px; }
.catalog-title { font-size: 1.875rem; font-weight: 700; margin: 0 0 0.25rem 0; color: #111827; }
.catalog-subtitle { color: #6b7280; margin: 0 0 2.5rem 0; }
.catalog-section { margin-bottom: 3.5rem; }
.catalog-section-heading { font-size: 1.125rem; font-weight: 600; border-bottom: 1px solid #e5e7eb; padding-bottom: 0.5rem; margin: 0 0 1.5rem 0; color: #111827; }
.catalog-example { margin-bottom: 2rem; }
.catalog-example-title { font-size: 0.875rem; font-weight: 600; color: #374151; margin: 0 0 0.5rem 0; }
.catalog-example-preview { padding: 1.25rem; background: #fff; border: 1px solid #e5e7eb; border-radius: 0.5rem; margin-bottom: 0.5rem; }
.catalog-example-snippet { background: #f3f4f6; border: 1px solid #e5e7eb; border-radius: 0.375rem; padding: 0.75rem 1rem; font-size: 0.75rem; font-family: ui-monospace, "Cascadia Code", "Source Code Pro", monospace; overflow-x: auto; white-space: pre; margin: 0; color: #374151; }
</style>
</head>
<body>
<div class="catalog-layout">
<aside class="catalog-sidebar">
<p class="catalog-sidebar-heading">Components</p>
<nav>
<a href="#badge" class="catalog-nav-link">Badge</a>
<a href="#button" class="catalog-nav-link">Button</a>
<a href="#card" class="catalog-nav-link">Card</a>
<a href="#empty-state" class="catalog-nav-link">Empty State</a>
<a href="#form-field" class="catalog-nav-link">Form Field</a>
<a href="#icon-button" class="catalog-nav-link">Icon Button</a>
<a href="#input" class="catalog-nav-link">Input</a>
<a href="#modal" class="catalog-nav-link">Modal</a>
<a href="#select" class="catalog-nav-link">Select</a>
<a href="#table" class="catalog-nav-link">Table</a>
<a href="#textarea" class="catalog-nav-link">Textarea</a>
</nav>
</aside>
<main class="catalog-main">
<h1 class="catalog-title">Component Catalog</h1>
<p class="catalog-subtitle">All 11 component types with variants. Visual sign-off gate for Phase 14.</p>
@catalogSection("badge", "Badge — DS-05", badgeExamples())
@catalogSection("button", "Button — DS-02", buttonExamples())
@catalogSection("card", "Card — DS-04", cardExamples())
@catalogSection("empty-state", "Empty State — DS-09", emptyStateExamples())
@catalogSection("form-field", "Form Field — DS-08", formFieldExamples())
@catalogSection("icon-button", "Icon Button — DS-07", iconButtonExamples())
@catalogSection("input", "Input — DS-03", inputExamples())
@catalogSection("modal", "Modal — DS-06", modalExamples())
@catalogSection("select", "Select — DS-10", selectExamples())
@catalogSection("table", "Table — DS-11", tableExamples())
@catalogSection("textarea", "Textarea — DS-03b", textareaExamples())
</main>
</div>
</body>
</html>
}
templ catalogSection(id string, heading string, examples []Example) {
<section id={ id } class="catalog-section">
<h2 class="catalog-section-heading">{ heading }</h2>
for _, ex := range examples {
<div class="catalog-example">
<p class="catalog-example-title">{ ex.Title }</p>
<div class="catalog-example-preview">
@ex.Preview
</div>
if ex.Snippet != "" {
<pre class="catalog-example-snippet"><code>{ ex.Snippet }</code></pre>
}
</div>
}
</section>
}