Skip to content

feat(customizer): disable the header and the footer for the whole site - #4650

Open
selul wants to merge 24 commits into
developmentfrom
feat/4551-global-settings
Open

selul wants to merge 24 commits into
developmentfrom
feat/4551-global-settings

Conversation

@selul

@selul selul commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Users who build their header and footer with a page builder had no way to turn off the theme header and footer for the whole site. This PR adds Disable Header and Disable Footer to existing Customizer sections, and a disabled header no longer leaves an empty wrapper on the page.

Note

This PR replaces #4628. It carries the commits of #4628 and moves the toggles out of the two single-control sections that #4628 added.

What changed

  • Header panel — Disable Header is the first control on the General tab of Global Header Settings. Neve Pro already shows its site-wide header controls on that tab. Sites still on the legacy header builder get the same section with the toggle as a plain control, without tabs.

  • Footer panel — a new Footer Options section holds Disable Footer. It sits below the footer rows, after Change Copyright when a site has that section.

  • Strings — the change adds no strings to translate. It reuses Disable Header, Disable Footer, Global Header Settings and Footer Options.

  • Header markup — when the header is off, the <header> element is printed only if other code adds content around the header, such as the Neve Pro page header. With nothing to wrap, no element is printed. Before, an empty element stayed on the page. The skip link now prints outside the header element, and on AMP it keeps next-page-hide. inc/compatibility/fse.php gets the same change for the block template.

  • Post meta — a page can still turn its own header or footer off. A page can no longer turn one back on against the global toggle.

  • AMP — the amp-state elements move to neve_after_header_wrapper_hook, because one of them drives the WooCommerce shop sidebar. The scroll-to-top animations print before the header wrapper, and their observer watches an anchor that scrolls out of view. When the footer is off, the infinite scroll steps aside and the archive keeps its regular pagination.

Note

The toggle removes the whole header region, and page builders render into that region. Elementor Pro, Header Footer Elementor and Beaver Themer hook neve_do_header and neve_do_footer, so their headers and footers go away too. This is intended: a user who wants a page builder header leaves the toggle off. Elementor Canvas templates never call get_header(), so they do not change.

Note

The header hooks run inside an output buffer, so the wrapper prints only around real content. A hook callback that calls ob_flush() or throws can bypass that buffer. No callback in Neve or Neve Pro does this.

Note

Disable Header is not a conditional header setting. Neve Pro does not swap it per header layout, so it hides every header layout at once.

What decides if the header renders

flowchart LR
    A["Page loads"] --> B{"Post meta<br/>set to on?"}
    B -- yes --> C["No header"]
    B -- no --> D{"New:<br/>Disable Header<br/>is on?"}:::added
    D -- yes --> E["Changed:<br/>no header element,<br/>skip link stays"]:::changed
    D -- no --> F["Header renders"]

    classDef added fill:#1a7f37,color:#fff,stroke:#116329,stroke-width:3px
    classDef changed fill:#9a6700,color:#fff,stroke:#5c3d00,stroke-width:3px,stroke-dasharray:6 3
Loading

