xtablo-source/backend/templates/app_layout_helpers.go
Arthur Belleville 9ba650b345
feat(18): restyle sidebar and header to match production design
- Sidebar: Tailwind utilities, French labels (Aperçu/Tâches/Projets/Planning/Discussions/Fichiers), hr separators, collapse button on group hover, tablo list with circle icons, org footer with avatar + "1 membre"
- Header: 75px height, border-b #EAECF0, search input left, bell + avatar-dropdown right (no breadcrumb visible — retained sr-only for a11y + tests)
- Layout: flex instead of grid, dashboard-main no padding, dashboard-main-content wrapper at 2rem
- Tests updated for new search-input assertion

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-17 16:00:26 +02:00

61 lines
2.2 KiB
Go

package templates
import "strings"
// BreadcrumbItem represents one crumb in the top header breadcrumb trail.
// If Href is empty, the item renders as plain text (current page — no link).
type BreadcrumbItem struct {
Label string
Href string
}
// sidebarNavItem describes one entry in the sidebar primary navigation list.
type sidebarNavItem struct {
Href string
Label string
Icon string
Active bool
DividerBefore bool
}
// navItemWrapperClass returns the Tailwind class string for a nav item wrapper.
func navItemWrapperClass(active bool) string {
if active {
return "flex w-full px-2.5 py-2 rounded-md cursor-pointer bg-purple-100 font-semibold"
}
return "flex w-full px-2.5 py-2 rounded-md cursor-pointer hover:bg-gray-100 font-medium"
}
// navItemLabelClass returns the Tailwind class string for a nav item text label.
func navItemLabelClass(active bool) string {
if active {
return "text-base font-normal text-[#804EEC]"
}
return "text-base font-normal text-gray-500"
}
// navItemIconClass returns the Tailwind class string for a nav item icon wrapper.
func navItemIconClass(active bool) string {
if active {
return "[&>svg]:w-5 [&>svg]:h-5 text-[#804EEC]"
}
return "[&>svg]:w-5 [&>svg]:h-5 text-gray-500"
}
// isActivePath reports whether activePath matches href.
func isActivePath(activePath string, href string) bool {
return strings.TrimSpace(activePath) != "" && activePath == href
}
// sidebarPrimaryNavItems returns the ordered sidebar nav items.
// French labels match the production app. DividerBefore adds an <hr> separator before the item.
func sidebarPrimaryNavItems(activePath string) []sidebarNavItem {
return []sidebarNavItem{
{Href: "/", Label: "Aperçu", Icon: "panels", Active: isActivePath(activePath, "/")},
{Href: "#", Label: "Tâches", Icon: "tasks", Active: false, DividerBefore: true},
{Href: "/", Label: "Projets", Icon: "layers", Active: false},
{Href: "/planning", Label: "Planning", Icon: "planning", Active: isActivePath(activePath, "/planning"), DividerBefore: true},
{Href: "#", Label: "Discussions", Icon: "chat", Active: false},
{Href: "#", Label: "Fichiers", Icon: "files", Active: false},
}
}