feat: swap theme switcher and account dropdown menu positions

This commit is contained in:
juancwu 2026-04-22 22:56:14 +00:00
commit 74795c583c

View file

@ -4,9 +4,9 @@ import (
"git.juancwu.dev/juancwu/budgit/internal/ctxkeys" "git.juancwu.dev/juancwu/budgit/internal/ctxkeys"
"git.juancwu.dev/juancwu/budgit/internal/model" "git.juancwu.dev/juancwu/budgit/internal/model"
"git.juancwu.dev/juancwu/budgit/internal/routeurl" "git.juancwu.dev/juancwu/budgit/internal/routeurl"
"git.juancwu.dev/juancwu/budgit/internal/ui/blocks"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/avatar" "git.juancwu.dev/juancwu/budgit/internal/ui/components/avatar"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/breadcrumb" "git.juancwu.dev/juancwu/budgit/internal/ui/components/breadcrumb"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/button"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/csrf" "git.juancwu.dev/juancwu/budgit/internal/ui/components/csrf"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/dropdown" "git.juancwu.dev/juancwu/budgit/internal/ui/components/dropdown"
"git.juancwu.dev/juancwu/budgit/internal/ui/components/icon" "git.juancwu.dev/juancwu/budgit/internal/ui/components/icon"
@ -47,6 +47,18 @@ templ App(title string, sidebarContent ...templ.Component) {
} }
@sidebar.Footer() { @sidebar.Footer() {
@sidebar.Menu() { @sidebar.Menu() {
@sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{
Size: sidebar.MenuButtonSizeSm,
Attributes: templ.Attributes{
"data-theme-switcher": "true",
"aria-label": "Toggle theme",
},
}) {
@icon.Eclipse(icon.Props{Class: "size-4"})
<span>Theme</span>
}
}
@sidebar.MenuItem() { @sidebar.MenuItem() {
@sidebar.MenuButton(sidebar.MenuButtonProps{ @sidebar.MenuButton(sidebar.MenuButtonProps{
Href: "mailto:" + cfg.SupportEmail, Href: "mailto:" + cfg.SupportEmail,
@ -60,15 +72,6 @@ templ App(title string, sidebarContent ...templ.Component) {
<div class="px-2 py-1"> <div class="px-2 py-1">
<span class="text-xs text-muted-foreground">App version: { cfg.Version }</span> <span class="text-xs text-muted-foreground">App version: { cfg.Version }</span>
</div> </div>
@sidebar.Separator()
@sidebar.Menu() {
@sidebar.MenuItem() {
{{ user := ctxkeys.User(ctx) }}
if user != nil {
@AppSidebarDropdown(user)
}
}
}
} }
} }
@sidebar.Inset() { @sidebar.Inset() {
@ -88,7 +91,10 @@ templ App(title string, sidebarContent ...templ.Component) {
} }
</div> </div>
<div class="ml-auto flex items-center gap-4"> <div class="ml-auto flex items-center gap-4">
@blocks.ThemeSwitcher() {{ user := ctxkeys.User(ctx) }}
if user != nil {
@AppAccountDropdown(user)
}
</div> </div>
</div> </div>
</header> </header>
@ -101,7 +107,7 @@ templ App(title string, sidebarContent ...templ.Component) {
} }
} }
templ AppSidebarDropdown(user *model.User) { templ AppAccountDropdown(user *model.User) {
{{ displayName := user.Email }} {{ displayName := user.Email }}
{{ {{
if user.Name != nil && *user.Name != "" { if user.Name != nil && *user.Name != "" {
@ -110,28 +116,28 @@ templ AppSidebarDropdown(user *model.User) {
}} }}
@dropdown.Dropdown() { @dropdown.Dropdown() {
@dropdown.Trigger() { @dropdown.Trigger() {
@sidebar.MenuButton(sidebar.MenuButtonProps{ @button.Button(button.Props{
Size: sidebar.MenuButtonSizeLg, Variant: button.VariantGhost,
Size: button.SizeIcon,
Class: "rounded-full",
Attributes: templ.Attributes{
"aria-label": "Account menu",
},
}) { }) {
<div id="sidebar-avatar" hx-swap-oob="true"> <div id="account-avatar" hx-swap-oob="true">
@avatar.Avatar(avatar.Props{Class: "size-8 rounded-lg"}) { @avatar.Avatar(avatar.Props{Class: "size-8 rounded-full"}) {
@avatar.Fallback() { @avatar.Fallback() {
{ strings.ToUpper(string(displayName[0])) } { strings.ToUpper(string(displayName[0])) }
} }
} }
</div> </div>
<div id="sidebar-user-name" hx-swap-oob="true" class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-medium">{ displayName }</span>
<span class="truncate text-xs text-muted-foreground">{ user.Email }</span>
</div>
@icon.ChevronsUpDown(icon.Props{Class: "ml-auto size-4"})
} }
} }
@dropdown.Content(dropdown.ContentProps{ @dropdown.Content(dropdown.ContentProps{
Class: "w-56", Class: "w-56",
Placement: dropdown.PlacementTopStart, Placement: dropdown.PlacementBottomEnd,
}) { }) {
<div id="dropdown-user-label" hx-swap-oob="true"> <div id="account-dropdown-label" hx-swap-oob="true">
@dropdown.Label() { @dropdown.Label() {
<div class="flex flex-col"> <div class="flex flex-col">
<span class="font-medium">{ displayName }</span> <span class="font-medium">{ displayName }</span>
@ -144,7 +150,7 @@ templ AppSidebarDropdown(user *model.User) {
Href: "/app/settings", Href: "/app/settings",
}) { }) {
<span class="flex items-center"> <span class="flex items-center">
@icon.Settings(icon.Props{Class: "mr-2"}) @icon.Settings(icon.Props{Class: "size-4 mr-2"})
Settings Settings
</span> </span>
} }
@ -156,7 +162,7 @@ templ AppSidebarDropdown(user *model.User) {
}, },
}) { }) {
<span class="flex items-center"> <span class="flex items-center">
@icon.LogOut(icon.Props{Class: "mr-2"}) @icon.LogOut(icon.Props{Class: "size-4 mr-2"})
Log out Log out
</span> </span>
} }