QA

  1. Go to WP Admin → Appearance → Customize → Header → Global Header Settings.

    Expect: the General tab opens first and shows Disable Header, off. The Style tab still holds the background controls.

  2. Turn on Disable Header and publish. Open the front end in a new tab and view the page source (Ctrl+U or Cmd+Option+U). Search for <header.

    Expect: no match. One neve-skip-link match stays, and Tab at the top of the page shows Skip to content.

  3. Open a category archive and a search results page, for example /?s=test.

    Expect: no header on either page. The page metabox never covered these views.

  4. Open a single page in the editor. In the sidebar, open Neve Options. Turn Disable Header on, update, then turn it off and update again.

    Expect: with the global toggle on, the page has no header in both states.

  5. Turn off the global Disable Header. On the same page, set the page's Disable Header to on and update.

    Expect: this page has no header. Every other page keeps its header.

  6. If WooCommerce is active, turn on the global toggle and open the shop archive on a narrow screen.

    Expect: no header. The shop sidebar and its filter toggle still work.

  7. Go to WP Admin → Appearance → Customize → Footer → Footer Options. Turn on Disable Footer and publish. Search the front-end source for id="site-footer".

    Expect: no match. The page still ends with </body>.

  8. Switch the site to the legacy header builder with WP-CLI, then go to Customize → Header.

    wp theme mod set neve_migrated_builders 0

    Expect: the panel lists Global Header Settings. It holds Disable Header with no tabs, and turning it on removes the header from the preview.

  9. Switch the site back to the new builder.

    wp theme mod remove neve_migrated_builders

    Expect: the Header panel shows the builder rows and the tabbed Global Header Settings again.

  10. If Neve Pro is active with a license, go to Customize → Header → Global Header Settings → General.

    Expect: Disable Header comes first, above Show This Header Site-wide.

  11. If Neve Pro is active with a license, add a component to its Page Header builder. Turn on Disable Header for one page in Neve Options, then for the whole site.

    Expect: in both cases the main header is gone and the page header still shows.

  12. If the AMP plugin is active, set the blog to infinite pagination with no sidebar. The Post Pagination control comes from Neve Pro, so without it use WP-CLI. Turn on Disable Footer and open the blog page on its AMP URL.

    wp theme mod set neve_pagination_type infinite
    wp theme mod set neve_default_sidebar_layout full-width

    Expect: the regular page links show at the end of the post list.

Part of #4551.

🤖 Generated with Claude Code

Alexia-Soare and others added 12 commits September 18, 2026 15:38
Add a Disable Header Globally toggle to the Header panel and a Disable
Footer Globally toggle to the Footer panel. Both feed the existing
neve_filter_toggle_content_parts filter, at a priority that runs after
the post meta, so the site wide setting wins.

Move the filter check outside the header element in both templates. The
element used to be printed even when the header was off, which left an
empty wrapper that held only the skip link. The skip link now sits
outside the element, so it survives a disabled header.

The builder panels hide every section they do not name, so both sections
are added to the whitelist in the customizer styles.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The states were printed on neve_after_header_hook, which does not run
when the header is off. One of them drives the WooCommerce shop sidebar,
which stays on the page without a header.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add unit tests for the toggle, its precedence over the post meta, the
markup of both templates and the customizer registration. Add end to end
tests, one of which opens the builder panels, because a section can
register and still be hidden by the panel styles.

Complete the WooCommerce stub with the conditional tags, so tests that
render body_class() after the cart tests do not fatal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The test case restores the hooks and rolls back the database, but it does
not touch $wp_customize. Keep the previous value and put it back, the way
the metabox test does with the REST server.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Hold the panel, the section title and the control label in one array per
part, in place of two ternaries.

Assert on the toggle structure in the e2e spec, not on the English label.
Check that the stylesheet exists before the test reads it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drop the hook docblock copied into header.php. footer.php documents this
filter and the block theme template carries none.

Keep only the part of the filter docblock a reader cannot infer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The animations were printed on `neve_before_header_hook`, which only runs
inside the header element. A header turned off in the customizer took them
with it, and the button stays hidden until an animation shows it.

Print them on `neve_before_header_wrapper_hook`, next to the AMP states.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An `amp-position-observer` watches its own parent when it has no target. Moving
the observer out of the header in 9462899 made the page wrapper its parent, and
the wrapper is never out of the viewport, so the button stayed hidden on every
AMP page.

Print an anchor at the top of the wrapper and point the observer at it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…settings

The toggles no longer get a section each. Disable Header now opens the
General tab of Global Header Settings, where Neve Pro already keeps its
site-wide header controls. Disable Footer lives in a new Global Footer
Settings section, the footer's counterpart, so the two panels match.

The theme mod keys stay neve_disable_header and neve_disable_footer, so
the render filter and saved values are unchanged. Both toggles reuse the
per-page labels and say that page builder headers and footers go too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/ is excluded from the theme build by .distignore. Drop this commit
before merging if the images should not stay in the repository.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pirate-bot

pirate-bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Plugin build for 22e9843 is ready 🛎️!

The toggle was registered only with the new builder's global header
settings, so sites still on the legacy builder lost it. Those sites now
get a Global Header Settings section with the toggle as a plain control.
It has no tabs, so any Neve Pro controls in that section show as before,
and a section Pro registered first is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul
selul requested a review from pirate-bot October 7, 2026 20:32

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes requested

