Ver código fonte

HANDOFF.md: mark Phase 14 shipped

Maintenance rule (§14). Moves Phase 14 from Upcoming → Shipped
with its SHA (101cc57), resets §9 Upcoming to the "Nothing
scheduled" template (matches the shape used after Phase 12 / 13
shipped), updates the §12 resume prompt to "1–14 shipped, no
scheduled work," and appends 15695ab (Phase 14 plan) plus
101cc57 (Phase 14 code) to the §13 git history block so it
matches `git log`.

No §3 directory refresh (no new files — pure edits to
layout.php, app.js, ACCEPTANCE.md). Test count unchanged at
88 / 208; §11 already reflects that.

No code changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
achiappa 2 semanas atrás
pai
commit
d59120c7e1
1 arquivos alterados com 33 adições e 138 exclusões
  1. 33 138
      HANDOFF.md

+ 33 - 138
HANDOFF.md

@@ -288,138 +288,32 @@ with a `BOOTSTRAP_ADMIN` audit row.
       both the Columns dropdown (Phase 10) and this phase's focus
       auto-hide — new-task cells are now recognised by both systems.
 
+- [x] **Phase 14 — Hamburger menu groups admin utilities + Sign out**
+      (`101cc57`): `views/layout.php` moves Workers / Users / Audit
+      log / Sign out into a dropdown behind a `<button
+      data-menu-trigger>` with an inline-SVG hamburger (three
+      `<line>`s, `stroke-current`, no external asset). The `<div
+      id="app-menu" data-menu role="menu" hidden>` panel is
+      absolutely positioned with `min-w-[12rem]`, rounded border,
+      `bg-white shadow-lg`, items `px-3 py-2 text-sm
+      hover:bg-slate-50` plus a focus ring. Admins see Workers /
+      Users / Audit log / `<hr>` / Sign out; non-admins see just
+      Sign out (no divider). Sprints, New sprint (admin only), and
+      the user badge stay inline. Sign out remains a native
+      `<form method="post" action="/auth/logout">` with the
+      `_csrf` hidden input — no JS-driven POST. `public/assets/js/
+      app.js` gains a ~30-line vanilla-JS IIFE (document.
+      querySelector + addEventListener, no jQuery) that toggles
+      `hidden` + `aria-expanded` on click, closes on outside-click
+      / Escape (returning focus to the trigger) / any role=
+      "menuitem" click. CSP stays strict. Zero PHPUnit changes —
+      88 / 208 holds. ACCEPTANCE.md gains a "Phase 14 — Hamburger
+      menu" section with the four manual scenarios from the plan.
+
 ### Upcoming
 
