feat(toolbar): theme-mode tester + sync toolbar.templ from cms

Sync the vendored templates/bn/toolbar.templ with the cms copy (entrance
animation, position picker chips, HidePreviewToggle — and the new per-tab
theme tester button). Port themeInitScript to the override-aware
window.bnApplyTheme so jutsu-rendered pages honour the admin's transient
bn-theme-override (sessionStorage) ahead of the visitor bn-theme preference.

Regenerated *_templ.go with templ v0.3.1020 (button/engagement diffs are
generator-version churn only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Alex Dunmow 2026-07-07 02:20:04 +08:00
parent 1a75edeae9
commit 1ee9c280e2
6 changed files with 482 additions and 281 deletions

View File

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT. // Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.1001 // templ: version: v0.3.1020
package shared package shared
//lint:file-ignore SA4006 This context is only used if a nested component is present. //lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -44,7 +44,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var3 templ.SafeURL var templ_7745c5c3_Var3 templ.SafeURL
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(btn.URL)) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(btn.URL))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 8, Col: 33} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 8, Col: 33}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -55,11 +55,11 @@ func RenderButton(btn ButtonConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var4 string var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var2).String())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 1, Col: 0} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 1, Col: 0}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -80,7 +80,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var5 string var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(btn.InlineStyle()) templ_7745c5c3_Var5, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(btn.InlineStyle())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 14, Col: 29} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 14, Col: 29}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -93,7 +93,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var6 string var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text) templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 16, Col: 14} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 16, Col: 14}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -116,7 +116,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var8 templ.SafeURL var templ_7745c5c3_Var8 templ.SafeURL
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(btn.URL)) templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(btn.URL))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 20, Col: 33} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 20, Col: 33}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -127,11 +127,11 @@ func RenderButton(btn ButtonConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var9 string var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var7).String()) templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var7).String())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 1, Col: 0} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 1, Col: 0}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -152,7 +152,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var10 string var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text) templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 27, Col: 14} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 27, Col: 14}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -175,11 +175,11 @@ func RenderButton(btn ButtonConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var12 string var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var11).String()) templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var11).String())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 1, Col: 0} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 1, Col: 0}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -190,7 +190,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var13 string var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(btn.InlineStyle()) templ_7745c5c3_Var13, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(btn.InlineStyle())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 32, Col: 74} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 32, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -203,7 +203,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var14 string var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text) templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 33, Col: 14} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 33, Col: 14}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -224,11 +224,11 @@ func RenderButton(btn ButtonConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var16 string var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var15).String()) templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var15).String())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 1, Col: 0} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 1, Col: 0}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -239,7 +239,7 @@ func RenderButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var17 string var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text) templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 37, Col: 14} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 37, Col: 14}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -288,11 +288,11 @@ func RenderSubmitButton(btn ButtonConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var20 string var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var19).String()) templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var19).String())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 1, Col: 0} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 1, Col: 0}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -303,7 +303,7 @@ func RenderSubmitButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var21 string var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(btn.InlineStyle()) templ_7745c5c3_Var21, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues(btn.InlineStyle())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 46, Col: 73} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 46, Col: 73}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -316,7 +316,7 @@ func RenderSubmitButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var22 string var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text) templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 47, Col: 13} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 47, Col: 13}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -337,11 +337,11 @@ func RenderSubmitButton(btn ButtonConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var24 string var templ_7745c5c3_Var24 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var23).String()) templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.ResolveAttributeValue(templ.CSSClasses(templ_7745c5c3_Var23).String())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 1, Col: 0} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 1, Col: 0}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
@ -352,7 +352,7 @@ func RenderSubmitButton(btn ButtonConfig) templ.Component {
var templ_7745c5c3_Var25 string var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text) templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(btn.Text)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `button.templ`, Line: 51, Col: 13} return templ.Error{Err: templ_7745c5c3_Err, FileName: `blocks/shared/button.templ`, Line: 51, Col: 13}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {

View File

@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT. // Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.1001 // templ: version: v0.3.1020
package bn package bn
//lint:file-ignore SA4006 This context is only used if a nested component is present. //lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -60,11 +60,11 @@ func EngagementScript(config EngagementConfig) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
var templ_7745c5c3_Var2 string var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(engagementConfigJSON(config)) templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.ResolveAttributeValue(engagementConfigJSON(config))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `engagement.templ`, Line: 30, Col: 63} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/engagement.templ`, Line: 30, Col: 63}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@ -775,15 +775,23 @@ func themeInitScript(themeMode string) templ.Component {
default: default:
themeMode = "light" themeMode = "light"
} }
// Precedence: admin toolbar override (per-tab, sessionStorage) → visitor
// preference (bn-theme cookie/localStorage) → site default → system.
// Exposed as window.bnApplyTheme so the toolbar theme tester can re-apply
// after changing the override without duplicating this resolution.
// KEEP IN SYNC with cms backend/templates/bn/head.templ.
return templ.Raw(`<script> return templ.Raw(`<script>
(function(){ window.bnApplyTheme=function(){
var c=document.cookie.match(/(?:^|; )bn-theme=([^;]*)/); var t=null;try{t=sessionStorage.getItem('bn-theme-override')}catch(e){}
var t=c?c[1]:localStorage.getItem('bn-theme'); if(!t){
var c=document.cookie.match(/(?:^|; )bn-theme=([^;]*)/);
t=c?c[1]:localStorage.getItem('bn-theme');
}
if(!t)t='` + themeMode + `'; if(!t)t='` + themeMode + `';
var h=document.documentElement;
if(t==='system')t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'; if(t==='system')t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light';
if(t==='dark')h.classList.add('dark'); document.documentElement.classList.toggle('dark',t==='dark');
else h.classList.remove('dark'); return t;
})(); };
window.bnApplyTheme();
</script>`) </script>`)
} }

View File

@ -416,7 +416,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var2 string var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.EffectiveTitle()) templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.EffectiveTitle())
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 384, Col: 32} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 384, Col: 32}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -434,7 +434,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var3 templ.SafeURL var templ_7745c5c3_Var3 templ.SafeURL
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs("/data/styles/styles.css?v=" + data.CSSHash) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs("/data/styles/styles.css?v=" + data.CSSHash)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 386, Col: 76} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 386, Col: 76}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -466,7 +466,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var4 templ.SafeURL var templ_7745c5c3_Var4 templ.SafeURL
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.FaviconICO) templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.FaviconICO)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 394, Col: 80} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 394, Col: 80}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -479,7 +479,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var5 templ.SafeURL var templ_7745c5c3_Var5 templ.SafeURL
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.Favicon16) templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.Favicon16)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 395, Col: 90} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 395, Col: 90}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -492,7 +492,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var6 templ.SafeURL var templ_7745c5c3_Var6 templ.SafeURL
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.Favicon32) templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.Favicon32)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 396, Col: 90} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 396, Col: 90}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -505,7 +505,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var7 templ.SafeURL var templ_7745c5c3_Var7 templ.SafeURL
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.AppleTouchIcon) templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.AppleTouchIcon)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 397, Col: 92} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 397, Col: 92}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -518,7 +518,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var8 templ.SafeURL var templ_7745c5c3_Var8 templ.SafeURL
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.ManifestURL) templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Branding.ManifestURL)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 398, Col: 65} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 398, Col: 65}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -536,7 +536,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var9 string var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.Branding.ThemeColor) templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.Branding.ThemeColor)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 400, Col: 72} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 400, Col: 72}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var9)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -560,7 +560,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var10 templ.SafeURL var templ_7745c5c3_Var10 templ.SafeURL
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Favicon) templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.Favicon)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 405, Col: 49} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 405, Col: 49}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -583,7 +583,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var11 templ.SafeURL var templ_7745c5c3_Var11 templ.SafeURL
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.AppleTouchIcon) templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.AppleTouchIcon)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 408, Col: 68} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 408, Col: 68}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -603,7 +603,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var12 string var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaDescription) templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 416, Col: 67} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 416, Col: 67}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var12)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -621,7 +621,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var13 string var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.MetaDescription) templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.MetaDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 418, Col: 67} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 418, Col: 67}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var13) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var13)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -640,7 +640,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var14 templ.SafeURL var templ_7745c5c3_Var14 templ.SafeURL
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinURLErrs(data.PageMeta.CanonicalURL) templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinURLErrs(data.PageMeta.CanonicalURL)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 423, Col: 58} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 423, Col: 58}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -659,7 +659,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var15 string var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.RobotsDirective) templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.RobotsDirective)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 428, Col: 62} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 428, Col: 62}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var15) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var15)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -678,7 +678,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var16 string var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.OGSiteName) templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.OGSiteName)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 434, Col: 67} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 434, Col: 67}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var16)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -697,7 +697,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var17 string var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGTitle) templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGTitle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 439, Col: 60} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 439, Col: 60}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var17)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -715,7 +715,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var18 string var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaTitle) templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaTitle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 441, Col: 62} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 441, Col: 62}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var18) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var18)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -733,7 +733,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var19 string var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Title) templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Title)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 443, Col: 49} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 443, Col: 49}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var19) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var19)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -752,7 +752,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var20 string var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGDescription) templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 448, Col: 72} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 448, Col: 72}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var20)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -770,7 +770,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var21 string var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaDescription) templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 450, Col: 74} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 450, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var21) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var21)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -788,7 +788,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var22 string var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.MetaDescription) templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.MetaDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 452, Col: 74} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 452, Col: 74}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -807,7 +807,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var23 string var templ_7745c5c3_Var23 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.PageMeta.OGImage)) templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.PageMeta.OGImage))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 457, Col: 77} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 457, Col: 77}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var23) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var23)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -825,7 +825,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var24 string var templ_7745c5c3_Var24 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.Settings.DefaultOGImage)) templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.Settings.DefaultOGImage))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 459, Col: 84} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 459, Col: 84}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var24)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -848,7 +848,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var25 string var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.TwitterHandle) templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.TwitterHandle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 467, Col: 66} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 467, Col: 66}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var25) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var25)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -871,7 +871,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var26 string var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.TwitterTitle) templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.TwitterTitle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 473, Col: 66} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 473, Col: 66}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var26) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var26)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -889,7 +889,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var27 string var templ_7745c5c3_Var27 string
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGTitle) templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGTitle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 475, Col: 61} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 475, Col: 61}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var27) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var27)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -907,7 +907,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var28 string var templ_7745c5c3_Var28 string
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaTitle) templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaTitle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 477, Col: 63} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 477, Col: 63}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var28)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -925,7 +925,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var29 string var templ_7745c5c3_Var29 string
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Title) templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Title)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 479, Col: 50} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 479, Col: 50}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var29) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var29)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -944,7 +944,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var30 string var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.TwitterDescription) templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.TwitterDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 484, Col: 78} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 484, Col: 78}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var30) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var30)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -962,7 +962,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var31 string var templ_7745c5c3_Var31 string
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGDescription) templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.OGDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 486, Col: 73} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 486, Col: 73}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var31) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var31)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -980,7 +980,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var32 string var templ_7745c5c3_Var32 string
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaDescription) templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.PageMeta.MetaDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 488, Col: 75} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 488, Col: 75}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var32) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var32)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -998,7 +998,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var33 string var templ_7745c5c3_Var33 string
templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.MetaDescription) templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.MetaDescription)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 490, Col: 75} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 490, Col: 75}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var33) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var33)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1017,7 +1017,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var34 string var templ_7745c5c3_Var34 string
templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.PageMeta.TwitterImage)) templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.PageMeta.TwitterImage))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 495, Col: 83} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 495, Col: 83}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var34) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var34)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1035,7 +1035,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var35 string var templ_7745c5c3_Var35 string
templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.PageMeta.OGImage)) templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.PageMeta.OGImage))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 497, Col: 78} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 497, Col: 78}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var35)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1053,7 +1053,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var36 string var templ_7745c5c3_Var36 string
templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.Settings.DefaultOGImage)) templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.ResolveAttributeValue(resolveMediaURL(data.Settings.DefaultOGImage))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 499, Col: 85} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 499, Col: 85}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var36) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var36)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1078,7 +1078,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var37 string var templ_7745c5c3_Var37 string
templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.RSSFeedTitle + " (RSS)") templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.RSSFeedTitle + " (RSS)")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 511, Col: 97} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 511, Col: 97}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var37) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var37)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1091,7 +1091,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var38 templ.SafeURL var templ_7745c5c3_Var38 templ.SafeURL
templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.RSSFeedURL) templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.RSSFeedURL)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 511, Col: 131} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 511, Col: 131}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1104,7 +1104,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var39 string var templ_7745c5c3_Var39 string
templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.RSSFeedTitle + " (Atom)") templ_7745c5c3_Var39, templ_7745c5c3_Err = templ.ResolveAttributeValue(data.Settings.RSSFeedTitle + " (Atom)")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 512, Col: 99} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 512, Col: 99}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var39) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var39)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1117,7 +1117,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var40 templ.SafeURL var templ_7745c5c3_Var40 templ.SafeURL
templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.RSSFeedURL + "/atom") templ_7745c5c3_Var40, templ_7745c5c3_Err = templ.JoinURLErrs(data.Settings.RSSFeedURL + "/atom")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 512, Col: 143} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 512, Col: 143}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var40))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1136,7 +1136,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var41 string var templ_7745c5c3_Var41 string
templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.ResolveAttributeValue("https://www.googletagmanager.com/gtag/js?id=" + data.Settings.GoogleAnalyticsID) templ_7745c5c3_Var41, templ_7745c5c3_Err = templ.ResolveAttributeValue("https://www.googletagmanager.com/gtag/js?id=" + data.Settings.GoogleAnalyticsID)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 516, Col: 103} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 516, Col: 103}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var41) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var41)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1167,7 +1167,7 @@ func Head(data HeadData) templ.Component {
var templ_7745c5c3_Var42 templ.SafeURL var templ_7745c5c3_Var42 templ.SafeURL
templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinURLErrs(style) templ_7745c5c3_Var42, templ_7745c5c3_Err = templ.JoinURLErrs(style)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 524, Col: 38} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 524, Col: 38}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var42))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1374,7 +1374,7 @@ func analyticsScript(nonce string) templ.Component {
var templ_7745c5c3_Var47 string var templ_7745c5c3_Var47 string
templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.ResolveAttributeValue(nonce) templ_7745c5c3_Var47, templ_7745c5c3_Err = templ.ResolveAttributeValue(nonce)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bn/head.templ`, Line: 598, Col: 27} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bn/head.templ`, Line: 598, Col: 27}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var47) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var47)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@ -1394,16 +1394,24 @@ func themeInitScript(themeMode string) templ.Component {
default: default:
themeMode = "light" themeMode = "light"
} }
// Precedence: admin toolbar override (per-tab, sessionStorage) → visitor
// preference (bn-theme cookie/localStorage) → site default → system.
// Exposed as window.bnApplyTheme so the toolbar theme tester can re-apply
// after changing the override without duplicating this resolution.
// KEEP IN SYNC with cms backend/templates/bn/head.templ.
return templ.Raw(`<script> return templ.Raw(`<script>
(function(){ window.bnApplyTheme=function(){
var c=document.cookie.match(/(?:^|; )bn-theme=([^;]*)/); var t=null;try{t=sessionStorage.getItem('bn-theme-override')}catch(e){}
var t=c?c[1]:localStorage.getItem('bn-theme'); if(!t){
var c=document.cookie.match(/(?:^|; )bn-theme=([^;]*)/);
t=c?c[1]:localStorage.getItem('bn-theme');
}
if(!t)t='` + themeMode + `'; if(!t)t='` + themeMode + `';
var h=document.documentElement;
if(t==='system')t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'; if(t==='system')t=window.matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light';
if(t==='dark')h.classList.add('dark'); document.documentElement.classList.toggle('dark',t==='dark');
else h.classList.remove('dark'); return t;
})(); };
window.bnApplyTheme();
</script>`) </script>`)
} }

View File

@ -17,6 +17,8 @@ type ToolbarData struct {
Status string // "published", "draft", "scheduled" Status string // "published", "draft", "scheduled"
HasUnpublishedChanges bool HasUnpublishedChanges bool
PreviewMode string // "published" or "draft" PreviewMode string // "published" or "draft"
HidePreviewToggle bool
Animate bool // true only on initial full-page render (entrance animation); false on HTMX re-renders
Position string // "tl", "tc", "tr", "bl", "bc", "br" (default: "tr") Position string // "tl", "tc", "tr", "bl", "bc", "br" (default: "tr")
ScheduledAt *time.Time ScheduledAt *time.Time
TemplateName string TemplateName string
@ -135,6 +137,20 @@ func (t ToolbarData) DropdownAlign() string {
return "right" return "right"
} }
// EnterAnimationClass returns the entrance-animation classes for the initial
// full-page render. It slides the pill in from the edge it rests against (up for
// bottom positions, down for top) then gives a brief pulse. Empty on HTMX
// re-renders (Animate=false) so publish/discard/reposition swaps appear instantly.
func (t ToolbarData) EnterAnimationClass() string {
if !t.Animate {
return ""
}
if t.IsBottomPosition() {
return "bn-toolbar-enter bn-toolbar-enter-up"
}
return "bn-toolbar-enter bn-toolbar-enter-down"
}
// PositionClasses returns the positioning classes for the floating pill // PositionClasses returns the positioning classes for the floating pill
func (t ToolbarData) PositionClasses() string { func (t ToolbarData) PositionClasses() string {
switch t.Position { switch t.Position {
@ -188,7 +204,7 @@ templ AdminEditorToolbar(data ToolbarData) {
if data.Enabled { if data.Enabled {
<div <div
id="bn-admin-toolbar" id="bn-admin-toolbar"
class={ "bn-toolbar fixed z-[9999] flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-full backdrop-blur-md transition-all duration-300", data.PositionClasses() } class={ "bn-toolbar fixed z-[9999] flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-full backdrop-blur-md transition-all duration-300", data.PositionClasses(), data.EnterAnimationClass() }
> >
<style> <style>
/* Toolbar: dark by default (for light pages), light when page has .dark class */ /* Toolbar: dark by default (for light pages), light when page has .dark class */
@ -205,6 +221,33 @@ templ AdminEditorToolbar(data ToolbarData) {
border: 1px solid var(--bn-toolbar-border); border: 1px solid var(--bn-toolbar-border);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.25), 0 8px 10px -6px rgba(0, 0, 0, 0.2); box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.25), 0 8px 10px -6px rgba(0, 0, 0, 0.2);
} }
/* Entrance: slide in from the resting edge, then a brief pulse.
Animates `transform` only; Tailwind v4 centres via the separate
`translate` property, so `-translate-x-1/2` is preserved. Runs
~1s after render, 500ms total, initial page load only. */
@keyframes bn-toolbar-slide-up {
0% { opacity: 0; transform: translateY(1.25rem); }
60% { opacity: 1; transform: translateY(0) scale(1); }
80% { transform: translateY(0) scale(1.05); }
100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes bn-toolbar-slide-down {
0% { opacity: 0; transform: translateY(-1.25rem); }
60% { opacity: 1; transform: translateY(0) scale(1); }
80% { transform: translateY(0) scale(1.05); }
100% { opacity: 1; transform: translateY(0) scale(1); }
}
.bn-toolbar-enter {
animation-duration: 500ms;
animation-delay: 900ms;
animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
animation-fill-mode: both;
}
.bn-toolbar-enter-up { animation-name: bn-toolbar-slide-up; }
.bn-toolbar-enter-down { animation-name: bn-toolbar-slide-down; }
@media (prefers-reduced-motion: reduce) {
.bn-toolbar-enter { animation: none; }
}
/* Light toolbar when page theme is dark (.dark class on html or body) */ /* Light toolbar when page theme is dark (.dark class on html or body) */
.dark .bn-toolbar, html.dark .bn-toolbar, body.dark .bn-toolbar { .dark .bn-toolbar, html.dark .bn-toolbar, body.dark .bn-toolbar {
--bn-toolbar-bg: rgba(250, 250, 250, 0.95); --bn-toolbar-bg: rgba(250, 250, 250, 0.95);
@ -225,6 +268,13 @@ templ AdminEditorToolbar(data ToolbarData) {
.bn-toolbar .bn-toolbar-primary:hover { .bn-toolbar .bn-toolbar-primary:hover {
background: color-mix(in srgb, var(--bn-toolbar-primary-bg) 90%, black); background: color-mix(in srgb, var(--bn-toolbar-primary-bg) 90%, black);
} }
/* Theme tester: highlighted while a light/dark override is forced.
Uses toolbar vars (not site theme tokens) so it renders on any site. */
.bn-toolbar .bn-theme-tester-active,
.bn-toolbar .bn-theme-tester-active:hover {
background: color-mix(in srgb, var(--bn-toolbar-primary-bg) 20%, transparent);
color: var(--bn-toolbar-primary-bg);
}
/* Dropdown styling - inherits toolbar vars */ /* Dropdown styling - inherits toolbar vars */
.bn-toolbar-dropdown { .bn-toolbar-dropdown {
background: var(--bn-toolbar-bg); background: var(--bn-toolbar-bg);
@ -262,28 +312,120 @@ templ AdminEditorToolbar(data ToolbarData) {
<span class={ "w-2 h-2 rounded-full", templ.KV("bg-success", data.Status == "published"), templ.KV("bg-warning", data.Status == "draft"), templ.KV("bg-info", data.Status == "scheduled"), templ.KV("animate-pulse ring-2 ring-warning/50", data.HasUnpublishedChanges) }></span> <span class={ "w-2 h-2 rounded-full", templ.KV("bg-success", data.Status == "published"), templ.KV("bg-warning", data.Status == "draft"), templ.KV("bg-info", data.Status == "scheduled"), templ.KV("animate-pulse ring-2 ring-warning/50", data.HasUnpublishedChanges) }></span>
<span class="bn-toolbar-muted text-xs hidden sm:inline">{ data.StatusLabel() }</span> <span class="bn-toolbar-muted text-xs hidden sm:inline">{ data.StatusLabel() }</span>
</div> </div>
if !data.HidePreviewToggle {
<!-- Divider -->
<div class="bn-toolbar-divider w-px h-5"></div>
<!-- Preview toggle - compact -->
<button
type="button"
class={ "bn-toolbar-hover inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs transition-colors", templ.KV("!bg-info/20 text-info", data.IsPreviewMode()), templ.KV("bn-toolbar-muted", !data.IsPreviewMode()) }
onclick={ togglePreviewMode(data.IsPreviewMode()) }
title={ func() string { if data.IsPreviewMode() { return "Viewing draft - click to view published" } else { return "Viewing published - click to preview draft" } }() }
>
if data.IsPreviewMode() {
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path>
<path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"></path>
</svg>
<span class="hidden sm:inline">Draft</span>
} else {
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
</svg>
<span class="hidden sm:inline">Live</span>
}
</button>
}
<!-- Divider --> <!-- Divider -->
<div class="bn-toolbar-divider w-px h-5"></div> <div class="bn-toolbar-divider w-px h-5"></div>
<!-- Preview toggle - compact --> <!-- Theme tester: cycles site default → forced light → forced dark.
Per-tab override (sessionStorage), applied by bnApplyTheme in head.templ.
Never touches the visitor bn-theme preference. -->
<button <button
type="button" type="button"
class={ "bn-toolbar-hover inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs transition-colors", templ.KV("!bg-info/20 text-info", data.IsPreviewMode()), templ.KV("bn-toolbar-muted", !data.IsPreviewMode()) } id="bn-theme-tester"
onclick={ togglePreviewMode(data.IsPreviewMode()) } class="bn-toolbar-hover bn-toolbar-muted inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs transition-colors"
title={ func() string { if data.IsPreviewMode() { return "Viewing draft - click to view published" } else { return "Viewing published - click to preview draft" } }() } onclick="bnCycleThemeTester()"
title="Theme: site default — click to force light"
> >
if data.IsPreviewMode() { <span data-tt="auto">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z"></path> <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
<path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd"></path> <line x1="8" y1="21" x2="16" y2="21"></line>
<line x1="12" y1="17" x2="12" y2="21"></line>
</svg> </svg>
<span class="hidden sm:inline">Draft</span> </span>
} else { <span data-tt="light" style="display:none">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 20 20" fill="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path> <circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg> </svg>
<span class="hidden sm:inline">Live</span> </span>
} <span data-tt="dark" style="display:none">
<svg xmlns="http://www.w3.org/2000/svg" class="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
</span>
<span data-tt-label class="hidden sm:inline" style="display:none"></span>
</button> </button>
<script>
// Theme tester: per-tab light/dark override for admins. Lives inside
// #bn-admin-toolbar so HTMX outerHTML swaps re-run the sync call.
window.bnCycleThemeTester = function() {
var cur = null;
try { cur = sessionStorage.getItem('bn-theme-override'); } catch (e) {}
var next = cur === 'light' ? 'dark' : (cur === 'dark' ? null : 'light');
try {
if (next) sessionStorage.setItem('bn-theme-override', next);
else sessionStorage.removeItem('bn-theme-override');
} catch (e) {}
if (window.bnApplyTheme) {
window.bnApplyTheme();
} else if (next) {
// Fallback for templates without the bn head script
document.documentElement.classList.toggle('dark', next === 'dark');
}
window.bnSyncThemeTester();
// Let darkmode-switcher blocks refresh their icons
var mode = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
document.querySelectorAll('[data-bn-theme-toggle]').forEach(function(el) {
el.dispatchEvent(new CustomEvent('bn:theme-changed', { detail: { mode: mode } }));
});
};
window.bnSyncThemeTester = function() {
var btn = document.getElementById('bn-theme-tester');
if (!btn) return;
var cur = null;
try { cur = sessionStorage.getItem('bn-theme-override'); } catch (e) {}
var state = (cur === 'light' || cur === 'dark') ? cur : 'auto';
btn.querySelectorAll('[data-tt]').forEach(function(s) {
s.style.display = s.getAttribute('data-tt') === state ? '' : 'none';
});
var lbl = btn.querySelector('[data-tt-label]');
if (state === 'auto') {
lbl.style.display = 'none';
lbl.textContent = '';
} else {
lbl.style.display = '';
lbl.textContent = state === 'light' ? 'Light' : 'Dark';
}
btn.classList.toggle('bn-theme-tester-active', state !== 'auto');
btn.classList.toggle('bn-toolbar-muted', state === 'auto');
btn.title = state === 'auto'
? 'Theme: site default — click to force light'
: (state === 'light'
? 'Theme: forced light — click to force dark'
: 'Theme: forced dark — click to reset to site default');
};
window.bnSyncThemeTester();
</script>
<!-- Blog-specific: Reading time --> <!-- Blog-specific: Reading time -->
if data.IsBlogPost() && data.ReadingTime > 0 { if data.IsBlogPost() && data.ReadingTime > 0 {
<div class="bn-toolbar-muted hidden md:flex items-center gap-1 px-2 text-xs" title="Reading time"> <div class="bn-toolbar-muted hidden md:flex items-center gap-1 px-2 text-xs" title="Reading time">
@ -347,6 +489,21 @@ templ AdminEditorToolbar(data ToolbarData) {
// PageInfoDropdown renders the page info and quick actions dropdown // PageInfoDropdown renders the page info and quick actions dropdown
templ PageInfoDropdown(data ToolbarData) { templ PageInfoDropdown(data ToolbarData) {
<div class="bn-toolbar-dropdown rounded-lg py-2 min-w-[260px] max-w-[320px]"> <div class="bn-toolbar-dropdown rounded-lg py-2 min-w-[260px] max-w-[320px]">
<style>
/* Position-picker chips - shipped with the fragment so styling never
desyncs from the separately-rendered toolbar shell. Uses toolbar
vars (resolve via the enclosing .bn-toolbar) to stay visible in
both inverted themes. */
.bn-toolbar-dropdown .bn-dd-poschip { border-color: var(--bn-toolbar-border); }
.bn-toolbar-dropdown .bn-dd-poschip:hover { background: var(--bn-toolbar-hover); }
.bn-toolbar-dropdown .bn-dd-poschip-active,
.bn-toolbar-dropdown .bn-dd-poschip-active:hover {
background: var(--bn-toolbar-primary-bg);
border-color: var(--bn-toolbar-primary-bg);
}
.bn-toolbar-dropdown .bn-dd-dot { background: var(--bn-toolbar-muted); }
.bn-toolbar-dropdown .bn-dd-dot-active { background: var(--bn-toolbar-primary-fg); }
</style>
<!-- Analytics snapshot --> <!-- Analytics snapshot -->
if data.TodayPageviews > 0 || data.PageviewsTrend != "" { if data.TodayPageviews > 0 || data.PageviewsTrend != "" {
<div class="bn-dd-border px-3 py-2 border-b"> <div class="bn-dd-border px-3 py-2 border-b">
@ -482,15 +639,16 @@ templ PageInfoDropdown(data ToolbarData) {
// positionButton renders a position selector button // positionButton renders a position selector button
templ positionButton(pageID uuid.UUID, pos string, currentPos string, label string) { templ positionButton(pageID uuid.UUID, pos string, currentPos string, label string) {
{{ active := pos == currentPos || (currentPos == "" && pos == "tr") }}
<button <button
type="button" type="button"
class={ "w-8 h-6 rounded border transition-colors flex items-center justify-center", templ.KV("bg-info border-info", pos == currentPos || (currentPos == "" && pos == "tr")), templ.KV("bn-dd-border bn-dd-hover", pos != currentPos && !(currentPos == "" && pos == "tr")) } class={ "bn-dd-poschip w-8 h-6 rounded border transition-colors flex items-center justify-center", templ.KV("bn-dd-poschip-active", active) }
hx-post={ fmt.Sprintf("/toolbar/set-position/%s?pos=%s", pageID, pos) } hx-post={ fmt.Sprintf("/toolbar/set-position/%s?pos=%s", pageID, pos) }
hx-target="#bn-admin-toolbar" hx-target="#bn-admin-toolbar"
hx-swap="outerHTML" hx-swap="outerHTML"
title={ label } title={ label }
> >
<span class={ "w-1.5 h-1.5 rounded-full", templ.KV("bg-info-foreground", pos == currentPos || (currentPos == "" && pos == "tr")), templ.KV("bn-dd-muted", pos != currentPos && !(currentPos == "" && pos == "tr")) }></span> <span class={ "w-1.5 h-1.5 rounded-full", templ.KV("bn-dd-dot-active", active), templ.KV("bn-dd-dot", !active) }></span>
</button> </button>
} }

File diff suppressed because one or more lines are too long