ikurotime / gitgud

public
Refactor styles in templates for improved UI consistency and readability
DDavid committed on 2026-08-09 15:22 commit 679bcff
internal/interface/web/templates/browse_blob.templ +1 −1
package templates
import "gitgud/internal/domain"
templ BrowseBlob(user *domain.User, repo *domain.Repository, ref string, blob *domain.FileBlob, highlighted string) {
@Layout(blob.Path+" · gitgud", user) {
@repoHeader(repo, "code")
<div class="mb-3 flex items-center gap-2 font-mono text-sm">
<span class="inline-flex items-center gap-2 rounded-md border border-line2 bg-panel2 px-2.5 py-1 text-xs text-ink">
<span class="inline-block size-2 rounded-full border-[1.5px] border-accent"></span>{ ref }
</span>
<span class="text-faint">/</span>
<span class="text-accent">{ blob.Path }</span>
</div>
<div class="card overflow-hidden">
<div class="flex items-center justify-between border-b border-line bg-[#0e1410] px-4 py-2.5 font-mono text-xs text-muted">
<span>{ humanSize(blob.Size) } · <span class="text-accent">{ langLabel(blob.Path) }</span></span>
<a class="rounded border border-line2 px-2.5 py-1 text-ink transition hover:border-faint hover:bg-panel2" href={ templ.SafeURL(repoPath(repo, "/raw/"+ref+"/"+blob.Path)) }>Raw</a>
</div>
if blob.IsBinary {
<div class="px-4 py-10 text-center text-sm text-faint">Binary file not shown.</div>
} else {
- <div class="overflow-x-auto bg-[#0a0e0b] text-xs leading-relaxed [&_pre]:!bg-transparent">
+ <div class="overflow-x-auto bg-[#0c0c0c] text-xs leading-relaxed [&_pre]:!bg-transparent">
@templ.Raw(highlighted)
</div>
}
</div>
}
}
internal/interface/web/templates/browse_blob_templ.go +1 −1
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func BrowseBlob(user *domain.User, repo *domain.Repository, ref string, blob *domain.FileBlob, highlighted string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = repoHeader(repo, "code").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <div class=\"mb-3 flex items-center gap-2 font-mono text-sm\"><span class=\"inline-flex items-center gap-2 rounded-md border border-line2 bg-panel2 px-2.5 py-1 text-xs text-ink\"><span class=\"inline-block size-2 rounded-full border-[1.5px] border-accent\"></span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(ref)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 10, Col: 92}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-faint\">/</span> <span class=\"text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(blob.Path)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 13, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"card overflow-hidden\"><div class=\"flex items-center justify-between border-b border-line bg-[#0e1410] px-4 py-2.5 font-mono text-xs text-muted\"><span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(humanSize(blob.Size))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 17, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " · <span class=\"text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(langLabel(blob.Path))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/browse_blob.templ`, Line: 17, Col: 86}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</span></span> <a class=\"rounded border border-line2 px-2.5 py-1 text-ink transition hover:border-faint hover:bg-panel2\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 templ.SafeURL = templ.SafeURL(repoPath(repo, "/raw/"+ref+"/"+blob.Path))
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var7)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">Raw</a></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if blob.IsBinary {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"px-4 py-10 text-center text-sm text-faint\">Binary file not shown.</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"overflow-x-auto bg-[#0a0e0b] text-xs leading-relaxed [&amp;_pre]:!bg-transparent\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"overflow-x-auto bg-[#0c0c0c] text-xs leading-relaxed [&amp;_pre]:!bg-transparent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.Raw(highlighted).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(blob.Path+" · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/layout.templ +29 −28
package templates
import "gitgud/internal/domain"
templ Layout(title string, user *domain.User) {
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{ title }</title>
<link rel="preconnect" href="https://fonts.googleapis.com"/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme {
- --color-canvas: #080b09;
- --color-panel: #0b100d;
- --color-panel2: #141b16;
- --color-line: #1e2820;
- --color-line2: #25342a;
- --color-ink: #eef4ef;
- --color-muted: #8a978c;
- --color-faint: #54605c;
- --color-accent: #3fcf7f;
- --color-accenthi: #6fe0a0;
- --color-grass: #2ea04a;
- --color-grasshi: #34b554;
- --color-grassink: #06120a;
- --color-open: #3fcf7f;
- --color-closed: #ff7066;
+ --color-canvas: #0a0a0a;
+ --color-panel: #0e0e0e;
+ --color-panel2: #161616;
+ --color-line: #1f1f1f;
+ --color-line2: #2a2a2a;
+ --color-ink: #ededed;
+ --color-muted: #a1a1a1;
+ --color-faint: #6e6e6e;
+ --color-accent: #ededed;
+ --color-accenthi: #ffffff;
+ --color-grass: #ededed;
+ --color-grasshi: #ffffff;
+ --color-grassink: #0a0a0a;
+ --color-open: #3fb950;
+ --color-closed: #f85149;
--color-merged: #a371f7;
- --color-warn: #e0c060;
+ --color-warn: #d29922;
--font-sans: "Geist", ui-sans-serif, system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
}
@layer base {
html { color-scheme: dark; }
body { @apply bg-canvas text-ink font-sans antialiased; }
body::before {
content: "";
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
- background: radial-gradient(680px 320px at 50% -120px, rgba(63,207,127,.12), transparent 70%);
+ background: radial-gradient(680px 320px at 50% -120px, rgba(255,255,255,.05), transparent 70%);
}
a { @apply transition-colors; }
code, pre, .mono { @apply font-mono; }
- ::selection { background: rgba(63,207,127,.30); }
+ ::selection { background: rgba(255,255,255,.18); }
::-webkit-scrollbar { width: 10px; height: 10px; }
- ::-webkit-scrollbar-thumb { background: #25342a; border-radius: 9999px; border: 2px solid #080b09; }
- :focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(63,207,127,.55); border-radius: 6px; }
- main { animation: rise .42s cubic-bezier(.22,1,.36,1) both; }
- @keyframes rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
+ ::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 9999px; border: 2px solid #0a0a0a; }
+ :focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(255,255,255,.45); border-radius: 6px; }
+ main { animation: fade .15s ease-out both; }
+ @keyframes fade { from { opacity: 0; } to { opacity: 1; } }
+ @media (prefers-reduced-motion: reduce) { main { animation: none; } }
}
@layer components {
.btn { @apply inline-flex items-center gap-1.5 rounded-md border border-line2 bg-panel2 px-3 py-1.5 text-sm font-medium text-ink transition hover:border-faint hover:bg-line; }
- .btn-primary { @apply border-transparent bg-grass font-semibold text-grassink shadow-[0_0_0_1px_rgba(46,160,74,.5),0_6px_20px_-10px_rgba(63,207,127,.8)] hover:bg-grasshi hover:border-transparent; }
+ .btn-primary { @apply border-transparent bg-grass font-semibold text-grassink hover:bg-grasshi hover:border-transparent; }
.btn-danger { @apply text-closed hover:border-closed hover:bg-closed/10; }
- .input, .textarea, .select { @apply w-full rounded-md border border-line2 bg-[#0e1410] px-3 py-2 text-sm text-ink placeholder:text-faint transition focus:border-accent; }
+ .input, .textarea, .select { @apply w-full rounded-md border border-line2 bg-[#111111] px-3 py-2 text-sm text-ink placeholder:text-faint transition focus:border-faint; }
.card { @apply rounded-md border border-line bg-panel; }
.link { @apply text-ink hover:text-accent; }
.muted { @apply text-muted; }
.meta { @apply font-mono text-xs text-faint; }
.tab { @apply inline-flex items-center gap-2 border-b-2 border-transparent pb-2.5 text-sm text-muted transition hover:text-ink; }
.tab-active { @apply border-accent font-semibold text-ink; }
.badge { @apply inline-flex items-center gap-1 rounded border border-line2 px-2 py-0.5 text-xs font-medium text-muted; }
- .badge-open { @apply gap-1.5 rounded-full border-transparent bg-grass px-3 py-1 font-semibold text-grassink; }
+ .badge-open { @apply gap-1.5 rounded-full border-transparent bg-open/16 px-3 py-1 font-medium text-open; }
.badge-closed { @apply gap-1.5 rounded-full border-transparent bg-closed/16 px-3 py-1 font-medium text-[#ff8f86]; }
.badge-merged { @apply gap-1.5 rounded-full border-transparent bg-merged/16 px-3 py-1 font-medium text-[#c8a6f7]; }
.label-bug { @apply inline-flex items-center rounded-full bg-closed/16 px-2.5 py-0.5 text-[10px] font-medium text-[#ff8f86]; }
.label-enh { @apply inline-flex items-center rounded-full bg-accent/16 px-2.5 py-0.5 text-[10px] font-medium text-accenthi; }
.label-good { @apply inline-flex items-center rounded-full bg-warn/16 px-2.5 py-0.5 text-[10px] font-medium text-warn; }
.row { @apply transition hover:bg-panel2; }
- .diff-add { @apply bg-accent/12 text-[#aee6c4]; }
+ .diff-add { @apply bg-open/12 text-[#7ee2a0]; }
.diff-del { @apply bg-closed/12 text-[#f2b8b3]; }
- .diff-hunk { @apply bg-[#10171b] text-[#5aa0c8]; }
+ .diff-hunk { @apply bg-panel2 text-faint; }
.prose-dark { @apply text-sm leading-relaxed text-muted; }
.prose-dark h1 { @apply mt-5 mb-3 text-xl font-semibold text-ink first:mt-0; }
.prose-dark h2 { @apply mt-5 mb-2 text-lg font-semibold text-ink first:mt-0; }
.prose-dark h3 { @apply mt-4 mb-2 font-semibold text-ink; }
.prose-dark p { @apply my-3; }
.prose-dark a { @apply text-accent hover:underline; }
.prose-dark strong { @apply font-semibold text-ink; }
.prose-dark ul { @apply my-3 list-disc pl-5; }
.prose-dark ol { @apply my-3 list-decimal pl-5; }
.prose-dark li { @apply my-1; }
.prose-dark code { @apply rounded border border-line2 bg-panel2 px-1.5 py-0.5 text-[.85em] text-accent; }
.prose-dark pre { @apply my-3 overflow-x-auto rounded-lg border border-line bg-panel2 p-4 text-xs; }
.prose-dark pre code { @apply bg-transparent p-0; }
.prose-dark blockquote { @apply my-3 border-l-2 border-line2 pl-4 text-faint; }
.prose-dark hr { @apply my-5 border-line; }
}
</style>
</head>
<body>
<header class="sticky top-0 z-20 border-b border-line bg-canvas/80 backdrop-blur-xl">
<nav class="mx-auto flex h-14 max-w-5xl items-center justify-between px-6">
<a href="/" class="flex items-center gap-2.5">
<span class="text-accent">@gitLogo("size-5")</span>
<span class="font-mono font-semibold tracking-tight text-ink">gitgud</span>
</a>
<div class="flex items-center gap-4 text-sm">
if user != nil {
<a class="btn" href="/new">+ New</a>
<div class="flex items-center gap-2">
@avatar(user.Username, "size-6")
<a class="link mono text-muted" href={ templ.SafeURL("/" + user.Username) }>{ user.Username }</a>
</div>
<form method="post" action="/logout">
@csrfField()
<button class="text-muted transition hover:text-ink" type="submit">Sign out</button>
</form>
} else {
<a class="text-muted transition hover:text-ink" href="/login">Sign in</a>
<a class="btn btn-primary" href="/register">Register</a>
}
</div>
</nav>
</header>
if flashOf(ctx) != "" {
<div class="mx-auto max-w-5xl px-6 pt-4">
<div class="card flex items-center gap-2 border-accent/30 bg-accent/10 px-4 py-2.5 text-sm text-ink">
<span class="size-1.5 rounded-full bg-accent"></span>
{ flashOf(ctx) }
</div>
</div>
}
<main class="relative z-10 mx-auto max-w-5xl px-6 py-8">
{ children... }
</main>
</body>
</html>
}
templ csrfField() {
<input type="hidden" name="csrf_token" value={ csrfToken(ctx) }/>
}
// gitLogo renders the gitgud branch-network mark. Color is inherited via currentColor.
templ gitLogo(class string) {
<svg class={ class } viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="6" cy="5.5" r="2.5"></circle>
<circle cx="6" cy="18.5" r="2.5"></circle>
<circle cx="18" cy="12" r="2.5"></circle>
<path d="M6 8v8"></path>
<path d="M6 12h6.5a3 3 0 0 0 3-3V9.5"></path>
</svg>
}
// avatar renders a deterministic gradient avatar with the user's initial.
templ avatar(name, class string) {
<span
- class={ "inline-flex shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#1f7a48] font-semibold text-grassink", class }
+ class={ "inline-flex shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-[#2a2a2a] to-[#0e0e0e] font-semibold text-ink ring-1 ring-line2", class }
style="font-size:.62em"
>{ initial(name) }</span>
}
internal/interface/web/templates/layout_templ.go +6 −6
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Layout(title string, user *domain.User) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\" class=\"dark\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 11, Col: 17}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"preconnect\" href=\"https://fonts.googleapis.com\"><link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin><link href=\"https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&amp;family=JetBrains+Mono:wght@400;500;600;700&amp;display=swap\" rel=\"stylesheet\"><script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\"></script><style type=\"text/tailwindcss\">\n\t\t\t\t@theme {\n\t\t\t\t\t--color-canvas: #080b09;\n\t\t\t\t\t--color-panel: #0b100d;\n\t\t\t\t\t--color-panel2: #141b16;\n\t\t\t\t\t--color-line: #1e2820;\n\t\t\t\t\t--color-line2: #25342a;\n\t\t\t\t\t--color-ink: #eef4ef;\n\t\t\t\t\t--color-muted: #8a978c;\n\t\t\t\t\t--color-faint: #54605c;\n\t\t\t\t\t--color-accent: #3fcf7f;\n\t\t\t\t\t--color-accenthi: #6fe0a0;\n\t\t\t\t\t--color-grass: #2ea04a;\n\t\t\t\t\t--color-grasshi: #34b554;\n\t\t\t\t\t--color-grassink: #06120a;\n\t\t\t\t\t--color-open: #3fcf7f;\n\t\t\t\t\t--color-closed: #ff7066;\n\t\t\t\t\t--color-merged: #a371f7;\n\t\t\t\t\t--color-warn: #e0c060;\n\t\t\t\t\t--font-sans: \"Geist\", ui-sans-serif, system-ui, sans-serif;\n\t\t\t\t\t--font-mono: \"JetBrains Mono\", ui-monospace, monospace;\n\t\t\t\t}\n\t\t\t\t@layer base {\n\t\t\t\t\thtml { color-scheme: dark; }\n\t\t\t\t\tbody { @apply bg-canvas text-ink font-sans antialiased; }\n\t\t\t\t\tbody::before {\n\t\t\t\t\t\tcontent: \"\";\n\t\t\t\t\t\tposition: fixed;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\tz-index: 0;\n\t\t\t\t\t\tbackground: radial-gradient(680px 320px at 50% -120px, rgba(63,207,127,.12), transparent 70%);\n\t\t\t\t\t}\n\t\t\t\t\ta { @apply transition-colors; }\n\t\t\t\t\tcode, pre, .mono { @apply font-mono; }\n\t\t\t\t\t::selection { background: rgba(63,207,127,.30); }\n\t\t\t\t\t::-webkit-scrollbar { width: 10px; height: 10px; }\n\t\t\t\t\t::-webkit-scrollbar-thumb { background: #25342a; border-radius: 9999px; border: 2px solid #080b09; }\n\t\t\t\t\t:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(63,207,127,.55); border-radius: 6px; }\n\t\t\t\t\tmain { animation: rise .42s cubic-bezier(.22,1,.36,1) both; }\n\t\t\t\t\t@keyframes rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }\n\t\t\t\t}\n\t\t\t\t@layer components {\n\t\t\t\t\t.btn { @apply inline-flex items-center gap-1.5 rounded-md border border-line2 bg-panel2 px-3 py-1.5 text-sm font-medium text-ink transition hover:border-faint hover:bg-line; }\n\t\t\t\t\t.btn-primary { @apply border-transparent bg-grass font-semibold text-grassink shadow-[0_0_0_1px_rgba(46,160,74,.5),0_6px_20px_-10px_rgba(63,207,127,.8)] hover:bg-grasshi hover:border-transparent; }\n\t\t\t\t\t.btn-danger { @apply text-closed hover:border-closed hover:bg-closed/10; }\n\t\t\t\t\t.input, .textarea, .select { @apply w-full rounded-md border border-line2 bg-[#0e1410] px-3 py-2 text-sm text-ink placeholder:text-faint transition focus:border-accent; }\n\t\t\t\t\t.card { @apply rounded-md border border-line bg-panel; }\n\t\t\t\t\t.link { @apply text-ink hover:text-accent; }\n\t\t\t\t\t.muted { @apply text-muted; }\n\t\t\t\t\t.meta { @apply font-mono text-xs text-faint; }\n\t\t\t\t\t.tab { @apply inline-flex items-center gap-2 border-b-2 border-transparent pb-2.5 text-sm text-muted transition hover:text-ink; }\n\t\t\t\t\t.tab-active { @apply border-accent font-semibold text-ink; }\n\t\t\t\t\t.badge { @apply inline-flex items-center gap-1 rounded border border-line2 px-2 py-0.5 text-xs font-medium text-muted; }\n\t\t\t\t\t.badge-open { @apply gap-1.5 rounded-full border-transparent bg-grass px-3 py-1 font-semibold text-grassink; }\n\t\t\t\t\t.badge-closed { @apply gap-1.5 rounded-full border-transparent bg-closed/16 px-3 py-1 font-medium text-[#ff8f86]; }\n\t\t\t\t\t.badge-merged { @apply gap-1.5 rounded-full border-transparent bg-merged/16 px-3 py-1 font-medium text-[#c8a6f7]; }\n\t\t\t\t\t.label-bug { @apply inline-flex items-center rounded-full bg-closed/16 px-2.5 py-0.5 text-[10px] font-medium text-[#ff8f86]; }\n\t\t\t\t\t.label-enh { @apply inline-flex items-center rounded-full bg-accent/16 px-2.5 py-0.5 text-[10px] font-medium text-accenthi; }\n\t\t\t\t\t.label-good { @apply inline-flex items-center rounded-full bg-warn/16 px-2.5 py-0.5 text-[10px] font-medium text-warn; }\n\t\t\t\t\t.row { @apply transition hover:bg-panel2; }\n\t\t\t\t\t.diff-add { @apply bg-accent/12 text-[#aee6c4]; }\n\t\t\t\t\t.diff-del { @apply bg-closed/12 text-[#f2b8b3]; }\n\t\t\t\t\t.diff-hunk { @apply bg-[#10171b] text-[#5aa0c8]; }\n\t\t\t\t\t.prose-dark { @apply text-sm leading-relaxed text-muted; }\n\t\t\t\t\t.prose-dark h1 { @apply mt-5 mb-3 text-xl font-semibold text-ink first:mt-0; }\n\t\t\t\t\t.prose-dark h2 { @apply mt-5 mb-2 text-lg font-semibold text-ink first:mt-0; }\n\t\t\t\t\t.prose-dark h3 { @apply mt-4 mb-2 font-semibold text-ink; }\n\t\t\t\t\t.prose-dark p { @apply my-3; }\n\t\t\t\t\t.prose-dark a { @apply text-accent hover:underline; }\n\t\t\t\t\t.prose-dark strong { @apply font-semibold text-ink; }\n\t\t\t\t\t.prose-dark ul { @apply my-3 list-disc pl-5; }\n\t\t\t\t\t.prose-dark ol { @apply my-3 list-decimal pl-5; }\n\t\t\t\t\t.prose-dark li { @apply my-1; }\n\t\t\t\t\t.prose-dark code { @apply rounded border border-line2 bg-panel2 px-1.5 py-0.5 text-[.85em] text-accent; }\n\t\t\t\t\t.prose-dark pre { @apply my-3 overflow-x-auto rounded-lg border border-line bg-panel2 p-4 text-xs; }\n\t\t\t\t\t.prose-dark pre code { @apply bg-transparent p-0; }\n\t\t\t\t\t.prose-dark blockquote { @apply my-3 border-l-2 border-line2 pl-4 text-faint; }\n\t\t\t\t\t.prose-dark hr { @apply my-5 border-line; }\n\t\t\t\t}\n\t\t\t</style></head><body><header class=\"sticky top-0 z-20 border-b border-line bg-canvas/80 backdrop-blur-xl\"><nav class=\"mx-auto flex h-14 max-w-5xl items-center justify-between px-6\"><a href=\"/\" class=\"flex items-center gap-2.5\"><span class=\"text-accent\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"preconnect\" href=\"https://fonts.googleapis.com\"><link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin><link href=\"https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&amp;family=JetBrains+Mono:wght@400;500;600;700&amp;display=swap\" rel=\"stylesheet\"><script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\"></script><style type=\"text/tailwindcss\">\n\t\t\t\t@theme {\n\t\t\t\t\t--color-canvas: #0a0a0a;\n\t\t\t\t\t--color-panel: #0e0e0e;\n\t\t\t\t\t--color-panel2: #161616;\n\t\t\t\t\t--color-line: #1f1f1f;\n\t\t\t\t\t--color-line2: #2a2a2a;\n\t\t\t\t\t--color-ink: #ededed;\n\t\t\t\t\t--color-muted: #a1a1a1;\n\t\t\t\t\t--color-faint: #6e6e6e;\n\t\t\t\t\t--color-accent: #ededed;\n\t\t\t\t\t--color-accenthi: #ffffff;\n\t\t\t\t\t--color-grass: #ededed;\n\t\t\t\t\t--color-grasshi: #ffffff;\n\t\t\t\t\t--color-grassink: #0a0a0a;\n\t\t\t\t\t--color-open: #3fb950;\n\t\t\t\t\t--color-closed: #f85149;\n\t\t\t\t\t--color-merged: #a371f7;\n\t\t\t\t\t--color-warn: #d29922;\n\t\t\t\t\t--font-sans: \"Geist\", ui-sans-serif, system-ui, sans-serif;\n\t\t\t\t\t--font-mono: \"JetBrains Mono\", ui-monospace, monospace;\n\t\t\t\t}\n\t\t\t\t@layer base {\n\t\t\t\t\thtml { color-scheme: dark; }\n\t\t\t\t\tbody { @apply bg-canvas text-ink font-sans antialiased; }\n\t\t\t\t\tbody::before {\n\t\t\t\t\t\tcontent: \"\";\n\t\t\t\t\t\tposition: fixed;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\tz-index: 0;\n\t\t\t\t\t\tbackground: radial-gradient(680px 320px at 50% -120px, rgba(255,255,255,.05), transparent 70%);\n\t\t\t\t\t}\n\t\t\t\t\ta { @apply transition-colors; }\n\t\t\t\t\tcode, pre, .mono { @apply font-mono; }\n\t\t\t\t\t::selection { background: rgba(255,255,255,.18); }\n\t\t\t\t\t::-webkit-scrollbar { width: 10px; height: 10px; }\n\t\t\t\t\t::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 9999px; border: 2px solid #0a0a0a; }\n\t\t\t\t\t:focus-visible { outline: none; box-shadow: 0 0 0 2px rgba(255,255,255,.45); border-radius: 6px; }\n\t\t\t\t\tmain { animation: fade .15s ease-out both; }\n\t\t\t\t\t@keyframes fade { from { opacity: 0; } to { opacity: 1; } }\n\t\t\t\t\t@media (prefers-reduced-motion: reduce) { main { animation: none; } }\n\t\t\t\t}\n\t\t\t\t@layer components {\n\t\t\t\t\t.btn { @apply inline-flex items-center gap-1.5 rounded-md border border-line2 bg-panel2 px-3 py-1.5 text-sm font-medium text-ink transition hover:border-faint hover:bg-line; }\n\t\t\t\t\t.btn-primary { @apply border-transparent bg-grass font-semibold text-grassink hover:bg-grasshi hover:border-transparent; }\n\t\t\t\t\t.btn-danger { @apply text-closed hover:border-closed hover:bg-closed/10; }\n\t\t\t\t\t.input, .textarea, .select { @apply w-full rounded-md border border-line2 bg-[#111111] px-3 py-2 text-sm text-ink placeholder:text-faint transition focus:border-faint; }\n\t\t\t\t\t.card { @apply rounded-md border border-line bg-panel; }\n\t\t\t\t\t.link { @apply text-ink hover:text-accent; }\n\t\t\t\t\t.muted { @apply text-muted; }\n\t\t\t\t\t.meta { @apply font-mono text-xs text-faint; }\n\t\t\t\t\t.tab { @apply inline-flex items-center gap-2 border-b-2 border-transparent pb-2.5 text-sm text-muted transition hover:text-ink; }\n\t\t\t\t\t.tab-active { @apply border-accent font-semibold text-ink; }\n\t\t\t\t\t.badge { @apply inline-flex items-center gap-1 rounded border border-line2 px-2 py-0.5 text-xs font-medium text-muted; }\n\t\t\t\t\t.badge-open { @apply gap-1.5 rounded-full border-transparent bg-open/16 px-3 py-1 font-medium text-open; }\n\t\t\t\t\t.badge-closed { @apply gap-1.5 rounded-full border-transparent bg-closed/16 px-3 py-1 font-medium text-[#ff8f86]; }\n\t\t\t\t\t.badge-merged { @apply gap-1.5 rounded-full border-transparent bg-merged/16 px-3 py-1 font-medium text-[#c8a6f7]; }\n\t\t\t\t\t.label-bug { @apply inline-flex items-center rounded-full bg-closed/16 px-2.5 py-0.5 text-[10px] font-medium text-[#ff8f86]; }\n\t\t\t\t\t.label-enh { @apply inline-flex items-center rounded-full bg-accent/16 px-2.5 py-0.5 text-[10px] font-medium text-accenthi; }\n\t\t\t\t\t.label-good { @apply inline-flex items-center rounded-full bg-warn/16 px-2.5 py-0.5 text-[10px] font-medium text-warn; }\n\t\t\t\t\t.row { @apply transition hover:bg-panel2; }\n\t\t\t\t\t.diff-add { @apply bg-open/12 text-[#7ee2a0]; }\n\t\t\t\t\t.diff-del { @apply bg-closed/12 text-[#f2b8b3]; }\n\t\t\t\t\t.diff-hunk { @apply bg-panel2 text-faint; }\n\t\t\t\t\t.prose-dark { @apply text-sm leading-relaxed text-muted; }\n\t\t\t\t\t.prose-dark h1 { @apply mt-5 mb-3 text-xl font-semibold text-ink first:mt-0; }\n\t\t\t\t\t.prose-dark h2 { @apply mt-5 mb-2 text-lg font-semibold text-ink first:mt-0; }\n\t\t\t\t\t.prose-dark h3 { @apply mt-4 mb-2 font-semibold text-ink; }\n\t\t\t\t\t.prose-dark p { @apply my-3; }\n\t\t\t\t\t.prose-dark a { @apply text-accent hover:underline; }\n\t\t\t\t\t.prose-dark strong { @apply font-semibold text-ink; }\n\t\t\t\t\t.prose-dark ul { @apply my-3 list-disc pl-5; }\n\t\t\t\t\t.prose-dark ol { @apply my-3 list-decimal pl-5; }\n\t\t\t\t\t.prose-dark li { @apply my-1; }\n\t\t\t\t\t.prose-dark code { @apply rounded border border-line2 bg-panel2 px-1.5 py-0.5 text-[.85em] text-accent; }\n\t\t\t\t\t.prose-dark pre { @apply my-3 overflow-x-auto rounded-lg border border-line bg-panel2 p-4 text-xs; }\n\t\t\t\t\t.prose-dark pre code { @apply bg-transparent p-0; }\n\t\t\t\t\t.prose-dark blockquote { @apply my-3 border-l-2 border-line2 pl-4 text-faint; }\n\t\t\t\t\t.prose-dark hr { @apply my-5 border-line; }\n\t\t\t\t}\n\t\t\t</style></head><body><header class=\"sticky top-0 z-20 border-b border-line bg-canvas/80 backdrop-blur-xl\"><nav class=\"mx-auto flex h-14 max-w-5xl items-center justify-between px-6\"><a href=\"/\" class=\"flex items-center gap-2.5\"><span class=\"text-accent\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = gitLogo("size-5").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span> <span class=\"font-mono font-semibold tracking-tight text-ink\">gitgud</span></a><div class=\"flex items-center gap-4 text-sm\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if user != nil {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<a class=\"btn\" href=\"/new\">+ New</a><div class=\"flex items-center gap-2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = avatar(user.Username, "size-6").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<a class=\"link mono text-muted\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 templ.SafeURL = templ.SafeURL("/" + user.Username)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(user.Username)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 110, Col: 99}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 111, Col: 99}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</a></div><form method=\"post\" action=\"/logout\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = csrfField().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<button class=\"text-muted transition hover:text-ink\" type=\"submit\">Sign out</button></form>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a class=\"text-muted transition hover:text-ink\" href=\"/login\">Sign in</a> <a class=\"btn btn-primary\" href=\"/register\">Register</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div></nav></header>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if flashOf(ctx) != "" {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"mx-auto max-w-5xl px-6 pt-4\"><div class=\"card flex items-center gap-2 border-accent/30 bg-accent/10 px-4 py-2.5 text-sm text-ink\"><span class=\"size-1.5 rounded-full bg-accent\"></span> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(flashOf(ctx))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 127, Col: 20}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 128, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<main class=\"relative z-10 mx-auto max-w-5xl px-6 py-8\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</main></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func csrfField() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
if templ_7745c5c3_Var6 == nil {
templ_7745c5c3_Var6 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<input type=\"hidden\" name=\"csrf_token\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(csrfToken(ctx))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 139, Col: 62}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 140, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
// gitLogo renders the gitgud branch-network mark. Color is inherited via currentColor.
func gitLogo(class string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
if templ_7745c5c3_Var8 == nil {
templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
var templ_7745c5c3_Var9 = []any{class}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "<svg class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var9).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"6\" cy=\"5.5\" r=\"2.5\"></circle> <circle cx=\"6\" cy=\"18.5\" r=\"2.5\"></circle> <circle cx=\"18\" cy=\"12\" r=\"2.5\"></circle> <path d=\"M6 8v8\"></path> <path d=\"M6 12h6.5a3 3 0 0 0 3-3V9.5\"></path></svg>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
// avatar renders a deterministic gradient avatar with the user's initial.
func avatar(name, class string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
if templ_7745c5c3_Var11 == nil {
templ_7745c5c3_Var11 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
- var templ_7745c5c3_Var12 = []any{"inline-flex shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#1f7a48] font-semibold text-grassink", class}
+ var templ_7745c5c3_Var12 = []any{"inline-flex shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-[#2a2a2a] to-[#0e0e0e] font-semibold text-ink ring-1 ring-line2", class}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "<span class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" style=\"font-size:.62em\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(initial(name))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 158, Col: 17}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/layout.templ`, Line: 159, Col: 17}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate
internal/interface/web/templates/profile.templ +1 −1
package templates
import "gitgud/internal/domain"
templ Profile(user *domain.User, owner string, repos []*domain.Repository) {
@Layout(owner+" · gitgud", user) {
<div class="mb-6 flex items-center gap-4">
- <div class="flex size-14 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#a78bfa] font-mono text-xl font-bold text-white shadow-[0_0_24px_-6px_rgba(110,107,240,.6)]">
+ <div class="flex size-14 items-center justify-center rounded-full bg-gradient-to-br from-[#2a2a2a] to-[#0e0e0e] font-mono text-xl font-bold text-ink ring-1 ring-line2">
{ initial(owner) }
</div>
<div>
<h1 class="text-xl font-semibold tracking-tight">{ owner }</h1>
<p class="meta mt-0.5">{ itoa(len(repos)) } repositories</p>
</div>
</div>
if len(repos) == 0 {
@emptyState("Nothing here yet", "This user has no repositories to show.", "", "")
} else {
@repoList(repos)
}
}
}
internal/interface/web/templates/profile_templ.go +1 −1
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.865
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "gitgud/internal/domain"
func Profile(user *domain.User, owner string, repos []*domain.Repository) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-6 flex items-center gap-4\"><div class=\"flex size-14 items-center justify-center rounded-full bg-gradient-to-br from-accent to-[#a78bfa] font-mono text-xl font-bold text-white shadow-[0_0_24px_-6px_rgba(110,107,240,.6)]\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"mb-6 flex items-center gap-4\"><div class=\"flex size-14 items-center justify-center rounded-full bg-gradient-to-br from-[#2a2a2a] to-[#0e0e0e] font-mono text-xl font-bold text-ink ring-1 ring-line2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(initial(owner))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 9, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</div><div><h1 class=\"text-xl font-semibold tracking-tight\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(owner)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 12, Col: 60}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</h1><p class=\"meta mt-0.5\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(repos)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/interface/web/templates/profile.templ`, Line: 13, Col: 45}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, " repositories</p></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(repos) == 0 {
templ_7745c5c3_Err = emptyState("Nothing here yet", "This user has no repositories to show.", "", "").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = repoList(repos).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
return nil
})
templ_7745c5c3_Err = Layout(owner+" · gitgud", user).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate