Skip to content

Rebuild admin UI with React + Tailwind CSS v4 + shadcn/ui - #187

Merged
bordoni merged 24 commits into
mainfrom
feature/better-code-structure
Oct 17, 2026
Merged

bordoni merged 24 commits into
mainfrom
feature/better-code-structure

Conversation

@bordoni

@bordoni bordoni commented Mar 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Replace jQuery/Select2/PHP template admin UI with React 18 + Tailwind CSS v4 + shadcn/ui component architecture
  • Migrate all 6 admin pages (Settings, Terms, Users, Comments, Attachments, Posts) to lazy-loaded React roots backed by the existing REST API
  • Refactor PHP: unify container helpers in Factory classes, convert Ajax.php to instance methods, add DI-friendly Plugin methods, deprecate Field.php
  • Set up build pipeline with Bun, @tailwindcss/postcss, and fp: class prefix for CSS isolation from WordPress admin
  • Add 42 Jest tests (components, hooks, pages) and 11 WPUnit PHP tests for asset registration and page config

Latest changes

  • Replaced CSS #fakerpress-react-root specificity with zero-specificity :where([data-fp-root]) attribute scoping so WordPress admin form styles are cleanly overridden without !important
  • Removed ~433 lines of legacy Select2/jQuery .__fakerpress styles from admin.pcss
  • Simplified DateRangeField to a single value/onChange prop pair; fixed default dates being initialised as empty strings
  • Added tooltips to all form fields on the Attachments page
  • Tuned button and input sizes down one step for tighter WP admin fit
  • Set data-fp-root on document.body in JS and on template root divs in PHP so resets apply globally

Test plan

  • Run bun install && bun run build — verify build/admin.js, build/admin.css, and build/admin.asset.php are produced
  • Run bun run test — verify all 42 Jest tests pass
  • Run composer test:wpunit — verify all WPUnit tests pass (existing + 11 new)
  • Activate plugin in WordPress, visit each FakerPress admin page and verify React UI renders
  • Generate items from each page (Terms, Users, Comments, Attachments, Posts) via the Generate button
  • Test AJAX search fields (Author, Parent post, Term search) in BudugboxMulti components
  • Test date range presets and custom date pickers
  • Test Meta Field Rules add/remove and type switching
  • Verify Settings page erase confirmation dialog works
  • Confirm WordPress admin form elements (inputs, selects, buttons) retain native WP styles outside FakerPress panels

bordoni added 24 commits March 3, 2026 00:50
Replace the jQuery/Select2/PHP template admin interface with a modern
React component architecture. Each admin page renders as a separate
React root mounted on #fakerpress-react-root, using lazy-loaded page
components, React Hook Form for state, and the existing REST API for
data generation.

PHP refactoring:
- Unify container usage in Factory classes with helper functions
- Convert Ajax.php static methods to instance methods
- Add DI-friendly instance methods to Plugin.php
- Mark Field.php as @deprecated
- Add wp_localize_script page config bridge to all View classes

Build pipeline:
- Switch from npm to Bun, add React 18, Tailwind v4, shadcn/ui
- Configure webpack with @tailwindcss/postcss for packages/
- Register React bundle in Assets.php with conditional loading
- Set up Jest with jsdom, @testing-library/react, WordPress mocks

React components (22 shadcn/ui + 9 custom):
- Form: RangeInput, BudugboxMulti, DateRangeField, MetaFieldRules,
  TaxonomyFieldRules, GenerateButton, FormField
- Layout: PageLayout, AdminNotice
- Hooks: usePageConfig, useGenerateModule (with batching),
  useAsyncSearch (debounced AJAX)

Pages migrated: Settings, Terms, Users, Comments, Attachments, Posts

Tests: 42 Jest tests (components, hooks, pages) + 11 WPUnit tests
- Delete .nvmrc (no longer needed with Bun)
- Update AGENTS.md: prerequisites table, JS/CSS section heading, and all npm run commands → bun run
- Update CI js-build job: setup-node+npm ci → oven-sh/setup-bun+bun install/run
- Replace @import "tailwindcss" with partial imports (theme + utilities)
  to skip preflight and prevent global reset leaking into WP admin
