xtablo-source/.planning/phases/15-dashboard-tablos/15-CONTEXT.md
2026-05-16 21:08:44 +02:00

9.8 KiB
Raw Blame History

Phase 15: Dashboard & Tablos - Context

Gathered: 2026-05-16 Status: Ready for planning

## Phase Boundary

Replace the current top-nav shell + simple card list with a sidebar-based app layout (AppLayout) and project-card grid that matches the go-backend visual design. Phase 15 delivers:

  • New AppLayout templ with sidebar (brand, nav items, tablo list section, user footer)
  • Tablo dashboard restyled as a 3-column project-card grid
  • Tablo empty state uses the ui.EmptyState component
  • All existing tablo CRUD handler tests pass unchanged

Does NOT include: tablo detail restyling (Phase 16), chat/planning restyling (Phase 17), sidebar collapse JS interaction, mobile-responsive sidebar breakpoints.

## Implementation Decisions

App Layout Shell

  • D-L01: Create a new AppLayout(title string, user *auth.User, csrfToken string, activePath string, tablos []sqlc.Tablo) templ in backend/templates/. All authenticated dashboard pages use AppLayout. The old Layout templ is preserved but no longer used by dashboard pages (it becomes dead code, can be removed in a future cleanup).
  • D-L02: AppLayout uses the .dashboard-shell CSS grid (sidebar + main columns) from go-backend/internal/web/ui/app.css. Port .dashboard-shell, .dashboard-sidebar, .sidebar-nav-shell, all .sidebar-* CSS, .sidebar-organization, and .dashboard-main into backend/internal/web/ui/app.css (a new CSS file, not auth.css).
  • D-L03: Active nav item: AppLayout receives activePath string. A helper function (pure Go, not templ) returns "is-active" class when a nav item's href matches activePath. Handlers pass the current route path explicitly (e.g., "/", "/planning", "/tablos").
  • D-L04: Scripts: AppLayout loads htmx.min.js, sortable.min.js, and discussion-sse.js — same as the current Layout. No change to script loading.

Sidebar Nav Items

  • D-N01: Match go-backend nav item set: Dashboard (/), Tablos (/ or tablo overview — same as Dashboard for now), Tasks, Planning (/planning), Chat, Files, Settings. Use go-backend's dashboard_components.templ icon SVGs verbatim.
  • D-N02: Routes that exist in the backend get real href values: Dashboard (/), Planning (/planning). Routes not yet built as standalone pages (Tasks, Files, Settings) render as visual nav items with no href attribute (display only, cursor: default on the item).
  • D-N03: Chat is per-tablo (linked from tablo detail, not a top-level nav destination). In the sidebar nav, Chat links to / (dashboard) as a placeholder, or is rendered as a visual-only item like Tasks — Claude's discretion.
  • D-N04: Sidebar-projects section: shows the user's tablos as a list with a colored circle icon (derived from tablo color field) + truncated title. Each item links to /tablos/{id}. Section label: "Projects" (English, matching backend convention).

