feat(block-theme): add search overlay block#4729
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The class file is only included from the wp_is_block_theme() branch in class-blocks.php, so re-checking inside register_block() is dead code and diverges from the overlay-menu pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Matches the my-account-button pattern: blockClassName is applied to both the outer wp-block-buttons wrapper and the button's classnames() call, so block-style classes propagate consistently across editor and frontend output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-overlay Calling the hook at the top of the component (alongside the other use* hooks) reads more clearly than spreading the call inline in JSX, and matches the surrounding pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
render_trigger_button already returns a string; the buffer was extra indirection that masked the simpler return path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
z-index raised to 99999 so the panel isn't occluded by newspack-ui modals or the content banner. Default background and content max-width now read from the active theme's tokens, with the original literal values kept as CSS-fallbacks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The overlay color rendered in its own InspectorControls panel below
the standard Color section, which was easy to miss. Moving it under
InspectorControls group="color" with panelId={ clientId } slots it
into the existing Color ToolsPanel alongside Background and Text,
matching the overlay-menu pattern. Label shortened to "Overlay" so it
reads naturally next to "Background" and "Text".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces hard-coded 2rem padding with the spacing tokens (--wp--preset--spacing--30/40, responsive at the tablet breakpoint), adds overflow-y: auto so tall content can scroll, and locks document scrolling while any instance is open via the menu-open--search-overlay- body class selector. Matches the established overlay-menu defaults. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The theme's [class*="newspack-icon"] span selector hides spans off-screen — it expects icons rendered via CSS background/pseudo- element, not the inline-SVG-in-a-span pattern this block uses. With newspack-icon-close present, the visible SVG span was being pushed to left: -99999em and the close button rendered empty on the front end. Dropping the class matches the overlay-menu close button and restores the icon. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two small frontend tweaks on the search-overlay panel: - The close button color is now set inline based on the panel's computed background color, using the same YIQ formula the plugin's getContrast helper uses. Works for hex, rgba, theme-token defaults, and palette swatches uniformly because it reads the resolved CSS background via getComputedStyle. - Clicking the panel scrim (the colored area outside the search form and close button) now closes the overlay, matching the standard modal-with-scrim interaction. The handler uses e.target === panel so clicks on any inner element still behave as expected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the dense \$html .= concatenation in render_trigger_button, render_jetpack_trigger, and render_panel with ob_start() and inline PHP templates so the HTML structure is visible at a glance. Matches the overlay-menu-panel pattern (the closer reference) and follows the same phpcs:ignore conventions for outputting pre-escaped HTML (self::ICON_* constants and render_block() return values). Output is byte-identical to the previous implementation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The panel acts as a full-screen scrim — same idea as overlay-menu's .overlay-menu__scrim, just without a separate panel underneath. The opaque theme-base default treated it like a search-page takeover; rgba(0, 0, 0, 0.5) matches the scrim's lightbox/modal feel by default. The block's overlayColor attribute still overrides this when set. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Port the higher anchor, darker scrim, and slide-down content animation from newspack-block-theme's search overlay. Also wire the Overlay color control into the ToolsPanel reset flow so it clears with the rest of the color settings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a Search Overlay block for Newspack block themes, rendering a customizable trigger that opens a full-screen search dialog and hands off to Jetpack Instant Search when detected.
Changes:
- Registers the new Search Overlay block in editor/server block registration.
- Adds frontend overlay behavior, styling, editor UI, and dynamic PHP rendering.
- Adds a dedicated frontend bundle entry for the overlay script.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
webpack.config.js |
Adds the search overlay frontend script bundle. |
src/blocks/search-overlay/view.js |
Implements frontend open/close behavior, focus handling, and contrast color selection. |
src/blocks/search-overlay/style.scss |
Adds trigger, panel, close button, and body scroll-lock styles. |
src/blocks/search-overlay/index.js |
Registers block styles and editor settings. |
src/blocks/search-overlay/edit.js |
Adds editor controls and trigger label editing. |
src/blocks/search-overlay/class-search-overlay-block.php |
Adds server-side dynamic rendering and Jetpack handoff markup. |
src/blocks/search-overlay/block.json |
Defines block metadata, supports, styles, and view script. |
src/blocks/index.js |
Adds the block to client-side registration and block-theme gating. |
includes/class-blocks.php |
Includes the server-side block class for block themes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Looks good @laurelfulford! Tested and everything looks good. Below are some non-blocking comments from the review skill that I thought were worth looking at. Feel free to ignore any that you feel aren't relevant (even if its all of them).
| public static function render_block( array $attributes ): string { | ||
| // The compiled view script depends on dist/commons.js (a webpack split chunk). | ||
| // Ensure commons is enqueued so the entry callback can execute on the frontend. | ||
| \Newspack\Newspack::load_common_assets(); |
There was a problem hiding this comment.
Newspack::load_common_assets() enqueues newspack-commons JS and the newspack-commons CSS handle — the CSS depends on wp-components, pulling the editor-oriented stylesheet into every frontend page that contains an overlay-search block. The view script does need the webpack commons chunk (split-chunk dependency), but the CSS side is almost certainly dead weight on the frontend.
Inherited from overlay-menu, but this PR doubles the surface where it ships. Worth a follow-up to split frontend JS-only commons from full commons.
There was a problem hiding this comment.
Thanks @chickenn00dle! I made a new task for this here to untangle after this gets merged: NPPD-1563
| // Render core/search per instance so each panel gets its own unique input id. | ||
| $search_html = \render_block( | ||
| [ | ||
| 'blockName' => 'core/search', |
There was a problem hiding this comment.
render_block( [ 'blockName' => 'core/search', ... ] ) re-renders a fresh core/search block per overlay-search instance. For a header with multiple instances (desktop + mobile + footer), this runs the full core block render pipeline N times per request.
Acceptable for v1 — but if profiling shows it as a hot path, consider caching the rendered form HTML once and substituting wp_unique_id-suffixed input IDs per instance.
There was a problem hiding this comment.
This one seems relatively low risk (a site's unlikely to have more than 2 instances of the block to cover the desktop/mobile headers but better safe than sorry! I made NPPD-1564 to investigate further!
| */ | ||
| import domReady from '@wordpress/dom-ready'; | ||
|
|
||
| const FOCUSABLE_SELECTOR = |
There was a problem hiding this comment.
FOCUSABLE_SELECTOR, getVisibleFocusable(), the focus-trap loop, the Esc handler, and the "return focus to opener" pattern here are duplicated almost verbatim from overlay-menu/view.js. With a third overlay block landing in the codebase, it might be time to extract these into something like src/blocks/shared/overlay-controller.js.
The behaviors are also subtly diverging — overlay-menu uses setTimeout( ..., 50 ) for focus, overlay-search uses double requestAnimationFrame — both correct, but consistency matters going forward. Not a blocker for this PR; worth a follow-up issue.
There was a problem hiding this comment.
Good call! Issue created here for further follow-up NPPD-1565
|
Hey @laurelfulford, good job getting this PR merged! 🎉 Now, the Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label. If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label. Thank you! ❤️ |
All Submissions:
Changes proposed in this Pull Request:
This PR adds a Search Overlay Block to be used in the Newspack Block Theme. It's inserted as a button into the block theme, and when clicked, will open an overlay with the search block in it. The button appearance (colours, fonts, border radius), label (changing text or hiding text/icon) and overlay (colour) are customizeable, but the search -- for now -- is not).
When Jetpack's instant search is enabled, it will be opened instead.
A version of this functionality is currently baked into the theme using template parts. The downside is that that's pretty fragile - changing the structure or a class name could break how it works. My moving the functionality to block, we make sure it's easier to use, add, and customize.
Closes NPPD-1449.
How to test the changes in this Pull Request:
Test the visual stuff
Confirm the block is accessible
aria-expanded="false", aria-controls="newspack-overlay-search-panel-…"aria-hidden="true",inertattributesaria-expanded="true"and the panel losesaria-hiddenandinertJetpack Instant Search
Get weird & throw a search party!
esckey still closes the open overlay.Other information:
Update (scope)
In addition to introducing the new Search Overlay block, this PR includes two related changes to existing Newspack blocks:
Block style registration moved to
block.json— foroverlay-search,overlay-menu-trigger, andmy-account-button, thedefault/icon-only/text-onlystyle variations are now declared inblock.jsonstylesarrays instead of JS-onlyregisterBlockStyle()calls. This makes the variations visible totheme.jsonso themes can target them viastyles.blocks.<name>.variations.<style>.Overlay Menu inner blocks are now permanently locked —
overlay-menu-triggerandoverlay-menu-panelnow bakelock: { move: true, remove: true }into theirblock.jsonattribute defaults. Combined with the existingsupports.lock: false, the lock UI is hidden and the inner blocks of everynewspack/overlay-menuinstance — including ones already saved in shipped patterns — cannot be moved or deleted, even via the parent block's "Modify" template-bypass UI.Extra test steps for the scope updates
Companion theme PR:
Automattic/newspack-block-theme#452