- Add minimal scoped reset in @layer base targeting #fakerpress-react-root
- Add StripTailwindLayerHacksPlugin webpack plugin to remove Tailwind v4's
  :not(#\#) cascade-compatibility shims from compiled CSS assets
- Add postcss.config.js to route package CSS through @tailwindcss/postcss
- Document Tailwind/WP admin pitfalls in CLAUDE.md (formerly AGENTS.md)
- Fix all Tailwind classes from `fp-*` dash notation to `fp:*` colon notation
- Fix variant ordering: `fp:hover:`, `fp:last:`, `fp:sm:` (prefix always first)
- Document the correct `fp:` colon prefix rule in AGENTS.md
- Add scoped CSS variables and base styles to globals.css
- Add StripTailwindLayerHacksPlugin and minor webpack config tweaks

Tailwind v4 `prefix(fp)` generates `.fp\:flex` selectors — the dash form
`fp-flex` matches nothing and styles silently fail.
- Add @config directive to globals.css
- Switch box-sizing reset to :where(#fakerpress-react-root) for lower specificity
- Add :where([data-fp-root]) resets for all WP admin form element overrides
- Update color tokens to WP admin blue palette
- Remove legacy .__fakerpress block from admin.pcss (~433 lines)
- Add data-fp-root attribute to all PHP template root divs
- Set data-fp-root on document.body so CSS resets apply to all WP form elements
- Simplify DateRangeField to value/onChange API; export getPresetRange helper
- Initialise date default values with computed preset dates (not empty strings)
- Add tooltip props to all FormField instances on Attachments page
- Reduce button/input sizes one step for WP admin density (h-9→h-8, etc.)
- Add build:dev script to package.json
… reset

- Add @csstools/postcss-is-pseudo-class with onComplexSelector: 'ignore' to postcss.config.js
- Patch postcss-preset-env in .pcss webpack pipeline to also suppress warning
- Move CSS vars into @layer fp-base for internal cascade organization
- Promote WP admin resets out of @layer base (unlayered beats WP unlayered via source order)
- Add missing resets for headings, links, lists, and paragraphs to block WP admin bleed
…onents

- ReactAssetTest: register React bundle on an active admin page before asserting
- jest: ignore the dev/ Bun sub-project so its bun:test files don't run under Jest
- date-range-field/Budugbox-multi/meta-field-rules: update stale tests to the
  current component APIs (value/onChange, aria-labelled remove controls, inputs)
Make the X icon smaller (size-2.5) and turn the remove wrapper into a
centered inline-flex square so the rounded hover background aligns to the
badge instead of hugging the icon's text box.
…ound

Add a transparent base border to dropdown options and apply a visible
border plus accent background on hover and keyboard highlight so the
active option stands out clearly.
- cn(): configure tailwind-merge with the fp: prefix so className overrides
  (radius, border, etc.) actually win over component base classes instead of
  being silently dropped
- multi-select badges: give selected items a visible border and softer
  rectangular corners (rounded-md) instead of full pills
- switch: replace the transparent border with a visible foreground/20 border
- Migrate taxonomy term search from AJAX to REST (/terms/search)
- Add per-post-type default meta (_thumbnail_id) via the fakerpress.posts.default_meta filter
- Pre-fill and non-destructively merge default meta on post type change
- Guard Meta::generate() so under-configured meta types skip instead of fataling
- Restyle Taxonomy/Meta Field Rules from box to header + divider
- Move "Add Rule" buttons to the right
- Document that JS/CSS changes require recompiling
- Add attachment meta config panel (Stored Data id/url + Providers)
- Add a per-rule Weight field to every meta type
- Pre-configure default _thumbnail_id (store=id, providers, weight 75) so it
  renders complete and generates a featured image
- Fix meta type to backend mapping: number -> numbers, drop unsupported date,
  reshape ranged configs to positional [min,max] arrays, add config panels for
  wp_query / person / geo / company
- Enforce canonical config key order in transform so positional array_values()
  maps correctly regardless of UI interaction order
- Fix taxonomy mapping: emit the 'taxonomy' key (not 'taxonomy_rules') and a
  'qty' range (not 'quantity') so terms are actually applied; 'rate' already
  covers the old taxonomy 'weight' concept
- Add RuleCard/RuleField (components/form/rule-card.tsx): a white card per
  rule with a numbered badge, header − / + controls, and label-on-left field
  rows; removes the fragmented side-rail layout
- Rebuild Meta and Taxonomy rule rows and every per-type config panel on the
  new layout, matching the stable UI's native-WP form feel
- Add attachment Width/Height range fields; transform special-cases attachment
  so weight stays in slot 3 (store, providers, weight, width, height)
- Pre-fill a filterable default taxonomy rule (Categories + Tags, Rate 85,
  Qty 1-4) via the fakerpress.posts.default_taxonomy filter
- White card backgrounds on all rule rows
Rule cards now use the stable generator's layout: grey heading band, numbered
left gutter, label-left rows and stacked WordPress remove/add buttons on the right.
There is always at least one rule; - clears the last rule instead of removing it,
+ appends a blank rule, and the separate Add buttons are gone.

Meta configuration sits in one Configuration row with the stable inline labels and
order (weight between providers and sizes for attachments). Restores the Date type,
tag pickers for Person/Geo/Company/Elements/HTML templates, the stable defaults and
copy. Blank placeholder rules are dropped before the request.
The React pages sent REST params the generator modules never read, so Posts
returned 400 (post_type must be a string), Users and Comments fataled
(explode() on an array), and Terms/Attachments generated but the page still
showed an error because the hook read the batch outside the response envelope.

- transform.ts emits the keys and formats the modules read: comma-joined lists,
  interval_date, post_types/post_parent/images_origin, size, generate_* flags,
  {min,max} attachment sizes, and qty {min,max} so quantity ranges randomise
  instead of always using the minimum.
- use-generate-module reads { success, data } and sends the first batch total
  on later batches so the range is not re-rolled per batch.
- User module accepts a boolean use_html (the legacy form still posts 'on').
- Attachment module generates meta field rules through Module\Meta like the
  other modules, instead of storing each rule array under a numeric key.
placehold.co serves SVG when the URL has no extension, and attachments reject SVG,
so every Attachment meta rule that drew Placehold.co (half of the default
_thumbnail_id rule on Posts) failed. meta_type_attachment then stored pieces of
the WP_Error instead of skipping the value.

Ask for .png, as the Attachments generator already does, and treat a WP_Error
from save() as a failure.
- AdminPayloadsTest sends each generate endpoint the JSON the React admin sends
  and checks what was stored (types, dates, terms, roles, HTML descriptions,
  meta rules), plus the Placehold.co PNG URL and the attachment WP_Error guard.
  The four tests on the PHP fixes fail without them.
- transform tests pin the keys and formats each module reads; the generate hook
  tests use the real { success, data } envelope and cover batching.
- Lint-clean rule components and tests; stale Select label fix when a meta
  rule's type changes (config is keyed by type).
- CI: the WPUnit job builds JS first; ReactAssetTest needs build/admin.asset.php.
WordPress runs wp_filter_kses on user bios, which strips block tags like p and
h3 and keeps inline ones. The assertion only passed when the generator happened
to add an inline link, so it failed at random on CI (PHP 8.1/8.2). Ask for
blockquote, which kses keeps, and check for it.
Faker's url() sometimes builds URLs longer than the 100 characters
wp_insert_user() accepts; the insert fails with user_url_too_long and the user is
silently dropped, so asking for 6 users could give 5. This also made
UsersEndpointTest flaky on CI (1 in ~40 runs on PHP 8.2 locally).

Retry up to 5 times for a URL within the limit, then fall back to the domain.
@bordoni
bordoni merged commit c14071f into main Oct 17, 2026
3 of 5 checks passed
bordoni added a commit that referenced this pull request Oct 17, 2026
Changelog: open 0.10.0 with the React admin (#187) entries
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.

1 participant