Slipstream

v2.5.21Updated: 22/04/2026

v2.5.21

  — **Owners can now reach package-registered settings pages.** Package panels render with URLs like `admin.php?page=ss-menu-highlights-settings` — clicking them as an owner used to 403 because the packages registered those `add_submenu_page()` calls with `’manage_options’` as the capability (admin-only). WP’s menu-level cap check runs before the render function so owners never saw the page content.
– **Fix:** `filter_owner_capabilities()` now grants `is_slipstream_owner` to administrators too (it was already a persistent role cap on `owner` via `add_role()`; admins got it at runtime via the cap filter). This makes `is_slipstream_owner` the documented capability for panel-linked settings pages that both roles need to reach. No separate OR-check required.
– **Package pattern** — packages registering their settings page:
“`php
add_submenu_page(
null, // hidden slot (accessed via Slipstream dashboard)
‘My Package Settings’,
‘My Package’,
‘is_slipstream_owner’, // accessible to owners + admins
‘ss-my-package-settings’,
‘my_package_render_settings’
);
“`
`manage_options` should only be used when a page is legitimately admin-only (e.g. Slipstream Package Manager, Developer Config).
– **Updated 5 in-tree packages** to the new pattern: `menu-highlights`, `pdf-menus`, `quick-bar`, `smooth-slide`, `site-stats`. External plugins that register panel-linked admin pages with `manage_options` should update similarly.

v2.5.20

  — **Two new extension points for “+ Add New” flows.** The 2.5.15 add-new routing always forced an auto-draft + Content Editor redirect — fine for most CPTs but wrong for ones with their own creation UI (popup modals, wizards, etc.). Plugins can now override or tune both the destination and the initial status.

– **Filter `slipstream_new_post_url`** — fires inside `reroute_new_post_for_owner` BEFORE the auto-draft is created. If the filter returns a non-empty URL string, Slipstream redirects there directly and skips draft creation entirely. Plugins use this to route “+ Add New” to their own popup UI:
“`php
add_filter(‘slipstream_new_post_url’, function($url, $post_type) {
if ($post_type === ‘make_faq’) {
return admin_url(‘edit.php?post_type=make_faq&make_faq_new=1’);
}
return $url;
}, 10, 2);
“`
Plugin JS then watches for the marker param on page load and opens the popup. No draft left behind.

– **Filter `slipstream_new_post_initial_status`** — fires inside `handle_content_editor_save` when promoting an auto-draft on its first save. Default `’draft’` so users explicitly publish via the row-level status toggle, but CPTs where immediate-publish makes sense (FAQs, announcements, simple reference content with no draft workflow) can opt in:
“`php
add_filter(‘slipstream_new_post_initial_status’, function($status, $post_type) {
return $post_type === ‘make_faq’ ? ‘publish’ : $status;
}, 10, 2);
“`

– **Declarative sugar on `register_post_type_for_owner`.** Both filters have convenience args on the helper so packages can declare new-post behaviour at registration time:
“`php
$registry->register_post_type_for_owner(‘announcement’, array(
‘name’ => ‘Announcements’,
‘initial_status’ => ‘publish’, // auto-publish on first save
‘new_post_url’ => admin_url(‘edit.php?post_type=announcement&new=1’), // route to popup instead of CE
));
“`
Under the hood these register the filters for this one post type. Plugins with more dynamic needs (per-context status, URL variations) still use the filters directly.

v2.5.19

  — **Reusable modal CSS kit** at `assets/css/modal.css` — enqueued on every admin screen via `router.php::enqueue_styles`. Previously the modal styles (`.slip-modal-backdrop`, `.slip-modal-panel`, `.slip-modal-header`, `.slip-modal-title`, `.slip-modal-close`, `.slip-modal-body`, `.slip-modal-footer`, `.slip-modal-error`, `.slip-btn`, `.slip-btn-primary`, `.slip-btn-secondary`) lived inside `meta-seo.css` and only loaded on meta-seo screens. Third-party plugins that want to use the Slipstream aesthetic for their own popups (e.g. make-faq’s quick-edit) can now reference these classes directly in their markup without enqueueing anything extra. The `meta-seo.css` originals stay in place — they override-equal (same values) with no visual difference.
– **Added `.slip-modal-panel–wide`** modifier (max-width 720px) for richer forms. Default panel stays at 520px.
– **Added `.slip-modal-footer-status`** for status/loading areas pinned left in the footer (margin-right: auto), plus a small `.slip-modal-loading` spinner plugins can drop in during AJAX waits.
– **Added `.slip-toolbar`** for inline formatting toolbars attached above textareas (bold/italic/link-style rows) — matches Slipstream’s palette instead of raw WP admin chrome.
– **Input coverage broadened.** Modal input styling now applies to `[type=”url”]`, `[type=”email”]`, `[type=”number”]` in addition to `text` + `textarea`.
– **Design principle.** Plugins get a drop-in CSS kit; plugins keep their own JS/markup/logic. Slipstream doesn’t try to own their form flow — just gives them the visual vocabulary. `window.slipstreamModal` remains available (from meta-seo.js) for plugins that want a fully-managed popup, but using the raw classes is the zero-friction path for plugins with their own AJAX + form shape.

v2.5.18

  — **Framework-first: extension points for third-party plugins.** Previously owners’ chrome (row actions cluster, Content Editor dropdown) was hardcoded. Plugins that wanted to add their own actions — e.g. the `make-faq` plugin’s popup edit UI — had no clean hook. Three filter-based extension APIs so packages can add/remove/replace surfaces without touching Slipstream core:

– **Row actions → `slipstream_row_actions` filter.** `render_actions_cell()` now builds an associative array keyed by slug (`seo`, `featured_image`, `view`, `status`, `edit`), sorts by `priority`, and calls each item’s `render` callable. Plugin use:
“`php
add_filter(‘slipstream_row_actions’, function($actions, $post) {
if ($post->post_type === ‘make_faq’) {
unset($actions[‘view’]); // remove a default
$actions[‘quick_edit’] = [ // add a custom
‘priority’ => 50,
‘render’ => fn($p) => ‘‘,
];
unset($actions[‘edit’]); // override default Edit
}
return $actions;
}, 10, 2);
“`
`render` closures take `$post`, return HTML string (or `”` to skip). Each closure is responsible for its own escaping.

– **Default View action respects `publicly_queryable`.** For CPTs registered with `publicly_queryable => false` (FAQs, lookup tables, etc.) the default `view` action’s render short-circuits — `get_permalink()` would return a 404’ing URL anyway. Plugins that want a “view” target for non-queryable types replace the item via the filter above.

– **Content Editor dropdown → `slipstream_content_editor_dropdown` filter.** The split-save `⋮` menu items (“View page”, “Page settings”) are now an associative array keyed by slug with `priority`, `label`, `icon`, `url`, `target`, `attrs`, or a raw `html` override. Renders as `` if `url` set, `