Skip to content

Admin UI on @plugpress/ui (migration → v0.8.2) + header refresh + hygiene - #37

Merged
ifahimreza merged 9 commits into
mainfrom
feat/admin-header
Jul 11, 2026
Merged

Admin UI on @plugpress/ui (migration → v0.8.2) + header refresh + hygiene#37
ifahimreza merged 9 commits into
mainfrom
feat/admin-header

Conversation

@ifahimreza

Copy link
Copy Markdown
Contributor

Brings the Saddle admin UI onto @plugpress/ui end-to-end, adds the header/Home refresh from #35, fixes two design-system crashes surfaced during live testing, and lands the #8 free-side hygiene.

What's in here

UI migration + refresh

  • Full migration of every admin screen to @plugpress/ui (TopBar, Onboarding, Permissions, Home, Connect, ConnectionHealth, ConnectWizard, Guidance/Memory, Activity); ui.jsx compat shim deleted; style.scss cut ~1,260 lines; brand mark single-sourced.
  • Admin UI: full-width header + Home stat tiles + a11y (on @plugpress/ui v0.6.0) #35 — full-bleed header, Home StatCard/StatGrid tiles (Connected apps · Access level · Actions logged), SkipLink#pp-main a11y. Dropped the redundant "%d apps" badge.

Design-system crash fixes (released upstream, pinned here)

  • @plugpress/ui v0.8.1Button asChild threw React.Children.only on every use (component passed a 2-entry [spinner, children] array to Slot). Saddle also switched TopBar's Docs/Rate links to Button href= (cleaner idiom).
  • @plugpress/ui v0.8.2Dialog "no accessible name" dev-warning fired on closed dialogs (ConfirmProvider's idle dialog), noisy on every load; now gated on open.
  • Pin: v0.8.2.

#8 hygiene (free side)

  • Deduped four identical log() wrappers (block/core-content/memory/site, 17 call sites) into one Saddle_Log::record_action() helper — maintainability only, no behavior change.
  • Confirmed the ConnectWizard --scope user fix ships in the build.
  • Confirmed connect round-trip + revoke-invalidation are already automated (connect-test.php, 22 tests).

Verification

  • JS builds clean; admin/build/index.asset.php externals unchanged; no google-fonts in built CSS.
  • PHP: relevant PHPUnit suites green (79 + 22 + connect/site/blocks/memory); phpcs clean on changed files.
  • Live: React crash and the Dialog warning both resolved after reload (hash 14af28ac).

Closes #35. #8 handled (closed separately; optional 401-legibility tail split to #36).

ifahimreza and others added 9 commits July 10, 2026 20:21
Retire the @wordpress/components compat shim (admin/src/ui.jsx) and compose
every admin screen directly on @plugpress/ui design-system components; bump
the pin v0.2.0 → v0.6.0.

- Screens on DS components: TopBar (Tabs/StatusDot), Onboarding + Permissions
  (CardRadioGroup, ApplyBar, toast), Home (Hero/CalloutCard/CardGrid/RowList),
  Connect tab (PageHeader/EmptyState/RowList/useConfirm/Snippet), ConnectionHealth
  (CodeBlock/CalloutCard), ConnectWizard (Steps/CodeBlock/Snippet/LiveIndicator/
  useCopy — everCopied gate + back-out revoke preserved), Guidance/Memory
  (Card/RowList/Switch/Field/useConfirm/toast), Activity (FilterTabs/EmptyState/Badge).
- Mount TooltipProvider/ConfirmProvider/Toaster once at the app root.
- Delete admin/src/ui.jsx shim and dead theme icons; drop wp-components from the
  PHP fallback deps + stylesheet deps (no @wordpress/components left anywhere).
- style.scss 2,203 → 1,109 lines (kept: token aliases, setup shell, permissions
  lanes/chips, activity timeline, wizard flourishes).
- Single-source the brand mark: assets/brand/mark.svg is the only copy; React
  <BrandMark/> (SVGR) and the PHP admin-menu icon both read it.
- Reconcile CLAUDE.md + admin/DESIGN-ALIGNMENT.md to name @plugpress/ui as the kit.

v0.6.0 verified non-breaking for Saddle (all 34 imports resolve; flat Tabs/
FilterTabs/Steps + every pp-* class Saddle targets survive; adds a WCAG 2.2 AA
pass). Verified: build clean, react/wp-* externalized, no google-fonts; 300
PHPUnit tests green; wp-playground smoke test (app renders, DS + product
stylesheets ordered, pp-scope on body, monochrome accent wins, menu icon reads
the single-source SVG).

Follow-up: #35 (full-width header + Home stat tiles + a11y).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7RDwBHyNgrKKcDKYeuVLk
The fleet:agents tooling bumped the pin to v0.6.1; package.json already carried
it but node_modules/lockfile lagged at v0.6.0. Reinstalled at v0.6.1 and rebuilt
— admin/build is byte-identical (v0.6.1 changed only README, a consumer-agent
guide, and fleet tooling; zero component/CSS/JS changes), so nothing visual
differs from the tested v0.6.0 build.

- package-lock.json: v0.6.0 → v0.6.1 (now consistent with package.json).
- AGENTS.md: fleet:agents-managed pointer to the @plugpress/ui consumer guide
  (matches waggle/knovia).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7RDwBHyNgrKKcDKYeuVLk
…nt Home hero

Header (TopBar) becomes a full-bleed product bar: brand logo + name + version
tag on the left; the safety status pill + Pause, then Docs and ★ Rate links on
the right; section nav below. Reads version/docsUrl/rateUrl from saddleData
(new, filterable PHP fields). Layout: the width constraint moves off .saddle-app
onto .saddle-top__inner + a new centered .saddle-content (id=pp-main) so the bar
spans edge-to-edge, sticky under the admin bar.

Home: remove the "Right now" hero — it restated the access level the header now
shows. Home leads with the connect callout + cards; unused props cleaned up.

Also bumps @plugpress/ui to v0.6.2, which fixes the Activity filter tabs: the DS
FilterTabs never reset the native <button> chrome, so wp-admin borders bled
through into ugly bordered pills (fixed upstream to match SegmentedControl/Tabs).

Verified: 300 tests green; build clean, react/wp-* externalized, no google-fonts;
FilterTabs reset present in the built CSS; saddleData serves version/docs/rate
end-to-end in wp-playground; app mounts with no fatal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W7RDwBHyNgrKKcDKYeuVLk
Complete the remaining scope of #35 (the full-bleed header and #pp-main
anchor were already shipped on this branch):

