Extract admin UI into wp-admin-ui kit; consume from progress-planner#761
Extract admin UI into wp-admin-ui kit; consume from progress-planner#761
Conversation
Adds the extracted admin-ui kit as a composer dependency (vcs repo, dev-main) and wires a shadow admin page that boots AdminUI alongside the existing progress-planner admin page. Behind the PROGRESS_PLANNER_USE_ADMIN_UI_PKG constant — off by default, so production behavior is unchanged. - composer.json: require progressplanner/wp-admin-ui dev-main - progress-planner.php: conditionally load composer autoload + boot shadow page when the flag is defined-and-truthy - classes/admin/class-admin-ui-pkg-shadow.php: shadow page + smoke-test widget rendering <prpl-gauge> via the kit Verified: with flag off, PHP syntax + composer valid, no behavior change. With flag on, shadow page at ?page=progress-planner-adminui renders a gauge inside a proper widget wrapper, confirming the kit autoloads and works inside progress-planner's PHP environment. Phase 3 note: the shadow page sets host_assets_path to a non-existent dir because progress-planner's own asset file headers use qualified 'progress-planner/...' dep strings that the kit's enqueuer can't resolve yet. That gets fixed in Phase 3 when we set the kit's asset_prefix to 'progress-planner' — then legacy headers will round-trip cleanly.
Progress_Planner\Admin\Enqueue is now a thin adapter around the kit:
- enqueue_style() fully delegates to the kit enqueuer.
- enqueue_script() delegates non-vendor handles to the kit; vendor
scripts (particles-confetti, driver) keep their special handling
because their fixed path/version doesn't fit the kit's generic
{prefix}/{handle} resolution.
- Vendor handles are registered with the kit as externals with a lazy
resolver callback, so when another script declares them as deps, the
vendor file is wp_enqueue_script()'d on demand.
- Progress-planner-specific methods (localize_script() with its
per-handle switch, get_localized_strings(), get_badge_urls(),
maybe_empty_session_storage()) stay here — they're domain logic, not
asset mechanics.
- get_file_details() removed; the kit owns resolution now.
The kit's asset_prefix is 'progress-planner' so existing legacy headers
(Dependencies: progress-planner/foo) round-trip cleanly without needing
file edits.
Requires the kit's register_external() accepting a resolver callback
(progressplanner/wp-admin-ui@dev-main).
Adds Progress_Planner\UI\Branding::to_kit_branding() which returns a \ProgressPlanner\AdminUI\Branding populated with currently-resolved SaaS values (menu name, submenu name, admin menu icon SVG, logo HTML, and custom CSS). The SaaS-driven Progress_Planner\UI\Branding class keeps all its existing behavior — remote fetches, hostname sniffing, widget filtering — and this method is purely an output bridge. Kit code (which performs no remote calls) consumes the VO. The shadow page now uses to_kit_branding() instead of constructing its own Branding, exercising the bridge end-to-end.
Progress_Planner\Admin\Widgets\Widget now extends
ProgressPlanner\AdminUI\Widgets\Widget. Rendering mechanics (wrapper
div, CSS class naming, view loading) live in the kit; progress-planner-
specific additions stay here:
- range/frequency getters (bound to the existing <select> UI).
- legacy enqueue_styles/enqueue_scripts paths that use the classic
'progress-planner/page-widgets/{id}' handle convention.
Added Progress_Planner\Admin\Admin_UI_Instance — a lazy singleton
accessor for the kit's AdminUI instance. Boots with
register_page: false so the kit's PageRegistrar doesn't collide with
progress-planner's own Admin\Page class.
Return-type-compatible overrides in three concrete widgets
(Badge_Streak, Challenge, Todo) to match the kit's signatures.
Requires the kit's Config::$register_page flag
(progressplanner/wp-admin-ui@dev-main bump).
…I_PKG is on
When the flag is on:
- Admin_UI_Instance boots AdminUI with register_page=true, show_range_filter=true,
menu_slug='progress-planner' — kit's PageRegistrar owns the top-level menu.
- Admin\Page::add_page() short-circuits so we don't register a duplicate menu.
- Admin\Page::enqueue_assets() delegates to a new enqueue_widget_assets()
method that only enqueues widget-specific bits (tokens + layout + masonry
are the kit's responsibility now).
- Admin_UI_Pkg_Shadow::boot() registers progress-planner's widgets with the
kit and hooks legacy UI into the kit's filters/actions:
* {prefix}_admin_ui_menu_title_suffix → notification-count bubble.
* {prefix}_admin_ui_before_content → welcome/privacy gate.
* {prefix}_admin_ui_header_right → tour button + subscribe popover.
* {prefix}_admin_ui_after_widgets → overlay-close script, JS templates,
and the legacy progress_planner_admin_page_after_widgets action fires
as compat for third-party code.
With flag off: nothing routes through the kit's page flow; existing
Admin\Page behavior is unchanged.
Renamed views/admin-page.php → views/legacy-admin-page.php (same for -header)
so the kit's host-first view resolution finds the kit's versions for admin-
page.php while legacy-* stays available for the flag-off code path.
Also:
- Enqueue: pass an after_enqueue_script callback to the kit so
localize_script() fires for every transitively-enqueued script (fixes
prplL10nStrings / progressPlannerBadge / prplSuggestedTask not being
attached to deps resolved by the kit).
- Branding::to_kit_branding() now passes null for all colors so
progress-planner's variables-color.css wins for token values (requires
kit bump with nullable Branding colors).
Tagged v0.1.0 on the kit after the phase-1-through-5 integration was verified working in both flag states (PROGRESS_PLANNER_USE_ADMIN_UI_PKG on and off) with zero visual regression on the real admin page. Phase 6 (actually deleting duplicated CSS/JS from progress-planner's assets so the kit's files become the source of truth) is deferred to a follow-up branch — this one is the stabilization checkpoint.
- Rename Progress_Planner\Admin\Admin_UI_Pkg_Shadow → Admin_UI_Kit_Integration (and the file to match). The 'shadow' name was a Phase-2 artifact; post-Phase-5 this class is the integration layer between progress-planner and the kit when flag is on. - Bump progressplanner/wp-admin-ui to v0.1.1 for the proper cycle-safe dep resolution (processing vs enqueued two-set tracking), which fixed the prplInteractiveTaskFormListener undefined errors on the WP dashboard when multiple recommendation scripts share the interactive-task dep. Phase 3C (deleting duplicated CSS/JS from progress-planner/assets so host-first resolution falls through to the kit's copies) is abandoned for this round — byte-identical files at vendor/ URLs break rendering in the Local dev environment for reasons that need investigation. The kit's copies still ship inside vendor/, they're just not used unless a host plugin has no own copy.
Root-caused the earlier render regression: Progress_Planner\Admin\Enqueue
wrapped its own AssetEnqueuer with only a single host root and no
package fallback, so when legacy enqueue paths (flag-off) called
enqueue_style('progress-planner/variables-color') and the host file was
gone, resolve() returned null and wp_enqueue_style was never called.
Fix: give progress-planner's kit_enqueuer the same (host, package) root
list as the AdminUI's enqueuer uses. Deletions now fall through to the
kit's copies whether the flag is on or off.
With that landed, the Phase 3C/6 deletions are safe:
- assets/css/variables-color.css (identical to kit)
- assets/css/web-components/prpl-tooltip.css (identical)
- assets/css/web-components/prpl-install-plugin.css (identical)
- assets/js/web-components/prpl-{big-counter,chart-bar,chart-line,gauge-progress-controller,tooltip}.js
(identical behavior; kit's gauge-progress-controller drops the
gauge→controller→gauge legacy cycle dep, controller.js deps on
badge-progress-bar only.)
Kept in progress-planner's assets because the kit versions behave
differently or have domain coupling:
- prpl-gauge.js (host declares prpl-badge dep needed for host widgets)
- prpl-badge-progress-bar.js (same reason)
- prpl-install-plugin.js (kit strips the suggested-task coupling; host
still uses the old behavior)
- prpl-badge.js, prpl-interactive-task.js, prpl-task-*.js (progress-
planner-specific entirely)
- admin.css (host is a superset of the kit's layout-only version)
…e page The flag was the Phase-5 safety net for switching progress-planner to the extracted wp-admin-ui kit's page rendering. With the kit verified working in both flag states across all the Phase 1-6 commits, drop the toggle. Changes: - progress-planner.php: unconditional composer autoload + unconditional Admin_UI_Kit_Integration boot (was flag-gated). - Admin_UI_Instance: remove kit_renders_page(); boot kit with register_page=true always. - Admin_UI_Kit_Integration::boot(): remove the flag early-return. - Admin\Page: strip the legacy page ownership — no more add_page(), render_page(), enqueue_scripts(), enqueue_styles(), or get_notification_counter(). enqueue_assets() always runs the widget-only path (kit handles tokens + layout + masonry). Kept: get_widgets()/get_widget(), maybe_enqueue_focus_el_script(), remove_admin_notices(), clear_activity_scores_cache(), admin_footer(). - Deleted views/legacy-admin-page.php + views/legacy-admin-page-header.php (only the flag-off path used them).
|
Test on Playground |
Composer package changes
|
…CS warnings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace with direct enqueue of the base stylesheets (variables-color + admin) that the dashboard widgets need on the WP Dashboard screen. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The removed Page::enqueue_styles() also attached branding CSS overrides via wp_add_inline_style — restore that for WP Dashboard widgets. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The suggested-task template uses tooltip-actions classes, so the tooltip stylesheet is needed on the WP Dashboard. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The old progress_planner_admin_page_header_before action no longer fires since the kit owns the admin page header. Switch to the kit's equivalent progress-planner_admin_ui_header_before hook. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ilicfilip
left a comment
There was a problem hiding this comment.
Review: fixes pushed + items needing attention
Fixes pushed (5 commits)
-
PHPDoc + style fixes (
1db545a) — Added proper docblocks toAdmin_UI_Instance, removed double blank line inBranding::to_kit_branding(), fixed PHPCS param spacing inEnqueue. -
Dashboard widgets broken (
5afec8d,84eb430,2616438) —Page::enqueue_styles()was removed butDashboard_Widget_ScoreandDashboard_Widget_Todostill called it. Replaced with direct enqueue ofvariables-color,admin, branding inline CSS, andprpl-tooltip(needed by the suggested-task template). -
Playground header notice (
44c90aa) —progress_planner_admin_page_header_beforeaction no longer fires since the oldadmin-page-header.phpwas deleted. Updated Playground class to hook into the kit's equivalentprogress-planner_admin_ui_header_before.
Items needing attention
-
CI is fully red — All jobs fail at
composer installbecauseProgressPlanner/wp-admin-uiis a private repo and CI doesn't have credentials to clone it. You'll need to add a GitHub token (e.g.COMPOSER_AUTH_TOKENsecret) and configurecomposer config github-oauth.github.comin the workflows beforecomposer install. -
composer.lockplugin-api-version downgrade — Dropped from2.9.0to2.6.0, suggesting the lock was regenerated with an older Composer version. May cause issues if CI or other devs use Composer 2.9+. -
Recursive vendor path in kit — The CSS lint hook fails with
ENAMETOOLONGbecausewp-admin-ui/examples/minimal-plugin/contains a self-referencing vendor path. Worth addingexamples/to.gitattributes export-ignorein the kit repo.
Summary
Extracts the admin UI layer (page framework, asset enqueuer, widget base, web components, CSS tokens) of progress-planner into a standalone Composer package at
ProgressPlanner/wp-admin-ui(private, pinned atv0.1.1) and rewires progress-planner to consume the kit instead of shipping those bits directly.After this PR, the kit owns:
PageRegistrar).<prpl-gauge>/<prpl-tooltip>/chart/counter/progress-bar web components.variables-color.css) + layout-onlyadmin.css+grid-masonry.js.AssetEnqueuer(dep resolution, mtime versioning, external-handle callbacks).Progress-planner keeps all domain logic (task providers, badges, SaaS branding, privacy gate, tour, subscribe popover, JS templates, dashboard widgets). It integrates via
Admin_UI_Kit_Integrationwhich attaches the plugin's UI bits to the kit's{asset_prefix}_admin_ui_*hooks.Why
Reusable admin look-and-feel across other plugins. Everything kit-side is now extractable by any consumer via a
vcsComposer repo entry.Phases (each is its own commit for review)
Admin\Enqueuethrough the kit'sAssetEnqueuer.Progress_Planner\UI\Branding::to_kit_branding()bridge.Admin\Widgets\Widgetextends the kit's base.Test plan
composer installpicks upprogressplanner/wp-admin-ui v0.1.1./wp-admin/admin.php?page=progress-plannerrenders with no JS console errors.prplInteractiveTaskFormListenererrors.🤖 Generated with Claude Code