|
|
@@ -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
|