The toggles move correctly and the tests pass, but two small code fixes are needed in Header.php and the test provider.

Validation details
  • Files reviewed: 12/12 changed files. The four PNG screenshots were not inspected.
  • TestNeveGlobalHeaderFooter passed at HEAD with PHP 8.3, WordPress 7.1.3 and PHPUnit 9.6: 29 tests, 109 assertions.
  • Every changed test failed on the base code with the PR tests kept: 5 failures and 1 error.
  • No remaining code references the removed sections or the removed class.
  • Capability, sanitization and escaping match the base code.
Untested areas
  • The Customizer screens were not opened in a browser. The customizer build was not run.
  • The changed Playwright spec was not run.
  • Neve Pro was not available, so the order beside its controls is unchecked.

🤖 Automated review · run code-review-agent_6ac6ac6fdea3e6.06896057.


🤖 Review agent — review posted ✅ on 9d082a82 · changes requested · 2 findings · 15 min

Run code-review-agent_6ac6ac6fdea3e6.06896057 · trail

Comment thread header-footer-grid/Core/Builder/Header.php
Comment thread tests/test-neve-global-header-footer.php Outdated
Both registrations of neve_disable_header now take default, transport
and sanitize_callback from get_disable_header_setting_args(), so the
legacy and the new builder paths cannot drift apart. The user-since
data provider gets a precise return type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul
selul requested a review from pirate-bot October 7, 2026 20:51
… call

Theme Check reads each $wp_customize->add_setting() call and requires a
sanitize_callback key in it, so passing the shared argument array failed
the check. The legacy call now lists the keys, with values still taken
from get_disable_header_setting_args().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes requested

Both earlier findings are fixed. Add native : array return types to the two new helpers in Header.php.

Validation details
  • Files reviewed: 12/12 changed files. The four PNG screenshots were not inspected.
  • TestNeveGlobalHeaderFooter passed at HEAD with PHP 8.3, WordPress 7.1.3 and PHPUnit 9.6: 29 tests, 109 assertions.
  • php -l passed on Header.php.
  • Theme Check needs the literal sanitize_callback key inside add_setting(), so the unpacked keys are justified.
  • Base-tree test failures and the security checks come from run code-review-agent_6ac6ac6fdea3e6.06896057, not rerun.
Untested areas
  • The Customizer screens were not opened in a browser.
  • The changed Playwright spec was not run.
  • Neve Pro was not available, so the order beside its controls is unchecked.

🤖 Automated review · run code-review-agent_6ac6b18f6f31b7.82482385.


🤖 Review agent — review posted ✅ on a66fcdbc · changes requested · 2 findings · 7 min

Run code-review-agent_6ac6b18f6f31b7.82482385 · trail

Comment thread header-footer-grid/Core/Builder/Header.php Outdated
Comment thread header-footer-grid/Core/Builder/Header.php Outdated
…lpers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul
selul requested a review from pirate-bot October 7, 2026 21:15

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The PR passes. Both helpers in Header.php now declare native : array return types, which fixes the last two findings.

Validation details
  • Files reviewed: 12/12 changed files. Only Header.php changed since a66fcdbc. The four PNG screenshots were not inspected.
  • php -l passed on Header.php with PHP 8.3.
  • TestNeveGlobalHeaderFooter passed at HEAD with PHP 8.3, WordPress 7.1.3 and PHPUnit 9.6: 29 tests, 109 assertions.
  • A standards check of the new commit found no issue.
  • Security checks and base-tree test runs come from runs code-review-agent_6ac6ac6fdea3e6.06896057 and code-review-agent_6ac6b18f6f31b7.82482385, not rerun.
Untested areas
  • The Customizer screens were not opened in a browser.
  • The changed Playwright spec was not run.
  • Neve Pro was not available, so the order beside its controls is unchecked.

🤖 Automated review · run code-review-agent_6ac6b67b04eaf5.37804121.


🤖 Review agent — review posted ✅ on 12ef6887 · approved · 0 findings · 2 min

Run code-review-agent_6ac6b67b04eaf5.37804121 · trail

