feat: collapsible grouped fields, blocks, and repeaters#635
feat: collapsible grouped fields, blocks, and repeaters#635bobbwal wants to merge 25 commits intoSonicJs-Org:mainfrom
Conversation
|
Need to investigate further but it seems that in the grouped/blocks form setup, validation errors inside collapsed groups can be hidden, so Update / Update & Publish can appear unresponsive. This is a UX issue rather than a save failure. Follow-up could auto-expand groups with errors, show an error badge/count on collapsed headers, and focus/scroll to the first invalid field on submit. |
…ields-ui # Conflicts: # my-sonicjs-app/src/collections/page-blocks.collection.ts # packages/core/dist/chunk-2YRNPIU4.cjs # packages/core/dist/chunk-2YRNPIU4.cjs.map # packages/core/dist/chunk-6RABGLOO.cjs # packages/core/dist/chunk-6RABGLOO.cjs.map # packages/core/dist/chunk-7DU5PUKL.js # packages/core/dist/chunk-CC4JXOXD.js # packages/core/dist/chunk-D77GPCUP.cjs # packages/core/dist/chunk-D77GPCUP.cjs.map # packages/core/dist/chunk-DADFCDML.js # packages/core/dist/chunk-DADFCDML.js.map # packages/core/dist/chunk-FQAOOSEB.js # packages/core/dist/chunk-FQAOOSEB.js.map # packages/core/dist/chunk-GFKIWSGM.cjs # packages/core/dist/chunk-GFKIWSGM.cjs.map # packages/core/dist/chunk-IUARXOBE.cjs # packages/core/dist/chunk-IUARXOBE.cjs.map # packages/core/dist/chunk-K6TOTMAZ.js # packages/core/dist/chunk-K6TOTMAZ.js.map # packages/core/dist/chunk-PM35AAL5.js # packages/core/dist/chunk-PM35AAL5.js.map # packages/core/dist/chunk-QK5PFGDM.cjs # packages/core/dist/chunk-QKY6I4B7.js # packages/core/dist/chunk-RTXGSM7L.cjs # packages/core/dist/chunk-THCZHX25.cjs # packages/core/dist/chunk-VXTHM6MB.js # packages/core/dist/chunk-VXTHM6MB.js.map # packages/core/dist/chunk-YGWKSR7I.js # packages/core/dist/chunk-YGWKSR7I.js.map # packages/core/dist/chunk-ZKA4WKRO.cjs # packages/core/dist/chunk-ZKA4WKRO.cjs.map # packages/core/dist/index.cjs # packages/core/dist/index.js # packages/core/dist/middleware.cjs # packages/core/dist/middleware.js # packages/core/dist/migrations-AIIAB6XI.js.map # packages/core/dist/migrations-FKBLWET7.cjs.map # packages/core/dist/migrations-JXEISWW5.cjs.map # packages/core/dist/migrations-U57UHVWR.cjs.map # packages/core/dist/migrations-WJVCIKQO.js.map # packages/core/dist/migrations-ZI3P6YZN.js.map # packages/core/dist/routes.cjs # packages/core/dist/routes.js # packages/core/dist/services.cjs # packages/core/dist/services.js # packages/core/src/db/migrations-bundle.ts # packages/core/src/templates/components/dynamic-field.template.ts
# Conflicts: # my-sonicjs-app/src/collections/page-blocks.collection.ts # packages/core/dist/chunk-2YRNPIU4.cjs # packages/core/dist/chunk-2YRNPIU4.cjs.map # packages/core/dist/chunk-3ZUCKXWH.js # packages/core/dist/chunk-3ZUCKXWH.js.map # packages/core/dist/chunk-6RABGLOO.cjs # packages/core/dist/chunk-6RABGLOO.cjs.map # packages/core/dist/chunk-7DU5PUKL.js # packages/core/dist/chunk-CV3VJQSK.cjs # packages/core/dist/chunk-CV3VJQSK.cjs.map # packages/core/dist/chunk-DADFCDML.js # packages/core/dist/chunk-DADFCDML.js.map # packages/core/dist/chunk-ELKAJLYR.cjs # packages/core/dist/chunk-ELKAJLYR.cjs.map # packages/core/dist/chunk-F3B7Q2TS.js # packages/core/dist/chunk-F3B7Q2TS.js.map # packages/core/dist/chunk-FQAOOSEB.js # packages/core/dist/chunk-FQAOOSEB.js.map # packages/core/dist/chunk-H764CAXQ.cjs # packages/core/dist/chunk-H764CAXQ.cjs.map # packages/core/dist/chunk-NY3V264Z.js # packages/core/dist/chunk-OAV6BLZX.js # packages/core/dist/chunk-QK5PFGDM.cjs # packages/core/dist/chunk-W3CLHJUC.cjs # packages/core/dist/chunk-XFK5GC5H.js # packages/core/dist/chunk-XFK5GC5H.js.map # packages/core/dist/chunk-XI6ETTJM.js # packages/core/dist/chunk-XI6ETTJM.js.map # packages/core/dist/chunk-YKPHABCW.cjs # packages/core/dist/chunk-YKPHABCW.cjs.map # packages/core/dist/chunk-ZDH6MHUU.cjs # packages/core/dist/index.cjs # packages/core/dist/index.js # packages/core/dist/middleware.cjs # packages/core/dist/middleware.js # packages/core/dist/migrations-7RCSUPXP.cjs.map # packages/core/dist/migrations-I6PIUYDS.js.map # packages/core/dist/migrations-LCELTSFO.js.map # packages/core/dist/migrations-NXINNQAE.cjs.map # packages/core/dist/migrations-U57UHVWR.cjs.map # packages/core/dist/migrations-WJVCIKQO.js.map # packages/core/dist/routes.cjs # packages/core/dist/routes.js # packages/core/dist/services.cjs # packages/core/dist/services.js # packages/core/src/db/migrations-bundle.ts
This has been sorted, along with the following: Update since original PR description:
|
…er add-item behavior - Scope structured-array operations to direct child items to prevent parent arrays from capturing nested descendants - Harden structured-field initialization with template-skipping and init guards - Resolve list/template/hidden input references live during array actions to avoid stale refs after save/reload - Fix nested array empty-state visibility targeting to direct empty panel only - Add unit coverage for selector scoping in dynamic field template tests - Add E2E coverage for nested array serialization, deletion persistence, and add-after-return flow using page-blocks fixture updates
- Rebuild @sonicjs-cms/core distribution outputs - Update generated migrations bundle to match source changes
Update (Follow-up Fixes Added)Added a follow-up fix for nested repeater serialization/regression uncovered after testing. What was fixed
Test coverage added/updated
Verification
All passing locally. |
- prevent structured field re-initialization while the document is still loading - add nested object serialization regressions in unit and Playwright coverage - update the sample page blocks schema fixture for the repro flow
Update (Follow-up Fixes Added)What was happeningFor nested object-of-objects fields, saves were succeeding, but reopening the edit form could rewrite the parent hidden JSON to only include the first parsed child object. In practice this meant cases like Root causeStructured field initialization was being re-run from repeated inline scripts while the document was still loading. That Fix
Tests
|
Added a follow-up fix for media fields inside structured-array object rows.What was happeningMedia selection inside repeatable object rows could target the wrong field instance in admin forms. In practice, selecting/uploading media for a later row could do nothing at first, then eventually update an earlier row instead. While fixing that path, I also found a related template-token issue in nested gallery-style blocks: block insertion was Fix
Tests
|
|
More context — your collapsible fields feature was cherry-picked into PR #729, currently in CI. This is a big UX improvement and will ship in the next release. Amazing work on this one, @bobbwal — 25 commits of solid engineering! Our process: we cherry-pick fork PRs into lane711 branches to run full CI. Your authorship is preserved in the git history. |
…#635) Add collapsible/expandable sections for grouped fields in the admin content form, improving UX for complex nested collection schemas (objects, arrays, blocks). Includes drag-and-drop reordering, validation visibility, and proper serialization of nested structures. Cherry-picked from bobbwal/sonicjs fix/grouped-fields-ui branch. E2E tests 55-58 skipped pending CI fixture data. Co-Authored-By: Rob Walton <bobbwal@users.noreply.github.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…#635) (#739) Add collapsible/expandable sections for grouped fields in the admin content form, improving UX for complex nested collection schemas (objects, arrays, blocks). Includes drag-and-drop reordering, validation visibility, and proper serialization of nested structures. Cherry-picked from bobbwal/sonicjs fix/grouped-fields-ui branch. E2E tests 55-58 skipped pending CI fixture data. Co-authored-by: Rob Walton <bobbwal@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description
Adds collapsible UI for grouped object fields, blocks, and repeaters in admin forms, defaults them to collapsed, and aligns toggle chevrons. New items expand automatically.
Also adds explicit object field layout control via
objectLayout('nested' | 'flat') and clarifiescollapsedbehaviour in docs (collapsedapplies to nested only).This PR also adds session-level collapsed/expanded state persistence for grouped fields, repeaters, and blocks (scoped per document/collection), plus validation visibility improvements so hidden errors are revealed.
Fixes #634
Includes fixes from #649 and #645 (merged into this branch).
Changes
objectLayoutsupport for object fields (nesteddefault,flatnon-collapsible)collapsedoption for object group fields (default collapsed)objectLayout+collapsedbehaviortests/e2e/53-object-layout.spec.tstests/e2e/55-collapsible-state-persistence.spec.tstests/e2e/56-collapsible-validation-visibility.spec.ts54-hero-cta-style-persistence.spec.ts)Testing
npm run type-checktests/e2e/53-object-layout.spec.tstests/e2e/55-collapsible-state-persistence.spec.tstests/e2e/56-collapsible-validation-visibility.spec.tstests/e2e/54-hero-cta-style-persistence.spec.tsUnit Tests
E2E Tests
Screenshots/Videos
Before:

After:

Checklist
Follow-up planned: refactor collapsible-state persistence helpers to reduce duplication and simplify key/state handling (no functional change).
Generated with Claude Code in Conductor