- Home: three DS StatCard tiles in a StatGrid — Connected apps, Access
  level, Actions logged — sourced from data Home already loads. Drop the
  now-redundant "%d apps" header badge (and its unused sprintf/_n).
- App: DS SkipLink -> #pp-main as the first focusable element (a11y).
- SCSS: .saddle-stats outer spacing only; StatGrid owns its layout.
- Resync @plugpress/ui 0.6.2 -> v0.8.0 (pin was already bumped but the
  install was never re-run) and rebuild. Externals unchanged, no
  google-fonts in built CSS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v0.8.0 newly implements Button `asChild` via Slot, whose React.Children.only
rejects the `children: [loading && spinner, children]` array the Button always
builds — so any `Button asChild` throws "expected to receive a single React
element child" at render. Our TopBar Docs/Rate links used that path.

Drop asChild + the inner <a>; pass `href` directly so Button renders an <a>
itself (Comp = href ? 'a' : 'button'). Same markup and classes, no Slot.

Upstream: the DS Button asChild path is broken for every consumer on v0.8.0 —
needs a separate fix in plugpress-ui.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The block/core-content/memory/site ability groups each carried an identical
private static log() wrapper around Saddle_Log::record(). Replace all four with
one shared Saddle_Log::record_action( $action, $target, $summary ) helper (17
call sites). Saddle_Log is required unconditionally in saddle.php, so the
per-wrapper class_exists() guard was dead defensiveness and is dropped.

Maintainability only — no behavior change. Relevant suites green (79 tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consume the upstream fix for the Button asChild → Slot Children.only crash
(plugpress-ui a303a8f / v0.8.1). Saddle's TopBar already sidesteps it by using
`Button href=…`; this keeps the DS itself sound as belt-and-suspenders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Picks up the DS fix for the "Dialog has no accessible name" warning that fired
on ConfirmProvider's idle (closed) dialog on every admin load. Console is clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ifahimreza
ifahimreza merged commit c8c5cdb into main Jul 11, 2026
0 of 4 checks passed
@ifahimreza
ifahimreza deleted the feat/admin-header branch August 20, 2026 07:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admin UI: full-width header + Home stat tiles + a11y (on @plugpress/ui v0.6.0)

1 participant