---
phase: 18-app-shell-navigation
plan: "03"
subsystem: templates/css/web
tags: [go, templ, page-header, breadcrumb, avatar-dropdown, css, nav]
dependency_graph:
  requires: [18-01, 18-02]
  provides: [PageHeader templ component, avatar dropdown with logout, /settings stub, page-header CSS]
  affects: [backend/templates/app_layout.templ, backend/internal/web/ui/app.css, backend/static/tailwind.css, backend/internal/web/router.go, backend/internal/web/handlers_tablos_test.go]
tech_stack:
  added: []
  patterns: [native details/summary HTML dropdown, outside-click JS listener, three-zone header layout]
key_files:
  created: []
  modified:
    - backend/templates/app_layout.templ
    - backend/internal/web/ui/app.css
    - backend/static/tailwind.css
    - backend/internal/web/router.go
    - backend/internal/web/handlers_tablos_test.go
decisions:
  - Native details/summary for avatar dropdown (D-06) - no Alpine.js required
  - Logout form moves from SidebarOrganizationFooter to avatar dropdown with CSRF token (T-18-03-01 mitigated)
  - /settings as inline stub handler (no template) - full settings page is future work
  - PageHeader replaces Plan 01 breadcrumb/headerActions stubs in AppLayout
metrics:
  duration: ~15min
  completed: "2026-05-17"
  tasks: 2
  files: 5
---

# Phase 18 Plan 03: PageHeader Component and Avatar Dropdown Summary

**One-liner:** PageHeader templ component with three-zone layout (breadcrumb/search/avatar), native details/summary avatar dropdown with logout and settings link, page-header CSS, /settings stub route, and updated tests delivering NAV-02.

## Tasks Completed

| # | Task | Commit | Files |
|---|------|--------|-------|
| 1 | Implement PageHeader component and wire into AppLayout | c190723 | app_layout.templ |
| 2 | Add page-header CSS to app.css, add /settings stub route, update tests | 9a70553 | app.css, tailwind.css, router.go, handlers_tablos_test.go |

## Decisions Made

- **Native details/summary for avatar dropdown** (D-06) — no Alpine.js, small inline JS for outside-click close; the approach is standards-compliant and works without any framework
- **Logout moved from SidebarOrganizationFooter to avatar dropdown** — CSRF token via `ui.CSRFField(csrfToken)` maintained (T-18-03-01 mitigated); logout continues to work
- **/settings as inline http.HandlerFunc stub** — avoids creating a full template for a placeholder page; satisfies D-06 requirement that the settings link navigates somewhere
- **pageTitle fallback in breadcrumb** — when breadcrumb slice is empty, falls back to rendering pageTitle as the current item so the header is never empty

## Verification

- `templ generate ./...` — zero errors (exit 0)
- `go build ./...` — zero errors (exit 0)
- `go test ./...` — all tests pass (backend/internal/web: 0.261s, backend/templates: 0.459s)
- `grep -c "page-header" backend/static/tailwind.css` — returns 1
- `grep -c "header-avatar-menu" backend/static/tailwind.css` — returns 1
- TestTablosDashboard_Header test exists and compiled correctly (skips due to no test DB in CI)
- TestTablosDashboard_Sidebar has new page-header and breadcrumb assertions

## Deviations from Plan

None — plan executed exactly as written.

## Known Stubs

- `/settings` returns a minimal inline HTML stub (not a full AppLayout page). The full settings page is deferred to a future phase.
- Bell and inbox buttons in the header are disabled placeholders — no notification system wiring in Phase 18.
- Search placeholder is visual-only — no backend wiring.
- `SidebarOrganizationFooter` component remains in `app_layout.templ` but is no longer called (was removed from DashboardSidebar in Plan 02, logout moved to avatar dropdown in this plan). Safe to remove in a cleanup pass.
- `SidebarProjectsSection` component remains in `app_layout.templ` but is no longer called (Plan 02 inlined the projects section). Safe to remove in a cleanup pass.

## Threat Flags

None — T-18-03-01 (CSRF on logout form) was mitigated by `ui.CSRFField(csrfToken)`. T-18-03-02 (email in dropdown) is handled by templ auto-escaping. T-18-03-03 and T-18-03-04 are accepted/already mitigated.

## Self-Check: PASSED

- `backend/templates/app_layout.templ` — exists, contains PageHeader component and @PageHeader call in AppLayout
- `backend/internal/web/ui/app.css` — exists, contains page-header CSS block
- `backend/static/tailwind.css` — exists, grep returns 1 for both page-header and header-avatar-menu
- `backend/internal/web/router.go` — exists, contains /settings route
- `backend/internal/web/handlers_tablos_test.go` — exists, contains TestTablosDashboard_Header test
- Commits c190723, 9a70553 — both present in git log