Tablo Project Cards

  • D-C01: Tablo dashboard uses the .project-grid 3-column CSS grid layout from go-backend. Port .project-grid, .project-card, .project-card-top, and related CSS into the new app.css.
  • D-C02: Each project card shows (matching go-backend exactly): colored circle avatar (top-left) + title + edit icon button (top-right) + delete icon button (top-right) + creation date (bottom row).
  • D-C03: Color avatar: use tablo.Color field when set. When null/empty, show a default neutral/gray circle (no derived color, no initials). The circle renders via a small <span> styled with background-color, matching go-backend's .sidebar-project-icon pattern.
  • D-C04: Edit and delete action icons use @ui.IconButton(...) from the design system (Phase 13 component). The HTMX attributes for edit (hx-get=/tablos/{id}/edit) and delete (hx-delete=/tablos/{id}) are preserved from the current TabloCard implementation.
  • D-C05: The "New tablo" button and inline create form slot (#create-form-slot) move to a section header above the grid, matching go-backend's .overview-section-heading pattern.

Tablo Empty State

  • D-E01: When no tablos exist, use @ui.EmptyState(ui.EmptyStateProps{...}) — the Phase 13 component. Replace the current raw HTML empty state in TablosEmptyState(). Title: "No tablos yet". Description: "Create your first tablo to get started." Action: "New tablo" button.
  • D-F01: Include a sidebar footer matching go-backend's .sidebar-organization section. Shows: avatar circle (first letter of email, colored background) + user email + a small account link. Logout is moved from the old top-nav into this footer area.
  • D-F02: The account/settings page doesn't exist yet, so the footer button/link only shows the email + logout button. No settings navigation for Phase 15. The .organization-button wraps a simple display element, not a dropdown.
  • D-F03: Port .sidebar-organization, .organization-button, .organization-avatar, .organization-name, .organization-meta CSS from go-backend into app.css.

Claude's Discretion

  • Exact set of SVG icons for each nav item (copy from go-backend dashboard_components.templ — no new icon design needed)
  • Whether the sidebar-projects section is a separate templ component or inline in AppLayout (prefer separate SidebarProjectsSection for testability)
  • Exact color for the neutral avatar fallback (use --color-surface-muted or similar design token)
  • Whether sidebar-footer avatar background color is derived from email hash or a fixed brand color

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Product Scope

  • .planning/ROADMAP.md — Phase 15 goal, success criteria (5 criteria), requirements DASH-01/02/03
  • .planning/REQUIREMENTS.md — DASH-01 (sidebar design), DASH-02 (project-card layout), DASH-03 (empty state)
  • .planning/PROJECT.md — v3.0 scope: visual polish only, go-backend is the visual reference

Reference Implementation (source of truth)

  • go-backend/internal/web/views/dashboard_components.templDashboardPage, DashboardSidebar, SidebarProjectsSection, SidebarNavItem, SidebarOrganization — port structure from here
  • go-backend/internal/web/ui/app.css — ALL dashboard/sidebar CSS: .dashboard-shell, .dashboard-sidebar, .sidebar-nav-shell, all .sidebar-* classes, .sidebar-organization, .dashboard-main, .project-grid, .project-card, .project-card-top — extract these sections only
  • go-backend/static/logo_dark.png — brand logo already copied to backend/static/ in Phase 14

Current Backend (files being changed)

  • backend/templates/layout.templ — current top-nav Layout; being superseded by AppLayout for dashboard pages
  • backend/templates/tablos.templ — TablosDashboard, TabloCard, TablosEmptyState — all being restyled
  • backend/internal/web/handlers_tablos.go (or equivalent) — handlers need to pass tablos list + activePath to AppLayout

Design System (Phase 13 — already in backend)

  • backend/internal/web/ui/empty-state.css + backend/internal/web/ui/*.templui.EmptyState, ui.IconButton, ui.Button components already available
  • backend/internal/web/ui/base.css — design tokens; all new CSS in app.css must use var(--...) tokens

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • ui.EmptyState (Phase 13): Ready to use for TablosEmptyState — replace raw HTML with @ui.EmptyState(ui.EmptyStateProps{Title, Description, Icon, Action})
  • ui.IconButton (Phase 13): Use for edit + delete icon buttons on project cards — replaces any raw icon buttons
  • ui.Button (Phase 13): "New tablo" button stays as @ui.Button(...) with same HTMX attrs
  • backend/static/logo_dark.png: Already exists (Phase 14) — use for sidebar brand logo

Established Patterns

  • AuthLayout pattern (Phase 14): New AppLayout should follow the same package + templ structure — package templates, explicit param list, children via { children... }
  • sqlc.Tablo type: Has Color pgtype.Text (nullable), Title string, ID pgx.UUID, CreatedAt pgtype.Timestamptz — all needed for sidebar-projects and project cards
  • Handler pattern: Handlers currently call Layout(title, user, csrfToken) — will change to AppLayout(title, user, csrfToken, activePath, tablos) requiring handlers to fetch tablos list

Integration Points

  • backend/internal/web/handlers_tablos.go: TablosDashboardHandler fetches tablos for display; needs to also pass tablos to AppLayout for the sidebar-projects section (already has them)
  • Other handlers (PlanningHandler, ChatHandler, etc.): Will need to fetch the user's tablos list to populate the sidebar — this is a cross-handler concern worth factoring into a shared helper

</code_context>

## Specific Ideas
  • Sidebar visual: match go-backend's DashboardSidebar structure verbatim — brand logo (logo_dark.png, 4rem×4rem rounded), "XTablo" title, nav list, projects section, footer
  • Project card: match go-backend .project-card + .project-card-top layout — white card, 1rem border-radius, 1rem padding, edit/delete icon buttons in top-right corner
  • Sidebar footer: full .sidebar-organization treatment — avatar circle with first letter + email + logout button inside .organization-button
## Deferred Ideas
  • Sidebar collapse toggle (JS interaction) — requires client-side JS to persist collapsed state; deferred to a future polish phase
  • Mobile-responsive sidebar (hamburger menu, slide-in drawer) — deferred; Phase 15 desktop-first only
  • Tablo color picker in the create/edit form — the color field exists in the DB but no UI to set it; deferred to a future enhancement
  • Tasks, Files, Settings as standalone pages — nav items shown as visual-only until those pages are built

Phase: 15-dashboard-tablos Context gathered: 2026-05-16