|
|
@@ -290,9 +290,136 @@ with a `BOOTSTRAP_ADMIN` audit row.
|
|
|
|
|
|
### Upcoming
|
|
|
|
|
|
-Nothing scheduled. Residual follow-ups are in §10; the main outstanding
|
|
|
-item is a human-run walkthrough of [ACCEPTANCE.md](ACCEPTANCE.md)
|
|
|
-(now covering Phases 1–13) in a running container.
|
|
|
+- [ ] **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.
|
|
|
|
|
|
## 10. Residual known gaps / deferred items
|
|
|
|
|
|
@@ -350,13 +477,13 @@ 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) and §9 Upcoming is empty — no scheduled work.
|
|
|
-> Outstanding items are in §10 (mostly a human-run acceptance
|
|
|
-> walkthrough in the running container). If you plan to take on a new
|
|
|
-> phase, append its plan to §9 Upcoming first; when it ships, 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.
|
|
|
+> 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.
|
|
|
|
|
|
Claude should verify what's described here against actual repo state
|
|
|
before acting — nothing here is load-bearing once it grows stale.
|