=== Maestro: The Inline Admin Menu Editor ===
Contributors: dpknauss
Donate link: https://github.com/sponsors/dknauss
Tags: admin menu, admin menu editor, menu editor, hide menu items, menu icons
Requires at least: 6.4
Tested up to: 7.0
Stable tag: 1.1.1
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Rename, reorder, re-icon, and hide WordPress admin menu items per role — an inline admin menu editor you drive right on the menu itself.

== Description ==

**Maestro is an inline admin menu editor.** Instead of a separate settings
screen, it turns the WordPress 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 label to rename it, drag rows to reorder, swap a
top-level icon, or hide items from chosen roles.

**Try it first.** Launch a throwaway 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 users before you install anything.

= What you can do =

* **Rename** any top-level or submenu item — just click the label.
* **Reorder** items by dragging (top-level items among themselves, submenu items
  within their parent), or with the keyboard (`Alt`+`Arrow`).
* **Swap icons** on top-level items. The picker offers dashicons and bundled
  Bootstrap Icons with search, and accepts any of WordPress's four native icon
  forms (dashicon, "none", base64 image data-URI, or an image URL).
* **Hide** items from chosen roles — including administrators. Custom roles
  registered by other plugins
  ([User Role Editor](https://wordpress.org/plugins/user-role-editor/),
  [Members](https://wordpress.org/plugins/members/), etc.) appear automatically.
* **Reset** a single item to its WordPress default, or reset everything at once.

Changes are **global** — one configuration applies to everyone — and are stored
as a sparse delta layered over the menu WordPress builds on each load. Nothing
is rebuilt or duplicated, so a reset simply removes the delta and the original
menu returns.

= Important: visibility is cosmetic, not access control =

Hiding a menu item only declutters the menu. The underlying admin page still
loads for anyone who knows or types its URL, because a page's own registered
**capability** is the true lock. Maestro operates on the menu (presentation),
which is a different plane from authorization.

If you need to actually *prevent* access, pair Maestro with a capability manager:

* **[User Role Editor](https://wordpress.org/plugins/user-role-editor/)** — the
  simplest way to edit what a role can do.
* **[PublishPress Capabilities](https://wordpress.org/plugins/capability-manager-enhanced/)** —
  menu-aware; its Pro tier can block admin pages by URL.

The `maestro_capability` filter lets such a plugin hand editing rights to a
custom capability instead of the default `manage_options`.

= Accessibility and localization =

The editor is keyboard-operable end to end — select with `Enter`/`Space`,
reorder with `Alt`+`Arrow`, and every move and save is announced to screen
readers. Modified items carry a non-color indicator with screen-reader text, so
state never depends on color alone.

Maestro uses the `maestro-menu-editor` text domain and ships a translation
template plus starter language packs for Spanish (`es_ES`), German (`de_DE`),
Japanese (`ja`), French (`fr_FR`), Portuguese – Brazil (`pt_BR`), and Italian
(`it_IT`). WordPress.org language packs override and extend these; native-speaker
and WordPress Polyglots review is welcome.

== Installation ==

1. In your dashboard go to **Plugins → Add New**, search for "Maestro: The
   Inline Admin Menu Editor", and click **Install Now**, then **Activate**.
2. Or upload the plugin zip via **Plugins → Add New → Upload Plugin**, then
   activate it.
3. Or, manually: unzip into `wp-content/plugins/maestro-menu-editor` and
   activate from **Plugins**.
4. After activating, click **Edit Menu** in the admin bar to start editing the
   admin menu in place.

== Frequently Asked Questions ==

= Does hiding a menu item block access to that page? =

No — and this is important. Hiding an item is **cosmetic**: it removes the link
from the admin menu but does not stop anyone from reaching the page by typing or
bookmarking its URL. Real access is governed by each page's registered
capability. To actually block a page, use a capability manager such as
[User Role Editor](https://wordpress.org/plugins/user-role-editor/) or
[PublishPress Capabilities](https://wordpress.org/plugins/capability-manager-enhanced/).

= Do my changes affect everyone, or just me? =

Everyone. Maestro stores one global configuration that applies to all users; it
is not per-user. Per-role *visibility* lets you hide items from specific roles,
but the rename/reorder/icon changes themselves are global.

= Can I hide items from administrators too? =

Yes. Role visibility includes the administrator role, so you can declutter an
admin's menu — remembering that this is cosmetic, not a permission change.

= Does it work with custom roles from other plugins? =

Yes. Any role registered on the site — including custom roles from User Role
Editor, Members, and similar plugins — appears automatically in the visibility
control.

= Is the editor keyboard accessible? =

Yes. You can select, rename, reorder (`Alt`+`Arrow`), open the icon and
visibility controls, and reset items without a mouse. Saves and moves are
announced to screen readers.

= What happens when I deactivate or reset the plugin? =

The admin menu returns to exactly what WordPress and your active plugins
generate. Your customizations live in a single option as a sparse delta;
**Reset all** deletes that option, and deactivating the plugin stops it from
being applied.

= Can I move an item between a top-level position and a submenu? =

Not yet. Reparenting is deliberately deferred (see "Known limits" below).
Top-level items reorder among top-level items, and submenu items reorder within
their current parent.

== Screenshots ==

1. Editing the admin menu in place — the Posts item selected, with the shared controls panel (rename, icon, visibility, reset) open.
2. The icon picker: searchable Dashicons and bundled Bootstrap Icons tabs for swapping a top-level admin menu icon.
3. Per-role visibility — hiding an admin menu item from selected roles (a cosmetic declutter, not access control).
4. A renamed admin menu item, saved automatically by debounced autosave.

== Architecture (for developers) ==

* `Config` — reads/writes/sanitizes a single option (`maestro_config`) holding only
  the deltas. Reset = delete the option; the natural menu returns automatically.
* `Replay` — on a late `admin_menu` pass, applies rename/icon/visibility to the
  `$menu`/`$submenu` globals and reorders submenus. Top-level order uses the
  core `custom_menu_order` + `menu_order` filters. Resilient to missing slugs
  (orphans are skipped) and new items (appended at the end).
* `Rest` — `maestro/v1/config` (GET/POST/DELETE), capability-gated, `X-WP-Nonce`.
* The editor JS is driven by a localized model (with DOM ids), not DOM scraping,
  and diffs against captured pristine defaults so the stored config stays sparse.
* Localized editor labels are passed from PHP to JavaScript in `maestroData.i18n`;
  the runtime zip includes the bundled POT template and starter catalogs.

== Known limits / deferred to v2 ==

* **Reparenting** (moving an item between a top-level position and a submenu) is
  not included. Top-level items reorder among top-level items and submenu items
  reorder within their current parent. Reparenting needs hand-splicing of the
  globals plus `parent_file`/`submenu_file` highlighting fixes — a known
  minefield, parked deliberately.
* **Separators** are preserved in place but not yet add/move/delete-able; their
  generated slugs (`separator1`…) have no stable identity to key against.
* **Renaming** an item drops any core-appended count badge (e.g. pending
  comments) from that label, since the badge lives inside the title string.
* Submenu sort relies on items registering by the late `admin_menu` pass; a
  plugin that registers submenus on an unusually late hook may not be captured.

== Credits ==

Bundled [Bootstrap Icons](https://icons.getbootstrap.com/) are © The Bootstrap
Authors, licensed under the MIT License. They are recoloured to the WordPress
menu grey and embedded as data-URIs; see `bin/generate-bootstrap-icons.mjs`.

== Support This Plugin ==

If Maestro saves you time, you can support its ongoing maintenance through
[GitHub Sponsors](https://github.com/sponsors/dknauss).

== Changelog ==

= 1.1.1 =
* Editor: the selected item's name is now screen-reader-only — the visible
  breadcrumb duplicated the rename field and ate horizontal space, and the
  controls are self-explanatory. Screen-reader users still get the item /
  submenu context.
* Editor: shorter reset button labels — "Reset Item" and "Reset All".

= 1.1.0 =
* Keyboard reordering: select a menu item then press `Alt+ArrowUp` /
  `Alt+ArrowDown` to move it. Each move is announced to screen readers (politely
  for success, assertively when already at the boundary). No mouse required.
* Modified indicator: changed items show a non-color glyph (•) with screen-
  reader text "(modified)" in edit mode. The indicator refreshes live on every
  rename, icon change, visibility change, and reset.
* Discoverable per-item reset: the **Reset this item** button in the controls
  panel is now keyboard-reachable (Tab + Enter/Space) and is visually
  emphasised whenever the selected item has unsaved overrides.
* Solid bundled icons: the Bootstrap Icons set now uses solid (`*-fill`)
  variants, so it mixes naturally with WordPress's dashicons in the picker.
* Edit-mode polish: clearer toolbar grouping, a more scannable icon grid, and a
  dismissible first-run hint.
* Native save status: the saving / saved / error states now use WordPress
  dashicons (a spinner, a check, a warning) instead of emoji glyphs that some
  platforms recoloured or dropped; the idle state shows no icon.
* Fixes: the saved status no longer renders a double check mark; the rename
  field no longer shifts as the title length changes; toolbar controls wrap
  instead of overlapping on narrow screens.
* Listing: rewritten description and FAQ, plus a "Try it first" link to a live
  WordPress Playground demo.

= 1.0.0 =
* Initial release: rename, reorder, per-role visibility, reset.
* Icons: accepts all four native WordPress forms (dashicon, none, base64 image
  data-URI, image URL); picker bundles dashicons + curated Bootstrap Icons with
  search, keyboard accessibility, and mobile-sized touch targets.
* Editor: click-to-select with a shared panel, debounced single-flight autosave,
  and folded-mode neutralization.

== Upgrade Notice ==

= 1.1.1 =
Minor editor UI tidy: the item-name label is now screen-reader-only and the
reset buttons are "Reset Item" / "Reset All". No configuration changes.

= 1.1.0 =
Keyboard-accessible reordering, a live "modified" indicator, solid bundled
icons, native dashicon save-status, and responsive/edit-mode polish. No
configuration changes required.
