layout.tsx
Raw
1import type { Children } from "@kitajs/html";
2import config from "../config.ts";
3import { displayName } from "../lib/users.ts";
4import type { SessionUser } from "../middleware/session.ts";
5import { Avatar } from "./Avatar.tsx";
6
7interface LayoutProps {
8 user: SessionUser | null;
9 title?: string;
10 children: Children;
11}
12
13export function Layout({ user, title, children }: LayoutProps) {
14 const pageTitle = title ? `${title} — Hearthforge` : "Hearthforge";
15 return (
16 <html lang="en">
17 <head>
18 <meta charset="UTF-8" />
19 <meta name="viewport" content="width=500" />
20 <title safe>{pageTitle}</title>
21 <script src="/assets/theme.js"></script>
22 <link
23 rel="icon"
24 type="image/svg+xml"
25 href="/assets/favicon.svg"
26 />
27 <link rel="stylesheet" href="/assets/main.css" />
28 <script src="/assets/jxl-polyfill.js" defer></script>
29 <script src="/assets/app.js" defer></script>
30 </head>
31 <body>
32 <header class="site-header">
33 <nav class="site-nav">
34 <a href="/" class="site-logo">
35 <img
36 src="/assets/favicon.svg"
37 class="logo-icon"
38 alt=""
39 aria-hidden="true"
40 />
41 <span class="logo-text">Hearthforge</span>
42 </a>
43 <div class="nav-links">
44 {user ? (
45 <>
46 <a href="/settings" class="nav-user">
47 <Avatar
48 userId={user.id}
49 version={user.avatar_version}
50 size={24}
51 />
52 <span safe>
53 {displayName(user.username)}
54 </span>
55 </a>
56 <form
57 method="POST"
58 action="/logout"
59 class="inline-form"
60 >
61 <button
62 type="submit"
63 class="btn btn-sm"
64 >
65 Sign out
66 </button>
67 </form>
68 </>
69 ) : (
70 <>
71 <a href="/login" class="btn btn-sm">
72 Sign in
73 </a>
74 <a
75 href="/register"
76 class="btn btn-sm btn-primary"
77 >
78 Register
79 </a>
80 </>
81 )}
82 </div>
83 </nav>
84 </header>
85 <main class="site-main">{children}</main>
86 <footer class="site-footer">
87 <p safe>
88 Hearthforge — hosted by {config.OWNER_DISPLAY_NAME}
89 </p>
90 </footer>
91 </body>
92 </html>
93 );
94}
95