-- [ ] **Phase 14 — Hamburger menu groups admin utilities + Sign out**
-
-      **Problem.** The site header currently renders every nav link as a
-      top-level anchor: Sprints, Workers, Users, New sprint, Audit log,
-      display-name, and a Sign-out `<button>` in a `<form>`. On a
-      reasonably wide screen this is already six hit-targets; at laptop
-      widths the row wraps or compresses the display name. More
-      importantly, "Workers / Users / Audit log" are *administrative*
-      concerns — they're not the primary workflow (which is opening a
-      sprint) — but they share visual weight with the real actions.
-      Sign out is housekeeping and deserves even less real estate.
-
-      **Goal.** Tuck **Workers, Users, Audit log, Sign out** into a
-      hamburger-icon dropdown on the right of the header. Keep
-      **Sprints** and **New sprint** visible as primary actions. The
-      user's display name + admin badge stay visible too.
-
-      **Scope (plan).**
-
-      1. **View — `views/layout.php`.**
-         - Replace the flat `<nav>` content with two segments:
-           (a) primary links (Sprints, New sprint) and the user
-           badge, rendered as today;
-           (b) a `<button data-menu-trigger aria-expanded="false"
-           aria-haspopup="true" aria-controls="app-menu">` carrying
-           an inline SVG hamburger icon (three stacked `<rect>`s or
-           `<line>`s, width/height 20, stroke-current — no external
-           image, no font icons, CSP-clean).
-         - Next to the button, a `<div id="app-menu" data-menu
-           role="menu" hidden class="...">` absolutely positioned
-           dropdown that contains the four items in this order:
-             * `<a href="/workers" role="menuitem">Workers</a>` — admin only
-             * `<a href="/users"   role="menuitem">Users</a>`   — admin only
-             * `<a href="/audit"   role="menuitem">Audit log</a>` — admin only
-             * a visual divider (`<hr>`)
-             * the existing Sign-out `<form method="post" action="/auth/logout">`
-               with its CSRF hidden input; the submit button gets
-               `role="menuitem"` and matches the other items' styling.
-         - Non-admin users see a menu containing just the Sign-out
-           form, preceded by no divider. The hamburger is always
-           rendered when a user is signed in (simpler than
-           conditionally hiding it for non-admins — the one item
-           still reads fine inside the dropdown).
-         - Signed-out state is unchanged — still the inline "Sign
-           in" link.
-
-      2. **JS — `public/assets/js/app.js`.**
-         - Add a small controller (≤ 25 lines). `[data-menu-trigger]`
-           toggles `[hidden]` on `[data-menu]` and flips
-           `aria-expanded`. Close on:
-             * outside-click (pattern copied from
-               `sprint-planner.js`'s owner-filter dropdown);
-             * `Escape` keypress (focus returns to the trigger);
-             * clicking any `role="menuitem"` inside (so following a
-               link feels snappy and Sign-out's form submit isn't
-               visually delayed).
-         - No dependency on jQuery — `app.js` today is vanilla JS
-           (see the `data-href` handler); keep it that way.
-
-      3. **Styling.**
-         - Menu panel: rounded border, white bg, `shadow-lg`, min-w
-           ~12rem, 1-px slate border. Items: `px-3 py-2 text-sm
-           text-slate-700 hover:bg-slate-50` matching the settings
-           page's row styling. The Sign-out button inherits
-           `font-[inherit] text-left w-full` so it reads as a menu
-           row, not a form button.
-         - Hamburger button: `p-2 rounded-md hover:bg-slate-100`,
-           24×24 icon. `aria-label="Open menu"` on the button since
-           the icon is decorative.
-         - Focus-ring: `focus:outline-none focus:ring-2
-           focus:ring-slate-400` on both the trigger and each item.
-
-      4. **A11y.**
-         - `role="menu"` on the panel, `role="menuitem"` on each
-           item, `aria-expanded` on the trigger, `aria-controls`
-           pointing at the panel id.
-         - Keyboard: Enter/Space on trigger opens the menu and
-           focuses the first item. Arrow-down/up cycles items
-           (out of scope for a first cut — note as a follow-up if
-           screen-reader users complain; the menu is short enough
-           that tab-cycling is usable).
-         - The Sign-out button stays a real `<button type="submit">`
-           inside a real `<form method="post">` — no JS-driven POST,
-           preserves the `_csrf` guard.
-
-      5. **Edge cases.**
-         - **Hydration timing.** `app.js` is loaded with `defer`, so
-           the menu starts closed by virtue of `hidden` in the HTML.
-           No flash.
-         - **Very narrow screens.** The primary links (Sprints / New
-           sprint) already wrap in the current layout on mobile;
-           this phase does not make them responsive — deferred to
-           §10 if a real mobile need surfaces.
-         - **Sign-out posts through fine.** The enclosing form
-           submit is a native action; outside-click logic ignores
-           clicks on the submit button (handled by the
-           role="menuitem" close-on-click rule firing *after* the
-           form submission is already in-flight — native `<form>`
-           submit doesn't need the menu to stay open).
-
-      6. **Tests.** Zero PHPUnit additions — view-only change, same
-         pattern as Phase 10 and 13. Manual acceptance in
-         [ACCEPTANCE.md](ACCEPTANCE.md), add a new "Phase 14 —
-         Hamburger menu" section with:
-           (a) signed-in admin: trigger opens dropdown with Workers
-               / Users / Audit log / Sign out;
-           (b) signed-in non-admin: dropdown contains only Sign out;
-           (c) outside-click and Escape close the menu;
-           (d) Sign out from the menu still logs out with a valid
-               CSRF token (one full loop).
-
-      **Out of scope.**
-      - A full responsive mobile navigation (collapse of primary
-        links, off-canvas drawer, etc.). Deferred; this phase only
-        moves the admin / utility items into a dropdown.
-      - Theming or a dark-mode toggle inside the menu. Separate
-        concern, no request yet.
-      - Reordering `Workers / Users / Audit log / Sign out` — kept
-        in the order the user listed.
-      - Making the menu sticky on scroll. Header is already
-        non-sticky.
-
-      **Spec alignment.**
-      - §3 layout: no new files or directories (views/layout.php
-        and public/assets/js/app.js both already exist).
-      - §6 routes: unchanged — the menu links to existing pages.
-      - §7 audit: unchanged — Sign-out still emits its LOGOUT row.
-      - §11: phpunit count stays 88.
-      - CSP (Phase 11) stays strict — no inline handlers, no new
-        script host.
+- Nothing scheduled. When a new phase is ready, drop its plan
+  here and flip the checkbox when it ships (see §14).
 
 ## 10. Residual known gaps / deferred items
 
@@ -476,14 +370,13 @@ vendor/bin/phpunit
 Tell Claude:
 
 > Working on `/Users/achiappa/Development/claude_code_private/sprint_planer_web`.
-> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. Phases 1–13 are
-> shipped (see §9); Phase 14 (hamburger menu grouping Workers / Users /
-> Audit log / Sign out) is planned but not implemented — the scope is
-> in §9 under Upcoming. Other outstanding items are in §10 (mostly a
-> human-run acceptance walkthrough in the running container). If I ask
-> you to work Phase 14, follow the maintenance rule in §14 — commit
-> code, then commit a HANDOFF.md update separately that moves the
-> entry from Upcoming → Shipped with its SHA.
+> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. Phases 1–14
+> are shipped (see §9); no scheduled work — §9 Upcoming is empty.
+> Outstanding items are in §10 (mostly a human-run acceptance
+> walkthrough in the running container). If a new phase comes up,
+> follow the maintenance rule in §14 — commit code, then commit a
+> HANDOFF.md update separately that moves the entry from Upcoming
+> → Shipped with its SHA.
 
 Claude should verify what's described here against actual repo state
 before acting — nothing here is load-bearing once it grows stale.
@@ -491,6 +384,8 @@ before acting — nothing here is load-bearing once it grows stale.
 ## 13. Git history (as of this handoff)
 
 ```
+101cc57 Phase 14: hamburger menu groups admin utilities + Sign out
+15695ab HANDOFF.md: add Phase 14 plan (hamburger menu)
 23ab365 Fix: stamp data-col on JS-built task row cells
 d0fdf53 HANDOFF.md: mark Phase 13 shipped
 b027c5d Phase 13: Focus filter + Reset in the task list