Skip to content

Commit 735cd79

Browse files
authored
Merge pull request #69 from dknauss/release/v1.3.0-prep
v1.3.0 pre-tag: reduced-motion first-run fix + readme/demo polish
2 parents e992d8d + 623bf06 commit 735cd79

6 files changed

Lines changed: 46 additions & 3 deletions

File tree

.planning/PROJECT.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ and `.planning/milestones/` for records.
116116
- [ ] V2-15 — role cloning / per-user menu hiding
117117
- [] V2-16 — WooCommerce-first third-party menu compatibility — **delivered by milestone R1** (research; full 6-plugin survey → COMPAT-xx backlog). Forward production fixes now tracked as FIX-xx (COMPAT-01/02/03 highest priority).
118118
- [ ] V2-17 — single-site privileged editor tier (edges toward the Out-of-Scope “page locking” line; enforced tier likely belongs in wp-sudo or a documented bridge)
119+
- [ ] UX-11 — first-run guided tour, replacing the one-shot pulse (an ineffective ambient indicator). **Direction (discussed 2026-06-30):** a hand-rolled, lightweight, accessible **coachmark** — a 4–5 step anchored walkthrough (click-to-edit → controls panel → reorder via drag/▲▼ → icon/visibility → exit/reset), **first-run gated (localStorage) AND replayable via a persistent toolbar “?” control**. ESC / skip / next / back, focus-managed, `wp.a11y.speak` announcements, reduced-motion-aware. Hand-rolled (no tour library — driver.js/Shepherd/intro.js rejected) to keep the bundle lean and a11y under our control. Removes the ambient purple flash. Its own phase; out of v1.3.0. Pairs naturally with [[BUG-09]] (same first-run/menu-highlight code).
120+
- [ ] DEMO-01 — slug-resolution showcase demo: a Playground demo that actually demonstrates FIX-01/02/03, not just a busier menu. Needs a **pre-seeded `maestro_config`** whose override keys are in one slug form (e.g. `&`-encoded taxonomy, `ver=`-stamped, absolute-URL) while the menu renders another, so the user sees the override still land. Prefer a lightweight demo-only **fixture mu-plugin** (registers items with the R1 survey slug shapes; deterministic, near-zero Playground boot cost) over heavy real plugins. Optional secondary **“Try it with WooCommerce”** opt-in blueprint (wizard suppressed, version pinned) for name recognition; skip Elementor in the live demo (heaviest, onboarding-noisy, CSS-hides 2 of 3 menus per SURV-04). Out of v1.3.0 scope.
119121

120122
### Out of Scope
121123

.planning/REQUIREMENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Same code area or backlog, intentionally not in v1.3.0 (per scope decision):
4848
- **COMPAT-04** — level-qualified (parent vs submenu) match keys so shared-slug renames/hides don't hit both. Same resolve path, but changes match semantics more invasively; revisit after FIX-01/02/03 land.
4949
- **COMPAT-07** — preserve badge/HTML-in-title on rename (4/6 plugins). Feature-sized, separate code path (`Replay::replay()` title write).
5050
- **COMPAT-10** — optional subtree-hide (cascade parent-hide to children). Feature-sized, distinct from slug resolution.
51+
- **DEMO-01** — slug-resolution showcase demo (Playground). Demonstrates FIX-01/02/03 via a pre-seeded `maestro_config` whose keys differ in slug form from the rendered menu (host-move / `ver=` / `&` / UTM), against a busy menu. Prefer a lightweight fixture mu-plugin over heavy real plugins; optional WooCommerce-only opt-in blueprint for name recognition. Demo/marketing enhancement, not menu-handling code — its own small phase in a future milestone. See PROJECT.md backlog.
5152

5253
## Out of Scope
5354

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
In-place editing of the WordPress admin menu — rename items, reorder them, swap top-level icons, and hide items per role. Global configuration, no separate settings screen: the editor is toggled from the admin bar and operates on the menu itself.
1414

15-
**[Try it live in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Maestro/main/playground/blueprint-stable.json)** — boots a throwaway site with the plugin active, User Switching, and test users (editor / author / contributor / subscriber, password `password`) so you can try per-role visibility by switching users. This demo installs the **latest released version**. ([Development build (main)](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Maestro/main/playground/blueprint-hosted.json) also available.)
15+
**[Try it live in WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Maestro/main/playground/blueprint-stable.json)** — boots a throwaway site with the plugin active in edit mode, User Switching, and test users (editor / author / contributor / subscriber, password `password`) so you can try per-role visibility by switching users. This demo installs the **latest released version**. ([Development build (main)](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Maestro/main/playground/blueprint-hosted.json) also available.)
1616

1717
## Screenshots
1818

