Skip to content

Commit c8c5cdb

Browse files
ifahimrezaclaude
andauthored
Admin UI on @plugpress/ui (migration → v0.8.2) + header refresh + hygiene (#37)
* feat: migrate admin UI to @plugpress/ui v0.6.0 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 * chore: align @plugpress/ui to v0.6.1 (lockfile + fleet:agents guide) 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 * feat: real app header (logo, version, docs, rate, nav) + drop redundant 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 * Admin UI: Home stat tiles + SkipLink, resync @plugpress/ui v0.8.0 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> * Fix TopBar crash on @plugpress/ui v0.8.0 (Button asChild → Slot) 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> * #8 free L1: dedup four log() wrappers into Saddle_Log::record_action() 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> * Bump @plugpress/ui pin v0.8.0 → v0.8.1 (Button asChild fix) 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> * Bump @plugpress/ui pin v0.8.1 → v0.8.2 (Dialog a11y-name fix) 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> * docs: STATUS — 2026-07-11 UI refresh + DS crash fixes + #8, PR #37 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 1fc6710 commit c8c5cdb

33 files changed

Lines changed: 1557 additions & 2841 deletions

AGENTS.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# saddle
2+
3+
<!-- BEGIN @plugpress/ui (managed by fleet:agents) -->
4+
## @plugpress/ui
5+
6+
This plugin's admin UI is built on the PlugPress design system. Before building or editing any
7+
admin UI, read the usage guide shipped with the package:
8+
9+
node_modules/@plugpress/ui/docs/consumer-agent-guide.md
10+
11+
It covers setup, the design rules you must follow, the component inventory, and why UI changes
12+
don't appear until the pinned tag is bumped and the plugin is rebuilt.
13+
<!-- END @plugpress/ui -->

CLAUDE.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,13 @@ tests/ — PHPUnit integration suite (SQLite-backed, real
9393
tool — write them like documentation, not code comments.
9494
- No `eval()`, `proc_open`, `shell_exec`, `exec()` anywhere. Grep for these four
9595
before every release.
96-
- React: `@wordpress/components` only — no separate UI kit, no Tailwind, until
97-
`DESIGN-ALIGNMENT.md` says otherwise.
96+
- React UI: **`@plugpress/ui`** (github tag pin in package.json) is the UI kit —
97+
import primitives directly from `@plugpress/ui`. No `@wordpress/components`,
98+
no Tailwind, no second kit. Product-specific pieces (BrandMark, LevelIcon,
99+
AppLogo, the Permissions lanes/chips, the activity timeline) stay in-plugin,
100+
styled on `--pp-*` tokens. Light-only — no theme toggles. The brand mark is
101+
single-sourced from `assets/brand/mark.svg` (React SVGR import + PHP menu
102+
icon read the same file). See `admin/DESIGN-ALIGNMENT.md`.
98103

99104
## Testing checklist before any release
100105

STATUS.md

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,28 @@
44
**Board:** [PlugPress HQ](https://github.com/orgs/plugpressco/projects/3)
55

66
## Last session
7-
2026-07-10 — **The Closed-Loop Quality Engine shipped, free half complete** (epic [#22](https://github.com/plugpressco/saddle/issues/22), PRs #28#32, suite 244 → **300 green**):
8-
- **F1** `Saddle_Lint_Style_Accessor` companion interface (additive — older accessors keep working) + Gutenberg impl (#23/PR #28).
9-
- **F5** a11y rules: text-contrast (ancestor-walk effective bg, WCAG AA 4.5/3.0 thresholds), missing-alt-text, heading-order — all feature-detect the companion and skip silently without it (#27/PR #29).
10-
- **F2** Agent Eyes: `saddle/render-node` — effective persisted styles (one resolver shared with lint) + capped/sanitized HTML; whole-page = bounded section outline. New `saddle_render_accessor` filter (#24/PR #30).
11-
- **F3** preview transport: `saddle/get-preview-url` — HMAC (post-bound, 5-min TTL, rotating secret with grace), served via the public-preview posts_results flip, noindex; the agent's own client does the screenshotting, nothing leaves the install (#25/PR #31).
12-
- **F4** `saddle/verify-page` — structural + echo (silently-ignored attrs) + lint over freshly re-read state, deduped/ranked/capped findings at real addresses, deterministic 0–100 score. Builders plug in via `saddle_verify_builder_findings` (#26/PR #32).
13-
- The Pro half (Divi driver, quality judgments, brief, context discipline, builder memory, skill) shipped the same day — see `saddle-pro/STATUS.md`.
14-
- Old-backlog #7 (render preview) closed as delivered by this scope.
7+
2026-07-11 — **Admin UI refresh + two DS crash fixes + #8 hygiene → PR [#37](https://github.com/plugpressco/saddle/pull/37)** (branch `feat/admin-header`, base main):
8+
- **[#35](https://github.com/plugpressco/saddle/issues/35) shipped** — full-bleed header was already in place; added Home `StatCard`/`StatGrid` tiles (Connected apps · Access level · Actions logged), `SkipLink``#pp-main`, dropped the redundant "%d apps" badge. Resynced the stale `@plugpress/ui` (node_modules was 0.6.2 vs the v0.8.0 pin).
9+
- **Two `@plugpress/ui` bugs found via live testing, fixed at root + released:** **v0.8.1**`Button asChild` threw `React.Children.only` on every use (passed a 2-entry `[spinner, children]` array to `Slot`); **v0.8.2**`Dialog` "no accessible name" warning fired on *closed* dialogs (ConfirmProvider's idle dialog), now gated on `open`. Both tagged/pushed on `plugpressco/plugpress-ui` (manual release, not `fleet release`, to avoid repinning the whole fleet). Saddle also switched TopBar Docs/Rate to `Button href=`; pin now **v0.8.2**.
10+
- **[#8](https://github.com/plugpressco/saddle/issues/8) closed** — deduped the four `log()` wrappers into `Saddle_Log::record_action()`; confirmed `--scope user` fix ships + connect/revoke tests already automated (22 green). Optional 401-legibility tail split to **[#36](https://github.com/plugpressco/saddle/issues/36)**.
11+
- Note: an unrelated in-progress change to `includes/class-saddle-mcp.php` (MCP inputSchema `properties: []``{}` normalization) sits uncommitted in the working tree — NOT part of PR #37.
12+
13+
2026-07-10 (later session) — **Admin UI fully migrated to @plugpress/ui v0.6.0** (on top of v0.9.0):
14+
- Pin bumped v0.2.0 → v0.6.0 (v0.6.0 verified non-breaking for Saddle: all 34 imports resolve, flat Tabs/FilterTabs/Steps + all `pp-*` classes survive; adds a WCAG 2.2 AA pass); `TooltipProvider`/`ConfirmProvider`/`Toaster` mounted once in App.jsx.
15+
- Every screen rewritten on DS components: TopBar (Tabs/StatusDot), Onboarding + Permissions (CardRadioGroup/SelectableCard, ApplyBar, toast), Home (Hero/CalloutCard/CardGrid/RowList), Connect tab (PageHeader/EmptyState/RowList/useConfirm/Snippet/Badge), 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).
16+
- `admin/src/ui.jsx` compat shim **deleted**; zero `@wordpress/components` usage (PHP fallback deps + stylesheet deps updated to match); dead theme icons removed.
17+
- `style.scss` 2,203 → **1,109 lines** (kept: token aliases, setup shell, lanes/chips, activity timeline, wizard flourishes, `.saddle-doc`).
18+
- **Brand mark single-sourced**: `assets/brand/mark.svg` is the only copy — React `<BrandMark/>` (SVGR) and the PHP menu icon (file read + recolor, with fallback) both consume it.
19+
- Docs reconciled: CLAUDE.md convention now names @plugpress/ui; DESIGN-ALIGNMENT.md re-decided (2026-07-10) — monochrome stands via the saddle accent, light-only.
20+
- Earlier same day: the Closed-Loop Quality Engine free half (epic #22, PRs #28#32, 300 green) — see git history.
1521

1622
## Next up
17-
- **Live divi-dev round-trip** (the epic's last gate): build a seeded-bad page → `verify-page` flags at correct addresses → fix → score rises; screenshot a minted preview URL in Claude Code; confirm effective styles against real Divi 5.8. Then close #22.
18-
- Consider a free minor release (the scope note says: free ships minor, Pro's min-free constant bumps — the constant bump is still pending in Pro).
23+
- **Review + merge PR [#37](https://github.com/plugpressco/saddle/pull/37)** (admin UI migration + refresh + crash fixes + hygiene). Manual click-through recommended: onboarding → wizard end-to-end (copy gate, back-out revoke, live listen), Permissions ApplyBar save/cancel/partial-fail, Guidance/Memory confirms + toasts, Activity filters/paging, ForeignNotices, keyboard-only + reduced-motion. Console should be clean post-reload (hash `14af28ac`).
24+
- **Decide on `includes/class-saddle-mcp.php`** — the uncommitted inputSchema normalization; commit it on its own (small PR) or discard.
25+
- **Live divi-dev round-trip** (epic #22's last gate): seeded-bad page → `verify-page` flags at correct addresses → fix → score rises; then close #22.
26+
- **Next backlog issue** (post-#8): [#5](https://github.com/plugpressco/saddle/issues/5) design-system unify (triage vs shipped brief/bundle first) or saddle-pro [#2](https://github.com/plugpressco/saddle-pro/issues/2) CF7.
27+
- Consider a free minor release (0.10.0) bundling the UI migration; Pro's min-free constant bump to match is still pending in Pro.
1928
- CI PHPUnit still red on GitHub Actions (no WP core in the runner) — fix as its own PR so future PRs get a real green.
2029

2130
## Blockers / open questions
22-
- Old work tickets #4#6, #8 remain from the previous scope — #5 (design-system unify) partially overlaps the shipped brief/bundle; triage them against the new scope when convenient.
31+
- Old work tickets #4#6 remain from the previous scope — #5 (design-system unify) partially overlaps the shipped brief/bundle; triage against the new scope when convenient. (#8 closed 2026-07-11.)

admin/DESIGN-ALIGNMENT.md

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,48 @@
11
# Saddle — Design Alignment
22

3-
> **DECIDED (2026-07-04, Fahim):** the monochrome identity is now intentional,
4-
> not a placeholder. Saddle keeps its own near-black/white, OpenAI/Apple-register
5-
> look — one restrained accent reserved for status/safety — with light AND dark
6-
> themes driven by the `s-palette-*` mixins in `style.scss`. The earlier
7-
> "align to inbees/outbees" directive below is SUPERSEDED; kept for history.
8-
> The brand mark is the stirrup-arch SVG (`<BrandMark />` in `icons.jsx`,
9-
> mirrored as the admin-menu icon in `class-saddle-settings.php`) — keep the
10-
> two paths in sync. Don't re-litigate this in future sessions.
11-
12-
## The former rule (superseded)
13-
14-
Do **not** invent a visual design from memory or taste. Saddle has to read as
15-
"the same workspace" as the rest of the PlugPress portfolio (inbees/outbees).
16-
That means pulling real values, not approximating them.
17-
18-
## Before you touch styles, gather the real reference
19-
20-
1. **Get the real inbees/outbees source.** Find the actual plugin admin code in
21-
the PlugPress monorepo (or the installed plugins). Do not work from
22-
screenshots or memory.
23-
2. **Extract real tokens, don't guess:**
24-
- Color palette (primary, surface, border, text, success/warning/error).
25-
- Font family and the type scale (sizes, weights, line-heights).
26-
- Spacing scale and border-radius conventions.
27-
- Any logo / icon assets and how they're sized.
28-
3. **Check for a shared component package.** If inbees/outbees pull from a shared
29-
PlugPress design-system package (React components or a token file), Saddle
30-
should consume that same package rather than re-implementing it. Re-using it
31-
is the whole point of "same workspace."
3+
> **DECIDED (2026-07-10, Fahim):** the admin UI is fully migrated to
4+
> **`@plugpress/ui` v0.3.0** — the shared PlugPress design system — which is
5+
> exactly the "shared component package" outcome the original research called
6+
> for. Import primitives directly from `@plugpress/ui`; the old
7+
> `admin/src/ui.jsx` compat shim is deleted. The system is **light-only**
8+
> (dark mode was removed from the DS in v0.2.0 — the dark-theme and
9+
> `s-palette-*` mentions below are historical). The 2026-07-04 monochrome
10+
> identity **stands**, now expressed through `tokens/accents/saddle.css`
11+
> (a fully monochrome accent) on top of the shared `--pp-*` tokens;
12+
> `style.scss` keeps only product-specific pieces (setup shell, permissions
13+
> lanes/chips, activity timeline, wizard flourishes) aliased to those tokens.
14+
> The brand mark is **single-sourced** from `assets/brand/mark.svg` — React's
15+
> `<BrandMark />` (SVGR import) and the PHP admin-menu icon
16+
> (`class-saddle-settings.php`, `file_get_contents` + recolor) both read that
17+
> one file; edit the SVG once to rebrand every surface.
18+
> Don't re-litigate any of this in future sessions.
3219
3320
## Constraints that still apply
3421

35-
- `@wordpress/components` only for UI primitives (see CLAUDE.md). No Tailwind,
36-
no styled-components, no separate UI kit — unless this research concludes a
37-
shared PlugPress package is the established pattern and overrides that.
22+
- UI primitives come from `@plugpress/ui` only — no `@wordpress/components`,
23+
no Tailwind, no styled-components, no second UI kit.
3824
- The Settings page must remain a single mounted React root (`#saddle-root`).
39-
- Don't regress accessibility: keep `@wordpress/components` semantics (labels,
40-
focus states) intact when restyling.
25+
- Don't regress accessibility: labels, focus rings, `role`/`aria-*` semantics,
26+
and `prefers-reduced-motion` support must survive any restyling.
27+
- Light-only: never add a theme toggle.
28+
- Portaled DS overlays (dialogs, dropdowns, toasts) read tokens from the
29+
`pp-scope` class on `<body>` (added via `admin_body_class`) — keep it.
30+
- Stylesheet order: the DS bundle (`index.css` → handle `saddle-admin-ds`)
31+
loads before Saddle's own `style-index.css` so product rules win.
32+
33+
---
4134

42-
## Done when
35+
## History
4336

44-
- `admin/src/style.scss` is built from real reference material (tokens traceable
45-
to inbees/outbees source, not invented).
46-
- A real Saddle icon replaces the placeholder `dashicons-rest-api` menu icon.
47-
- Side by side with inbees/outbees, the Saddle settings page is recognizably the
48-
same product family.
37+
> **DECIDED (2026-07-04, Fahim):** the monochrome identity is intentional,
38+
> not a placeholder. Saddle keeps its own near-black/white, OpenAI/Apple-register
39+
> look — one restrained accent reserved for status/safety. The earlier
40+
> "align to inbees/outbees" directive below is SUPERSEDED; kept for history.
41+
42+
### The former rule (superseded)
43+
44+
Do **not** invent a visual design from memory or taste. Saddle has to read as
45+
"the same workspace" as the rest of the PlugPress portfolio (inbees/outbees).
46+
That means pulling real values, not approximating them — and if a shared
47+
PlugPress design-system package exists, consume it rather than re-implementing
48+
it. (That package now exists: `@plugpress/ui`. It happened.)

admin/build/index-rtl.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

admin/build/index.asset.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-element', 'wp-i18n'), 'version' => 'fb668179e4dd58c480c4');
1+
<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-element', 'wp-i18n'), 'version' => '14af28acb07e0cb454e5');

admin/build/index.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

admin/build/index.js

Lines changed: 23 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

admin/build/style-index-rtl.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

admin/build/style-index.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)