@selul
selul changed the base branch from feat/4551 to development October 8, 2026 07:21
selul and others added 4 commits October 8, 2026 10:30
The footer section is now titled Footer Options and both toggles drop
their descriptions, so the change adds no strings to translate. Every
label it uses already exists in the theme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul selul changed the title refactor(customizer): move the header and footer toggles into global settings feat(customizer): disable the header and the footer for the whole site Oct 8, 2026
… without the footer

A disabled header skipped neve_before_header_hook and
neve_after_header_hook along with the wrapper. Neve Pro prints its page
header on neve_after_header_hook, so a page that turned its header off
lost the page header too, which development keeps. The hooks now always
run, and the header wrapper prints when the header is on or when the
hooks printed something. An empty wrapper is still dropped. The block
template follows the same rule.

The AMP infinite scroll wraps the footer hooks and removes the regular
pagination, so with the footer off an AMP blog archive had no pagination
at all. The infinite scroll now steps aside when the footer is off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The skip link used to sit inside <header next-page-hide>, so AMP infinite
scroll hid it on the pages it appends. Outside the header it needs its
own attribute, or every appended page adds another focusable skip link.

Tests now also cover whitespace-only hook output and the per-page switch
in the block theme template.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul
selul requested a review from pirate-bot October 8, 2026 07:59

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes requested

The feature code works, but four test fixes are needed: one FSE test cannot fail, one comment is false, one case is missing, and some types are too broad.

Validation details
  • Files reviewed: 13/17 changed files. The four PNG screenshots were not inspected.
  • TestNeveGlobalHeaderFooter passed at HEAD with PHP 8.3, WordPress 7.1.3 and PHPUnit 9.6: 37 tests.
  • With the changed theme files restored from pr-base, 25 of 37 tests failed.
  • A scratch FSE render with FSE templates enabled showed the header part dropped only at HEAD.
  • Source checks found no security issue.
Untested areas
  • The new Playwright spec was not run.
  • The Customizer screens were not opened.
  • AMP pages were not rendered in a browser.
  • Neve Pro was not available.

🤖 Automated review · run code-review-agent_6ac74d64b38553.54222683.


🤖 Review agent — review posted ✅ on 70f69bf4 · changes requested · 4 findings · 21 min

Run code-review-agent_6ac74d64b38553.54222683 · trail

Comment thread tests/test-neve-global-header-footer.php
Comment thread tests/test-neve-global-header-footer.php Outdated
Comment thread inc/compatibility/fse.php
Comment thread tests/test-neve-global-header-footer.php Outdated
selul and others added 2 commits October 8, 2026 11:23
The block template helper never enabled the theme's FSE templates, so the
header part never rendered and the tests passed whatever the template
did. They now turn the templates on and check neve_do_header, and a new
case covers the AMP attribute on the block template skip link.

The shop test is gone: it opened a regular page and never reached the
shop branch, and the rule it checked is covered by the global-over-meta
test. Docblocks of the providers and helpers now give their shapes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@selul
selul requested a review from pirate-bot October 8, 2026 08:26

@pirate-bot pirate-bot left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approved

The PR passes. All four earlier test findings are fixed, and the new commit adds no new problem.

Validation details
  • Files reviewed: 13/13 changed files. Since 70f69bf4, only the test file changed and four screenshots were deleted.
  • TestNeveGlobalHeaderFooter passed at HEAD with PHPUnit 9.6, PHP 8.3 and WordPress 7.1.3: 37 tests.
  • With the changed theme files from pr-base, 25 of 37 tests failed, including the FSE disabled-header and FSE AMP tests.
  • With only fse.php from pr-base, 3 FSE tests failed.
  • Security checks from run code-review-agent_6ac74d64b38553.54222683 were reused, not rerun. No theme code changed since then.
Untested areas
  • The new Playwright spec was not run.
  • The Customizer screens and AMP pages were not opened in a browser.
  • Neve Pro was not available.

🤖 Automated review · run code-review-agent_6ac753d0713d86.11019970.


🤖 Review agent — review posted ✅ on 22e98438 · approved · 0 findings · 7 min

Run code-review-agent_6ac753d0713d86.11019970 · trail

This branch has not been deployed

No deployments
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.

3 participants