feat (design library): save patterns
Summary by CodeRabbit
-
New Features
- Saved tab for saved patterns (Pro) and Import/Export modal to import/export design-library data; saved-patterns prompt for non‑Pro users.
-
UI / Behaviour
- Insert action restored for Pages; consistent preview/insert behavior across non‑pages tabs; previews are layout‑constrained and inert while rendering; improved keyboard/click interactions and hover edit overlay.
-
Bug Fix / Preservation
- Saved patterns now preserve original content and design type through selection, preview, and insertion flows.
-
Styling
- Snackbar z‑index increased; hover overlay and responsive styles added.
Walkthrough
Adds a "saved" design type/tab and propagates a new design type (selectedTab) through fetching, filtering, placeholder replacement, selection, and block creation; Pro-gates saved UI and import/export flows; registers REST-backed saved patterns; and adds an Import/Export admin modal with context and styles.
Changes
| Cohort / File(s) | Summary |
|---|---|
Block edit / type propagationsrc/block/design-library/edit.js |
Adds type to design objects and passes it into createBlockWithAttributes; preserves type through selection and adjusts dev-mode attribute conditioning when type === 'saved'. |
Design list item & preview UIsrc/components/design-library-list/design-library-list-item.js, src/components/design-library-list/design-preview.js, src/components/design-library-list/editor.scss |
Replaces host button with conditional interactive div + buttonAttributes; removes pages early-return; injects applyFilters for pro pattern actions; preview wrapper gains is-layout-constrained and inert; adds edit-overlay styles and saved-item cursor tweaks. |
Preview renderer & utilsrc/components/design-library-list/use-preview-renderer.js, src/components/design-library-list/util.js |
Broadens tab-specific logic to treat pages specially (uses selectedTab !== 'pages' elsewhere); passes selectedTab into placeholder replacement; replacePlaceholders gains type param and short-circuits when type === 'saved'. |
Design list containersrc/components/design-library-list/index.js |
Adds selectedTab prop; Pro-gates saved tab by rendering ProControl for non-Pro users and preserves the list for other cases; imports isPro and ProControl. |
Modal design librarysrc/components/modal-design-library/modal.js, src/components/modal-design-library/header-actions.js, src/components/modal-design-library/editor.scss |
Wires selectedTab through modal flows; sources savedPatterns via filter; tags selected designs with type: selectedTab; adds early-return/restore path for saved; shifts background/footer visibility to selectedTab !== 'pages'; raises snackbar z-index when saved items exist. |
Design library coresrc/design-library/index.js, src/design-library/init.php |
Hardens fetchDesignLibrary against missing versions; filterDesigns accepts type (default 'patterns') and skips plan-filtering for 'saved'; PHP adds REST-backed stackable_design_library_saved_patterns setting, sanitizer, and returns saved patterns for type === 'saved'. |
Pro controlsrc/components/pro-control/index.js |
Adds design-library-saved-patterns label and descriptive content for the Pro prompt. |
Import / Export admin UIsrc/welcome/admin.js, src/welcome/admin.scss, src/welcome/import-export/index.js, src/welcome/import-export/context.js, src/welcome/import-export/design-library.js, src/welcome/import-export/import-export.scss |
Adds Import/Export modal and context, tabbed Import/Export UI with JSON import/export handling, Settings model persistence, design-library import/export filters with Pro gating, admin wiring and styles. |
Sequence Diagram(s)
sequenceDiagram
autonumber
actor User
participant Modal as ModalDesignLibrary
participant List as DesignLibraryList
participant Filter as filterDesigns
participant Util as replacePlaceholders
participant Block as createBlockWithAttributes
Note over Modal,List: Tabs = patterns | pages | saved
User->>Modal: Open modal (selectedTab)
Modal->>Filter: filterDesigns(type=selectedTab)
Filter-->>Modal: designs[]
Modal->>List: Render list (selectedTab)
User->>List: Select design(s)
List-->>Modal: onSelect(design { ..., type: selectedTab })
Modal->>Util: replacePlaceholders(content, ..., type=selectedTab)
alt type == saved
Util-->>Modal: return content unchanged
else type == pages
Util-->>Modal: apply pages placeholder logic
else
Util-->>Modal: apply DEFAULT_CONTENT replacements
end
Modal->>Block: createBlockWithAttributes(..., type=selectedTab)
Block-->>Modal: blocks inserted
sequenceDiagram
autonumber
actor Admin
participant Settings as Admin Settings
participant Modal as ImportExportModal
participant Ctx as ImportExportSettingsContext
participant Filters as applyFilters(...)
participant Model as models.Settings
Admin->>Settings: Open Import/Export
Settings->>Modal: Open ImportExportModal
Modal->>Ctx: Provide shared state (file / settings)
alt Export
Modal->>Filters: export-settings handlers
Filters-->>Modal: exported settings
Modal->>Admin: trigger download (timestamped JSON)
else Import
Admin->>Modal: Upload JSON
Modal->>Filters: import-settings handlers
Filters-->>Modal: prepared settings
Modal->>Model: save settings
Model-->>Modal: success
Modal-->>Admin: show snackbar + close
end
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~75 minutes
Potential review focal points:
- propagation of
typeacross selection → replacePlaceholders → block creation - PHP REST setting schema, sanitize_array_setting, and get_design_library handling for
saved - Pro-gating logic in DesignLibraryList and import/export design-library filters
- use-preview-renderer tab-logic changes and their effects on preview/insertion paths
Possibly related PRs
- gambitph/Stackable#3573 — Strong overlap: propagates design
type/selectedTab across modal, list, util, and block creation; likely code-level conflicts. - gambitph/Stackable#3594 — Touches
use-preview-rendererand preview gating similar to this PR’s tab-aware preview changes. - gambitph/Stackable#3601 — Modifies selection and preview flows in modal/list components; may conflict with
selectedTaband onSelect handling.
Poem
A rabbit hops to Saved with glee,
Types follow designs from A to Z.
From list to modal, then to block,
Defaults pause — the carrots stock.
Import, export — a hoppity spree. 🥕
Pre-merge checks and finishing touches
✅ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The PR title 'feat (design library): save patterns' directly and clearly summarizes the main change: adding the ability to save patterns in the design library. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✨ Finishing touches
- [ ] 📝 Generate docstrings
🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
feat/design-library-saving-patterns
📜 Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 109747651ba33a4d15340f5b2af57a0266315d4f and 708b376bc6bea869ce26cdf848e09d50c0984cbd.
📒 Files selected for processing (1)
src/components/pro-control/index.js(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/components/pro-control/index.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: PHP 8.2 and WP latest
- GitHub Check: PHP 8.2 and WP 6.7.2
- GitHub Check: PHP 8.2 and WP 6.5.5
- GitHub Check: PHP 8.2 and WP 6.6.2
- GitHub Check: PHP 7.3 and WP 6.5.5
- GitHub Check: PHP 7.3 and WP latest
- GitHub Check: build
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
🤖 Pull request artifacts
| file | commit |
|---|---|
pr3629-stackable-3629-merge.zip |
708b376bc6bea869ce26cdf848e09d50c0984cbd |
Try this Pull Request in the WordPress playground: https://playground.wordpress.net/?mode=seamless#{"landingPage":"/wp-admin/post-new.php?post_type=page","preferredVersions":{"php":"latest","wp":"latest"},"steps":[{"step":"login","username":"admin","password":"password"},{"step":"installPlugin","pluginZipFile":{"resource":"url","url":"https://raw.githubusercontent.com/gambitph/Stackable/artifacts/pr3629-stackable-3629-merge.zip"}}]}