assets/maestro.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,11 +1264,20 @@
12641264
var firstItem = document.querySelector( '#adminmenu > li.menu-top.maestro-item' );
12651265
if ( firstItem ) {
12661266
firstItem.classList.add( 'maestro-firstrun-pulse' );
1267+
var clearPulse = function () {
1268+
firstItem.classList.remove( 'maestro-firstrun-pulse' );
1269+
};
12671270
// Motion case: remove the class once the one-shot animation completes.
12681271
firstItem.addEventListener( 'animationend', function onEnd() {
1269-
firstItem.classList.remove( 'maestro-firstrun-pulse' );
1272+
clearPulse();
12701273
firstItem.removeEventListener( 'animationend', onEnd );
12711274
} );
1275+
// Reduced-motion / missed-event fallback: under prefers-reduced-motion the
1276+
// CSS sets animation:none, so animationend NEVER fires — without this the
1277+
// attention outline would persist on the first menu item until the user
1278+
// happens to dismiss the cue (and re-appear every load, since the seen flag
1279+
// is only set on dismiss). Guarantee the one-shot cue is actually one-shot.
1280+
window.setTimeout( clearPulse, 1800 );
12721281
}
12731282

12741283
function dismiss() {

readme.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Rename, reorder, change icons, and hide WordPress admin menu items per user role
1717

1818
Instead of a separate settings screen, Maestro turns the admin menu into something you edit *in place* — right where it lives. Toggle **Edit Menu** from the admin bar, and the menu becomes editable. Click a menu item to rename it, hide it from selected user roles, or change its icon. Drag submenu items and whole menu groups to reorder them.
1919

20-
**Try Maestro right here.** Launch a disposable demo in [WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Maestro/main/playground/blueprint-hosted.json) — it boots a site with Maestro active, User Switching, and test users (editor, author, contributor, subscriber; password `password`) so you can try per-role visibility by switching to another user's account.
20+
**Try Maestro right here.** Launch a demo in [WordPress Playground](https://playground.wordpress.net/?blueprint-url=https://raw.githubusercontent.com/dknauss/Maestro/main/playground/blueprint-hosted.json) — it boots a throwaway site with the plugin active in edit mode, plus User Switching and test users (editor, author, contributor, subscriber; password `password`) so you can try per-role visibility by switching to another user's account.
2121

2222
= What you can do — as a site administrator =
2323

@@ -128,6 +128,7 @@ If Maestro saves you time or brings you or your clients the joy of a tidy admin
128128
= 1.3.0 =
129129
* Saved overrides now keep applying even when your site moves to a new host, when a plugin updates and changes a version number in its menu URL, when UTM tracking parameters drift on external-tool links, and when a taxonomy slug is stored with `&` encoding instead of `&` (or vice versa) — no manual re-save needed.
130130
* Edit-mode toolbar: the Exit and Reset All controls now use clearer, more consistent icons (Exit matches the admin-bar toggle).
131+
* Fix: the one-time first-run highlight on the first menu item is now reliably momentary — it no longer stays outlined for people who use the "reduce motion" accessibility setting.
131132

132133
= 1.2.0 =
133134
* Redesigned edit-mode toolbar: every control is now a compact icon button in one consistent system, with colour signalling meaning — green for editing/saved, amber for unsaved changes, red for Reset All. Fully accessible: each control keeps its name for screen readers and shows a tooltip on hover.

tests/e2e/firstrun.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
/**
4+
* BUG-09 regression: the first-run attention pulse on the first menu item must be
5+
* a true one-shot in ALL motion preferences.
6+
*
7+
* Under prefers-reduced-motion the pulse CSS sets `animation: none`, so the
8+
* `animationend` event that normally removes the `maestro-firstrun-pulse` class
9+
* never fires. Before the fix this left a permanent 2px solid outline on the
10+
* first top-level item — read by users as a stray dark band above the next menu
11+
* group — and it re-appeared on every load (the seen flag is only set on
12+
* explicit dismiss). A timed fallback must remove the class regardless.
13+
*/
14+
test( 'first-run pulse self-clears under reduced motion', async ( { page } ) => {
15+
await page.emulateMedia( { reducedMotion: 'reduce' } );
16+
await page.goto( '/wp-admin/index.php?maestro_edit=1' );
17+
18+
// Force first-run state so the cue + pulse are actually built, then reload.
19+
await page.evaluate( () => window.localStorage.removeItem( 'maestroFirstRunDone' ) );
20+
await page.reload();
21+
await page.waitForSelector( '#adminmenu li.maestro-item' );
22+
23+
// The pulse may appear briefly, but must clear itself within a couple seconds
24+
// even though animationend never fires under reduced motion.
25+
await expect
26+
.poll( () => page.locator( '#adminmenu .maestro-firstrun-pulse' ).count(), {
27+
timeout: 4000,
28+
} )
29+
.toBe( 0 );
30+
} );

0 commit comments

Comments
 (0)