From c6e95871e2df76f0737c295749f09de5b79b650b Mon Sep 17 00:00:00 2001 From: krugazul Date: Wed, 30 Sep 2026 10:04:53 +0200 Subject: [PATCH 1/5] Altering the block to patterns --- blocks/phase-services/block.json | 11 - blocks/phase-services/index.js | 34 --- blocks/phase-services/render.php | 213 ------------------ inc/blocks.php | 38 ---- patterns/sections/phase-services-in-phase.php | 29 --- 5 files changed, 325 deletions(-) delete mode 100644 blocks/phase-services/block.json delete mode 100644 blocks/phase-services/index.js delete mode 100644 blocks/phase-services/render.php delete mode 100644 inc/blocks.php delete mode 100644 patterns/sections/phase-services-in-phase.php diff --git a/blocks/phase-services/block.json b/blocks/phase-services/block.json deleted file mode 100644 index e64ee3e..0000000 --- a/blocks/phase-services/block.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://schemas.wp.org/trunk/block.json", - "apiVersion": 3, - "name": "ls-theme/phase-services", - "title": "Phase Services", - "category": "text", - "description": "Renders the current lifecycle phase page's \"Services in this phase\" heading and service cards. Implements CodeRabbit's request-time rendering fix for patterns/sections/phase-services-in-phase.php: PHP phase-detection baked into a pattern's own content only re-evaluates while the pattern stays a live wp:pattern reference, and is lost if WordPress flattens it, so the phase-dependent selection and markup now live in this dynamic block's render.php instead, which runs at real request time regardless of how the surrounding pattern is stored.", - "textdomain": "ls-theme", - "usesContext": [ "postId" ], - "render": "file:./render.php" -} diff --git a/blocks/phase-services/index.js b/blocks/phase-services/index.js deleted file mode 100644 index 065d90f..0000000 --- a/blocks/phase-services/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Editor-side registration for ls-theme/phase-services. - * - * The PHP registration in inc/blocks.php (register_block_type against this folder's block.json) - * only tells WordPress how to render this block on the front end — the block editor's own JS - * registry is entirely separate, and needs its own wp.blocks.registerBlockType() call by the same - * name or it shows "Your site doesn't include support for this block" and renders nothing in the - * canvas. ServerSideRender is used for `edit` (rather than reimplementing the markup in JS) so the - * editor preview always matches render.php's actual output, including the current phase's real - * content and colour — no separate editor-only representation to keep in sync. - * - * Plain global-based script (no build step), per AGENTS.md "Avoid inventing a build pipeline". - * - * @package ls-theme - */ -( function ( blocks, element, serverSideRender ) { - var el = element.createElement; - - blocks.registerBlockType( 'ls-theme/phase-services', { - title: 'Phase Services', - category: 'text', - usesContext: [ 'postId' ], - description: 'Renders the current phase page\'s "Services in this phase" heading and service cards.', - edit: function ( props ) { - return el( serverSideRender, { - block: 'ls-theme/phase-services', - urlQueryArgs: { post_id: props.context ? props.context.postId : undefined }, - } ); - }, - save: function () { - return null; - }, - } ); -} )( window.wp.blocks, window.wp.element, window.wp.serverSideRender ); diff --git a/blocks/phase-services/render.php b/blocks/phase-services/render.php deleted file mode 100644 index 28bf9bc..0000000 --- a/blocks/phase-services/render.php +++ /dev/null @@ -1,213 +0,0 @@ - array( - array( - 'label' => __( 'Discovery', 'ls-theme' ), - 'description' => __( 'Stakeholder workshops, audits, scoping and feasibility — the evidence layer that comes before design or build.', 'ls-theme' ), - 'url' => '/services/discovery/', - 'icon' => 'search', - ), - ), - 'create' => array( - array( - 'label' => __( 'Content', 'ls-theme' ), - 'description' => __( 'Content modelling, editorial workflow and governance that holds up at scale.', 'ls-theme' ), - 'url' => '/services/content/', - 'icon' => 'file-text', - ), - array( - 'label' => __( 'Design', 'ls-theme' ), - 'description' => __( 'Design systems, accessible patterns and Figma→WordPress parity. Already a deeper page.', 'ls-theme' ), - 'url' => '/services/design/', - 'icon' => 'paint-brush', - ), - ), - 'build' => array( - array( - 'label' => __( 'Development', 'ls-theme' ), - 'description' => __( 'Block themes, WooCommerce, integrations and platform refactors built for long-term health.', 'ls-theme' ), - 'url' => '/services/development/', - 'icon' => 'code', - ), - array( - 'label' => __( 'Migrations', 'ls-theme' ), - 'description' => __( 'Audits, mapping and redirects that take legacy platforms apart without losing traction.', 'ls-theme' ), - 'url' => '/services/migrations/', - 'icon' => 'arrows-left-right', - ), - ), - 'launch' => array( - array( - 'label' => __( 'Hosting', 'ls-theme' ), - 'description' => __( 'Managed environments that match the platform, the workflows and the support model around it.', 'ls-theme' ), - 'url' => '/services/hosting/', - 'icon' => 'cloud', - ), - array( - 'label' => __( 'Performance', 'ls-theme' ), - 'description' => __( 'Core Web Vitals, caching, query review and template optimisation against real production data.', 'ls-theme' ), - 'url' => '/services/performance/', - 'icon' => 'gauge', - ), - array( - 'label' => __( 'Security', 'ls-theme' ), - 'description' => __( 'Audits, hardening guidance, monitoring and recovery planning that reduces risk before incidents.', 'ls-theme' ), - 'url' => '/services/security/', - 'icon' => 'shield', - ), - array( - 'label' => __( 'Training', 'ls-theme' ), - 'description' => __( 'Role-specific training and reference materials that move teams from dependency to confidence.', 'ls-theme' ), - 'url' => '/services/training/', - 'icon' => 'graduation-cap', - ), - ), - 'grow' => array( - array( - 'label' => __( 'Support', 'ls-theme' ), - 'description' => __( 'Maintenance, incident response and quiet improvement so platforms keep getting easier to run.', 'ls-theme' ), - 'url' => '/services/support/', - 'icon' => 'lifebuoy', - ), - array( - 'label' => __( 'SEO', 'ls-theme' ), - 'description' => __( 'Technical SEO, internal linking, schema and the publishing discipline that supports visibility.', 'ls-theme' ), - 'url' => '/services/seo/', - 'icon' => 'chart-line-up', - ), - array( - 'label' => __( 'Accessibility', 'ls-theme' ), - 'description' => __( 'Audits, remediation and the semantic structure that helps WCAG 2.2 AA stick over time.', 'ls-theme' ), - 'url' => '/services/accessibility/', - 'icon' => 'wheelchair', - ), - array( - 'label' => __( 'Email marketing', 'ls-theme' ), - 'description' => __( 'Journey planning, consent flows and the connection between email and the WordPress platform behind it.', 'ls-theme' ), - 'url' => '/services/email-marketing/', - 'icon' => 'envelope', - ), - ), - 'evolve' => array( - array( - 'label' => __( 'AI', 'ls-theme' ), - 'description' => __( 'AI-readiness reviews, governance and workflow planning — practical use without messy adoption.', 'ls-theme' ), - 'url' => '/services/ai/', - 'icon' => 'special-interests', - ), - ), -); - -$ls_phase_labels = array( - 'discover' => __( 'Discover', 'ls-theme' ), - 'create' => __( 'Create', 'ls-theme' ), - 'build' => __( 'Build', 'ls-theme' ), - 'launch' => __( 'Launch', 'ls-theme' ), - 'grow' => __( 'Grow', 'ls-theme' ), - 'evolve' => __( 'Evolve', 'ls-theme' ), -); - -$ls_post_id = isset( $block->context['postId'] ) ? (int) $block->context['postId'] : (int) get_the_ID(); -if ( ! $ls_post_id ) { - $ls_post_id = (int) get_queried_object_id(); -} - -$ls_current_phase_slug = ''; -$ls_queried_post = get_post( $ls_post_id ); -if ( $ls_queried_post instanceof WP_Post ) { - $ls_current_phase_slug = $ls_queried_post->post_name; -} - -$ls_active_phase_slug = isset( $ls_phase_services_by_phase[ $ls_current_phase_slug ] ) ? $ls_current_phase_slug : 'discover'; -$ls_active_phase_label = $ls_phase_labels[ $ls_active_phase_slug ]; -$ls_active_services = $ls_phase_services_by_phase[ $ls_active_phase_slug ]; -$ls_service_rows = array_chunk( $ls_active_services, 4 ); -$ls_phase_accent = 'var(--wp--custom--color--phase--' . $ls_active_phase_slug . ')'; - -ob_start(); -?> - -
- -

- - - -

- - - -

- -
- - - $ls_row ) : ?> - -
- - -
- -
- -
- - - -
- -

- - - -
- -

- -
- -
- - - - - -
- - -
- - - - -
- -
- From cf9d5389d8d16e3e0addb413e00933da1edd87b8 Mon Sep 17 00:00:00 2001 From: krugazul Date: Wed, 30 Sep 2026 10:05:02 +0200 Subject: [PATCH 2/5] Registering the new patterns --- CHANGELOG.md | 12 + blocks/phase-services/render.php | 213 ++++++++++++++++++ functions.php | 3 - patterns/sections/phase-services-build.php | 99 ++++++++ patterns/sections/phase-services-create.php | 99 ++++++++ patterns/sections/phase-services-discover.php | 93 ++++++++ patterns/sections/phase-services-evolve.php | 93 ++++++++ patterns/sections/phase-services-grow.php | 111 +++++++++ patterns/sections/phase-services-launch.php | 111 +++++++++ patterns/sections/phase-where-to-go-next.php | 2 +- 10 files changed, 832 insertions(+), 4 deletions(-) create mode 100644 blocks/phase-services/render.php create mode 100644 patterns/sections/phase-services-build.php create mode 100644 patterns/sections/phase-services-create.php create mode 100644 patterns/sections/phase-services-discover.php create mode 100644 patterns/sections/phase-services-evolve.php create mode 100644 patterns/sections/phase-services-grow.php create mode 100644 patterns/sections/phase-services-launch.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ee02330..0104f80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [Unreleased] — Replace the phase-services dynamic block with per-phase patterns (LS-4179) + +### Changed + +- Replaced the `ls-theme/phase-services` dynamic block, which chose its "Services in this phase" cards from the current page slug, with six static patterns you can insert from the editor: `patterns/sections/phase-services-{discover,create,build,launch,grow,evolve}.php` (Section - Phase Services: Discover … Evolve). Each one holds its own phase's heading, service tiles and phase accent colour, so the content no longer depends on which page it's placed on. + +### Removed + +- `blocks/phase-services/`, `inc/blocks.php` (and its `require` in `functions.php`), and `patterns/sections/phase-services-in-phase.php`, the wrapper pattern that only contained the block. + +--- + ## [Unreleased] — Make phase section patterns follow the current phase colour (LS-4179) ### Fixed diff --git a/blocks/phase-services/render.php b/blocks/phase-services/render.php new file mode 100644 index 0000000..b59c98b --- /dev/null +++ b/blocks/phase-services/render.php @@ -0,0 +1,213 @@ + array( + array( + 'label' => __( 'Discovery', 'ls-theme' ), + 'description' => __( 'Stakeholder workshops, audits, scoping and feasibility — the evidence layer that comes before design or build.', 'ls-theme' ), + 'url' => '/services/discovery/', + 'icon' => 'search', + ), + ), + 'create' => array( + array( + 'label' => __( 'Content', 'ls-theme' ), + 'description' => __( 'Content modelling, editorial workflow and governance that holds up at scale.', 'ls-theme' ), + 'url' => '/services/content/', + 'icon' => 'file-text', + ), + array( + 'label' => __( 'Design', 'ls-theme' ), + 'description' => __( 'Design systems, accessible patterns and Figma→WordPress parity. Already a deeper page.', 'ls-theme' ), + 'url' => '/services/design/', + 'icon' => 'paint-brush', + ), + ), + 'build' => array( + array( + 'label' => __( 'Development', 'ls-theme' ), + 'description' => __( 'Block themes, WooCommerce, integrations and platform refactors built for long-term health.', 'ls-theme' ), + 'url' => '/services/development/', + 'icon' => 'code', + ), + array( + 'label' => __( 'Migrations', 'ls-theme' ), + 'description' => __( 'Audits, mapping and redirects that take legacy platforms apart without losing traction.', 'ls-theme' ), + 'url' => '/services/migrations/', + 'icon' => 'arrows-left-right', + ), + ), + 'launch' => array( + array( + 'label' => __( 'Hosting', 'ls-theme' ), + 'description' => __( 'Managed environments that match the platform, the workflows and the support model around it.', 'ls-theme' ), + 'url' => '/services/hosting/', + 'icon' => 'cloud', + ), + array( + 'label' => __( 'Performance', 'ls-theme' ), + 'description' => __( 'Core Web Vitals, caching, query review and template optimisation against real production data.', 'ls-theme' ), + 'url' => '/services/performance/', + 'icon' => 'gauge', + ), + array( + 'label' => __( 'Security', 'ls-theme' ), + 'description' => __( 'Audits, hardening guidance, monitoring and recovery planning that reduces risk before incidents.', 'ls-theme' ), + 'url' => '/services/security/', + 'icon' => 'shield', + ), + array( + 'label' => __( 'Training', 'ls-theme' ), + 'description' => __( 'Role-specific training and reference materials that move teams from dependency to confidence.', 'ls-theme' ), + 'url' => '/services/training/', + 'icon' => 'graduation-cap', + ), + ), + 'grow' => array( + array( + 'label' => __( 'Support', 'ls-theme' ), + 'description' => __( 'Maintenance, incident response and quiet improvement so platforms keep getting easier to run.', 'ls-theme' ), + 'url' => '/services/support/', + 'icon' => 'lifebuoy', + ), + array( + 'label' => __( 'SEO', 'ls-theme' ), + 'description' => __( 'Technical SEO, internal linking, schema and the publishing discipline that supports visibility.', 'ls-theme' ), + 'url' => '/services/seo/', + 'icon' => 'chart-line-up', + ), + array( + 'label' => __( 'Accessibility', 'ls-theme' ), + 'description' => __( 'Audits, remediation and the semantic structure that helps WCAG 2.2 AA stick over time.', 'ls-theme' ), + 'url' => '/services/accessibility/', + 'icon' => 'wheelchair', + ), + array( + 'label' => __( 'Email marketing', 'ls-theme' ), + 'description' => __( 'Journey planning, consent flows and the connection between email and the WordPress platform behind it.', 'ls-theme' ), + 'url' => '/services/email-marketing/', + 'icon' => 'envelope', + ), + ), + 'evolve' => array( + array( + 'label' => __( 'AI', 'ls-theme' ), + 'description' => __( 'AI-readiness reviews, governance and workflow planning — practical use without messy adoption.', 'ls-theme' ), + 'url' => '/services/ai/', + 'icon' => 'special-interests', + ), + ), +); + +$ls_phase_labels = array( + 'discover' => __( 'Discover', 'ls-theme' ), + 'create' => __( 'Create', 'ls-theme' ), + 'build' => __( 'Build', 'ls-theme' ), + 'launch' => __( 'Launch', 'ls-theme' ), + 'grow' => __( 'Grow', 'ls-theme' ), + 'evolve' => __( 'Evolve', 'ls-theme' ), +); + +$ls_post_id = isset( $block->context['postId'] ) ? (int) $block->context['postId'] : (int) get_the_ID(); +if ( ! $ls_post_id ) { + $ls_post_id = (int) get_queried_object_id(); +} + +$ls_current_phase_slug = ''; +$ls_queried_post = get_post( $ls_post_id ); +if ( $ls_queried_post instanceof WP_Post ) { + $ls_current_phase_slug = $ls_queried_post->post_name; +} + +$ls_active_phase_slug = isset( $ls_phase_services_by_phase[ $ls_current_phase_slug ] ) ? $ls_current_phase_slug : 'discover'; +$ls_active_phase_label = $ls_phase_labels[ $ls_active_phase_slug ]; +$ls_active_services = $ls_phase_services_by_phase[ $ls_active_phase_slug ]; +$ls_service_rows = array_chunk( $ls_active_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--' . $ls_active_phase_slug . ')'; + +ob_start(); +?> + +
+ +

+ + + +

+ + + +

+ +
+ + + $ls_row ) : ?> + +
+ + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + __( 'Development', 'ls-theme' ), + 'description' => __( 'Block themes, WooCommerce, integrations and platform refactors built for long-term health.', 'ls-theme' ), + 'url' => '/services/development/', + 'icon' => 'code', + ), + array( + 'label' => __( 'Migrations', 'ls-theme' ), + 'description' => __( 'Audits, mapping and redirects that take legacy platforms apart without losing traction.', 'ls-theme' ), + 'url' => '/services/migrations/', + 'icon' => 'arrows-left-right', + ), +); + +$ls_service_rows = array_chunk( $ls_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--build)'; +?> + +
+ + +
+ +

+ + + +

+ + + +

+ +
+ + $ls_row ) : ?> + + +
+ + + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + +
+ diff --git a/patterns/sections/phase-services-create.php b/patterns/sections/phase-services-create.php new file mode 100644 index 0000000..5d7bd2f --- /dev/null +++ b/patterns/sections/phase-services-create.php @@ -0,0 +1,99 @@ + __( 'Content', 'ls-theme' ), + 'description' => __( 'Content modelling, editorial workflow and governance that holds up at scale.', 'ls-theme' ), + 'url' => '/services/content/', + 'icon' => 'file-text', + ), + array( + 'label' => __( 'Design', 'ls-theme' ), + 'description' => __( 'Design systems, accessible patterns and Figma→WordPress parity. Already a deeper page.', 'ls-theme' ), + 'url' => '/services/design/', + 'icon' => 'paint-brush', + ), +); + +$ls_service_rows = array_chunk( $ls_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--create)'; +?> + +
+ + +
+ +

+ + + +

+ + + +

+ +
+ + $ls_row ) : ?> + + +
+ + + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + +
+ diff --git a/patterns/sections/phase-services-discover.php b/patterns/sections/phase-services-discover.php new file mode 100644 index 0000000..3091390 --- /dev/null +++ b/patterns/sections/phase-services-discover.php @@ -0,0 +1,93 @@ + __( 'Discovery', 'ls-theme' ), + 'description' => __( 'Stakeholder workshops, audits, scoping and feasibility — the evidence layer that comes before design or build.', 'ls-theme' ), + 'url' => '/services/discovery/', + 'icon' => 'search', + ), +); + +$ls_service_rows = array_chunk( $ls_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--discover)'; +?> + +
+ + +
+ +

+ + + +

+ + + +

+ +
+ + $ls_row ) : ?> + + +
+ + + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + +
+ diff --git a/patterns/sections/phase-services-evolve.php b/patterns/sections/phase-services-evolve.php new file mode 100644 index 0000000..fdc650f --- /dev/null +++ b/patterns/sections/phase-services-evolve.php @@ -0,0 +1,93 @@ + __( 'AI', 'ls-theme' ), + 'description' => __( 'AI-readiness reviews, governance and workflow planning — practical use without messy adoption.', 'ls-theme' ), + 'url' => '/services/ai/', + 'icon' => 'special-interests', + ), +); + +$ls_service_rows = array_chunk( $ls_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--evolve)'; +?> + +
+ + +
+ +

+ + + +

+ + + +

+ +
+ + $ls_row ) : ?> + + +
+ + + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + +
+ diff --git a/patterns/sections/phase-services-grow.php b/patterns/sections/phase-services-grow.php new file mode 100644 index 0000000..3d46d6a --- /dev/null +++ b/patterns/sections/phase-services-grow.php @@ -0,0 +1,111 @@ + __( 'Support', 'ls-theme' ), + 'description' => __( 'Maintenance, incident response and quiet improvement so platforms keep getting easier to run.', 'ls-theme' ), + 'url' => '/services/support/', + 'icon' => 'lifebuoy', + ), + array( + 'label' => __( 'SEO', 'ls-theme' ), + 'description' => __( 'Technical SEO, internal linking, schema and the publishing discipline that supports visibility.', 'ls-theme' ), + 'url' => '/services/seo/', + 'icon' => 'chart-line-up', + ), + array( + 'label' => __( 'Accessibility', 'ls-theme' ), + 'description' => __( 'Audits, remediation and the semantic structure that helps WCAG 2.2 AA stick over time.', 'ls-theme' ), + 'url' => '/services/accessibility/', + 'icon' => 'wheelchair', + ), + array( + 'label' => __( 'Email marketing', 'ls-theme' ), + 'description' => __( 'Journey planning, consent flows and the connection between email and the WordPress platform behind it.', 'ls-theme' ), + 'url' => '/services/email-marketing/', + 'icon' => 'envelope', + ), +); + +$ls_service_rows = array_chunk( $ls_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--grow)'; +?> + +
+ + +
+ +

+ + + +

+ + + +

+ +
+ + $ls_row ) : ?> + + +
+ + + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + +
+ diff --git a/patterns/sections/phase-services-launch.php b/patterns/sections/phase-services-launch.php new file mode 100644 index 0000000..30d9a75 --- /dev/null +++ b/patterns/sections/phase-services-launch.php @@ -0,0 +1,111 @@ + __( 'Hosting', 'ls-theme' ), + 'description' => __( 'Managed environments that match the platform, the workflows and the support model around it.', 'ls-theme' ), + 'url' => '/services/hosting/', + 'icon' => 'cloud', + ), + array( + 'label' => __( 'Performance', 'ls-theme' ), + 'description' => __( 'Core Web Vitals, caching, query review and template optimisation against real production data.', 'ls-theme' ), + 'url' => '/services/performance/', + 'icon' => 'gauge', + ), + array( + 'label' => __( 'Security', 'ls-theme' ), + 'description' => __( 'Audits, hardening guidance, monitoring and recovery planning that reduces risk before incidents.', 'ls-theme' ), + 'url' => '/services/security/', + 'icon' => 'shield', + ), + array( + 'label' => __( 'Training', 'ls-theme' ), + 'description' => __( 'Role-specific training and reference materials that move teams from dependency to confidence.', 'ls-theme' ), + 'url' => '/services/training/', + 'icon' => 'graduation-cap', + ), +); + +$ls_service_rows = array_chunk( $ls_services, 4 ); +$ls_phase_accent = 'var(--wp--custom--color--phase--launch)'; +?> + +
+ + +
+ +

+ + + +

+ + + +

+ +
+ + $ls_row ) : ?> + + +
+ + + +
+ +
+ +
+ + + +
+ +

+ + + +
+ +

+ +
+ +
+ + + + + +
+ + +
+ + + +
+ diff --git a/patterns/sections/phase-where-to-go-next.php b/patterns/sections/phase-where-to-go-next.php index 6d55e87..115e23f 100644 --- a/patterns/sections/phase-where-to-go-next.php +++ b/patterns/sections/phase-where-to-go-next.php @@ -9,7 +9,7 @@ * Our Process overview); the eyebrow and card content still need to be pulled out per-page before * this is reused on the other five pages. Two equal-width cards reusing the existing * Card - Link Row style and Link Arrow Accent paragraph style (same "Explore service"/"Read more" - * convention used in phase-services-in-phase.php), rather than the source design's 4-column grid, + * convention used in the phase-services-{phase}.php patterns), rather than the source design's 4-column grid, * which only ever renders two cards. Adapts between the site's light and dark style variations via * text tokens; the phase accent uses the plain phase.{slug} token, same reasoning as * phase-support-focus.php and phase-common-services.php. From faa6a4d3afa86c263ac4604e34b7ff935ad94b45 Mon Sep 17 00:00:00 2001 From: krugazul Date: Wed, 30 Sep 2026 10:25:55 +0200 Subject: [PATCH 3/5] Remove orphaned phase-services render.php block.json, index.js and the inc/blocks.php registration were already removed, leaving render.php unreachable (and carrying a debug "test" class). Completes the blocks/phase-services/ removal. Co-Authored-By: Claude Opus 5.5 --- blocks/phase-services/render.php | 213 ------------------------------- 1 file changed, 213 deletions(-) delete mode 100644 blocks/phase-services/render.php diff --git a/blocks/phase-services/render.php b/blocks/phase-services/render.php deleted file mode 100644 index b59c98b..0000000 --- a/blocks/phase-services/render.php +++ /dev/null @@ -1,213 +0,0 @@ - array( - array( - 'label' => __( 'Discovery', 'ls-theme' ), - 'description' => __( 'Stakeholder workshops, audits, scoping and feasibility — the evidence layer that comes before design or build.', 'ls-theme' ), - 'url' => '/services/discovery/', - 'icon' => 'search', - ), - ), - 'create' => array( - array( - 'label' => __( 'Content', 'ls-theme' ), - 'description' => __( 'Content modelling, editorial workflow and governance that holds up at scale.', 'ls-theme' ), - 'url' => '/services/content/', - 'icon' => 'file-text', - ), - array( - 'label' => __( 'Design', 'ls-theme' ), - 'description' => __( 'Design systems, accessible patterns and Figma→WordPress parity. Already a deeper page.', 'ls-theme' ), - 'url' => '/services/design/', - 'icon' => 'paint-brush', - ), - ), - 'build' => array( - array( - 'label' => __( 'Development', 'ls-theme' ), - 'description' => __( 'Block themes, WooCommerce, integrations and platform refactors built for long-term health.', 'ls-theme' ), - 'url' => '/services/development/', - 'icon' => 'code', - ), - array( - 'label' => __( 'Migrations', 'ls-theme' ), - 'description' => __( 'Audits, mapping and redirects that take legacy platforms apart without losing traction.', 'ls-theme' ), - 'url' => '/services/migrations/', - 'icon' => 'arrows-left-right', - ), - ), - 'launch' => array( - array( - 'label' => __( 'Hosting', 'ls-theme' ), - 'description' => __( 'Managed environments that match the platform, the workflows and the support model around it.', 'ls-theme' ), - 'url' => '/services/hosting/', - 'icon' => 'cloud', - ), - array( - 'label' => __( 'Performance', 'ls-theme' ), - 'description' => __( 'Core Web Vitals, caching, query review and template optimisation against real production data.', 'ls-theme' ), - 'url' => '/services/performance/', - 'icon' => 'gauge', - ), - array( - 'label' => __( 'Security', 'ls-theme' ), - 'description' => __( 'Audits, hardening guidance, monitoring and recovery planning that reduces risk before incidents.', 'ls-theme' ), - 'url' => '/services/security/', - 'icon' => 'shield', - ), - array( - 'label' => __( 'Training', 'ls-theme' ), - 'description' => __( 'Role-specific training and reference materials that move teams from dependency to confidence.', 'ls-theme' ), - 'url' => '/services/training/', - 'icon' => 'graduation-cap', - ), - ), - 'grow' => array( - array( - 'label' => __( 'Support', 'ls-theme' ), - 'description' => __( 'Maintenance, incident response and quiet improvement so platforms keep getting easier to run.', 'ls-theme' ), - 'url' => '/services/support/', - 'icon' => 'lifebuoy', - ), - array( - 'label' => __( 'SEO', 'ls-theme' ), - 'description' => __( 'Technical SEO, internal linking, schema and the publishing discipline that supports visibility.', 'ls-theme' ), - 'url' => '/services/seo/', - 'icon' => 'chart-line-up', - ), - array( - 'label' => __( 'Accessibility', 'ls-theme' ), - 'description' => __( 'Audits, remediation and the semantic structure that helps WCAG 2.2 AA stick over time.', 'ls-theme' ), - 'url' => '/services/accessibility/', - 'icon' => 'wheelchair', - ), - array( - 'label' => __( 'Email marketing', 'ls-theme' ), - 'description' => __( 'Journey planning, consent flows and the connection between email and the WordPress platform behind it.', 'ls-theme' ), - 'url' => '/services/email-marketing/', - 'icon' => 'envelope', - ), - ), - 'evolve' => array( - array( - 'label' => __( 'AI', 'ls-theme' ), - 'description' => __( 'AI-readiness reviews, governance and workflow planning — practical use without messy adoption.', 'ls-theme' ), - 'url' => '/services/ai/', - 'icon' => 'special-interests', - ), - ), -); - -$ls_phase_labels = array( - 'discover' => __( 'Discover', 'ls-theme' ), - 'create' => __( 'Create', 'ls-theme' ), - 'build' => __( 'Build', 'ls-theme' ), - 'launch' => __( 'Launch', 'ls-theme' ), - 'grow' => __( 'Grow', 'ls-theme' ), - 'evolve' => __( 'Evolve', 'ls-theme' ), -); - -$ls_post_id = isset( $block->context['postId'] ) ? (int) $block->context['postId'] : (int) get_the_ID(); -if ( ! $ls_post_id ) { - $ls_post_id = (int) get_queried_object_id(); -} - -$ls_current_phase_slug = ''; -$ls_queried_post = get_post( $ls_post_id ); -if ( $ls_queried_post instanceof WP_Post ) { - $ls_current_phase_slug = $ls_queried_post->post_name; -} - -$ls_active_phase_slug = isset( $ls_phase_services_by_phase[ $ls_current_phase_slug ] ) ? $ls_current_phase_slug : 'discover'; -$ls_active_phase_label = $ls_phase_labels[ $ls_active_phase_slug ]; -$ls_active_services = $ls_phase_services_by_phase[ $ls_active_phase_slug ]; -$ls_service_rows = array_chunk( $ls_active_services, 4 ); -$ls_phase_accent = 'var(--wp--custom--color--phase--' . $ls_active_phase_slug . ')'; - -ob_start(); -?> - -
- -

- - - -

- - - -

- -
- - - $ls_row ) : ?> - -
- - -
- -
- -
- - - -
- -

- - - -
- -

- -
- -
- - - - - -
- - -
- - - Date: Wed, 30 Sep 2026 10:26:32 +0200 Subject: [PATCH 4/5] Link CHANGELOG entry to PR #76 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0104f80..23e6104 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `blocks/phase-services/`, `inc/blocks.php` (and its `require` in `functions.php`), and `patterns/sections/phase-services-in-phase.php`, the wrapper pattern that only contained the block. +([#76](https://github.com/lightspeedwp/ls-theme/pull/76)) + --- ## [Unreleased] — Make phase section patterns follow the current phase colour (LS-4179) From cdbc6e6705ba4a81fb7ee3ea59969f95f2e989a4 Mon Sep 17 00:00:00 2001 From: Brandonma21 Date: Wed, 30 Sep 2026 15:30:46 +0200 Subject: [PATCH 5/5] Put phase-services pattern Description headers on one line Fix - WordPress reads each pattern header from a single line, so the wrapped Description was cut off mid-sentence in the inserter - Replace it with one short description per pattern (Discover, Create, Build, Launch, Grow, Evolve) - Move the implementation notes into a // comment below the header so nothing is lost Review - Addresses CodeRabbit comment on PR #76 - Skipped the CHANGELOG issue-key comment: LS-4179 and LSA-132 are the same ticket and the changelog uses LS-4179 --- patterns/sections/phase-services-build.php | 16 ++++++++-------- patterns/sections/phase-services-create.php | 16 ++++++++-------- patterns/sections/phase-services-discover.php | 16 ++++++++-------- patterns/sections/phase-services-evolve.php | 16 ++++++++-------- patterns/sections/phase-services-grow.php | 16 ++++++++-------- patterns/sections/phase-services-launch.php | 16 ++++++++-------- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/patterns/sections/phase-services-build.php b/patterns/sections/phase-services-build.php index 81de864..cda1748 100644 --- a/patterns/sections/phase-services-build.php +++ b/patterns/sections/phase-services-build.php @@ -4,14 +4,7 @@ * Slug: ls-theme/phase-services-build * Categories: featured * Block Types: core/pattern - * Description: "Services in the Build phase" section for the Build lifecycle phase page — a - * centred eyebrow/heading/intro and a wrapped row of service tiles. One of six static per-phase - * patterns (phase-services-discover.php … phase-services-evolve.php) that replace the former - * ls-theme/phase-services dynamic block: each pattern hardcodes its own phase, so its content is - * fixed once inserted and stays correct whether or not the pattern is later flattened. Service - * labels, descriptions, URLs and icons are kept in sync with the master list in - * services-service-tiles.php. The phase accent uses the plain phase.build token, which already - * resolves to the correct light/dark value for this adaptive surface. + * Description: "Services in the Build phase" section for the Build lifecycle phase page: a centred eyebrow, heading and intro above a row of service tiles. * Keywords: phase, build, services, cards, section * Viewport Width: 1280 * Inserter: true @@ -19,6 +12,13 @@ * @package ls-theme */ +// One of six static per-phase patterns (phase-services-discover.php … phase-services-evolve.php) +// that replace the former ls-theme/phase-services dynamic block: each pattern hardcodes its own +// phase, so its content is fixed once inserted and stays correct whether or not the pattern is +// later flattened. Service labels, descriptions, URLs and icons are kept in sync with the master +// list in services-service-tiles.php. The phase accent uses the plain phase.build token, which +// already resolves to the correct light/dark value for this adaptive surface. + $ls_services = array( array( 'label' => __( 'Development', 'ls-theme' ), diff --git a/patterns/sections/phase-services-create.php b/patterns/sections/phase-services-create.php index 5d7bd2f..af2a02e 100644 --- a/patterns/sections/phase-services-create.php +++ b/patterns/sections/phase-services-create.php @@ -4,14 +4,7 @@ * Slug: ls-theme/phase-services-create * Categories: featured * Block Types: core/pattern - * Description: "Services in the Create phase" section for the Create lifecycle phase page — a - * centred eyebrow/heading/intro and a wrapped row of service tiles. One of six static per-phase - * patterns (phase-services-discover.php … phase-services-evolve.php) that replace the former - * ls-theme/phase-services dynamic block: each pattern hardcodes its own phase, so its content is - * fixed once inserted and stays correct whether or not the pattern is later flattened. Service - * labels, descriptions, URLs and icons are kept in sync with the master list in - * services-service-tiles.php. The phase accent uses the plain phase.create token, which already - * resolves to the correct light/dark value for this adaptive surface. + * Description: "Services in the Create phase" section for the Create lifecycle phase page: a centred eyebrow, heading and intro above a row of service tiles. * Keywords: phase, create, services, cards, section * Viewport Width: 1280 * Inserter: true @@ -19,6 +12,13 @@ * @package ls-theme */ +// One of six static per-phase patterns (phase-services-discover.php … phase-services-evolve.php) +// that replace the former ls-theme/phase-services dynamic block: each pattern hardcodes its own +// phase, so its content is fixed once inserted and stays correct whether or not the pattern is +// later flattened. Service labels, descriptions, URLs and icons are kept in sync with the master +// list in services-service-tiles.php. The phase accent uses the plain phase.create token, which +// already resolves to the correct light/dark value for this adaptive surface. + $ls_services = array( array( 'label' => __( 'Content', 'ls-theme' ), diff --git a/patterns/sections/phase-services-discover.php b/patterns/sections/phase-services-discover.php index 3091390..54b7f6f 100644 --- a/patterns/sections/phase-services-discover.php +++ b/patterns/sections/phase-services-discover.php @@ -4,14 +4,7 @@ * Slug: ls-theme/phase-services-discover * Categories: featured * Block Types: core/pattern - * Description: "Services in the Discover phase" section for the Discover lifecycle phase page — a - * centred eyebrow/heading/intro and a wrapped row of service tiles. One of six static per-phase - * patterns (phase-services-discover.php … phase-services-evolve.php) that replace the former - * ls-theme/phase-services dynamic block: each pattern hardcodes its own phase, so its content is - * fixed once inserted and stays correct whether or not the pattern is later flattened. Service - * labels, descriptions, URLs and icons are kept in sync with the master list in - * services-service-tiles.php. The phase accent uses the plain phase.discover token, which already - * resolves to the correct light/dark value for this adaptive surface. + * Description: "Services in the Discover phase" section for the Discover lifecycle phase page: a centred eyebrow, heading and intro above a row of service tiles. * Keywords: phase, discover, services, cards, section * Viewport Width: 1280 * Inserter: true @@ -19,6 +12,13 @@ * @package ls-theme */ +// One of six static per-phase patterns (phase-services-discover.php … phase-services-evolve.php) +// that replace the former ls-theme/phase-services dynamic block: each pattern hardcodes its own +// phase, so its content is fixed once inserted and stays correct whether or not the pattern is +// later flattened. Service labels, descriptions, URLs and icons are kept in sync with the master +// list in services-service-tiles.php. The phase accent uses the plain phase.discover token, which +// already resolves to the correct light/dark value for this adaptive surface. + $ls_services = array( array( 'label' => __( 'Discovery', 'ls-theme' ), diff --git a/patterns/sections/phase-services-evolve.php b/patterns/sections/phase-services-evolve.php index fdc650f..d22ed7e 100644 --- a/patterns/sections/phase-services-evolve.php +++ b/patterns/sections/phase-services-evolve.php @@ -4,14 +4,7 @@ * Slug: ls-theme/phase-services-evolve * Categories: featured * Block Types: core/pattern - * Description: "Services in the Evolve phase" section for the Evolve lifecycle phase page — a - * centred eyebrow/heading/intro and a wrapped row of service tiles. One of six static per-phase - * patterns (phase-services-discover.php … phase-services-evolve.php) that replace the former - * ls-theme/phase-services dynamic block: each pattern hardcodes its own phase, so its content is - * fixed once inserted and stays correct whether or not the pattern is later flattened. Service - * labels, descriptions, URLs and icons are kept in sync with the master list in - * services-service-tiles.php. The phase accent uses the plain phase.evolve token, which already - * resolves to the correct light/dark value for this adaptive surface. + * Description: "Services in the Evolve phase" section for the Evolve lifecycle phase page: a centred eyebrow, heading and intro above a row of service tiles. * Keywords: phase, evolve, services, cards, section * Viewport Width: 1280 * Inserter: true @@ -19,6 +12,13 @@ * @package ls-theme */ +// One of six static per-phase patterns (phase-services-discover.php … phase-services-evolve.php) +// that replace the former ls-theme/phase-services dynamic block: each pattern hardcodes its own +// phase, so its content is fixed once inserted and stays correct whether or not the pattern is +// later flattened. Service labels, descriptions, URLs and icons are kept in sync with the master +// list in services-service-tiles.php. The phase accent uses the plain phase.evolve token, which +// already resolves to the correct light/dark value for this adaptive surface. + $ls_services = array( array( 'label' => __( 'AI', 'ls-theme' ), diff --git a/patterns/sections/phase-services-grow.php b/patterns/sections/phase-services-grow.php index 3d46d6a..7c7d08c 100644 --- a/patterns/sections/phase-services-grow.php +++ b/patterns/sections/phase-services-grow.php @@ -4,14 +4,7 @@ * Slug: ls-theme/phase-services-grow * Categories: featured * Block Types: core/pattern - * Description: "Services in the Grow phase" section for the Grow lifecycle phase page — a - * centred eyebrow/heading/intro and a wrapped row of service tiles. One of six static per-phase - * patterns (phase-services-discover.php … phase-services-evolve.php) that replace the former - * ls-theme/phase-services dynamic block: each pattern hardcodes its own phase, so its content is - * fixed once inserted and stays correct whether or not the pattern is later flattened. Service - * labels, descriptions, URLs and icons are kept in sync with the master list in - * services-service-tiles.php. The phase accent uses the plain phase.grow token, which already - * resolves to the correct light/dark value for this adaptive surface. + * Description: "Services in the Grow phase" section for the Grow lifecycle phase page: a centred eyebrow, heading and intro above a row of service tiles. * Keywords: phase, grow, services, cards, section * Viewport Width: 1280 * Inserter: true @@ -19,6 +12,13 @@ * @package ls-theme */ +// One of six static per-phase patterns (phase-services-discover.php … phase-services-evolve.php) +// that replace the former ls-theme/phase-services dynamic block: each pattern hardcodes its own +// phase, so its content is fixed once inserted and stays correct whether or not the pattern is +// later flattened. Service labels, descriptions, URLs and icons are kept in sync with the master +// list in services-service-tiles.php. The phase accent uses the plain phase.grow token, which +// already resolves to the correct light/dark value for this adaptive surface. + $ls_services = array( array( 'label' => __( 'Support', 'ls-theme' ), diff --git a/patterns/sections/phase-services-launch.php b/patterns/sections/phase-services-launch.php index 30d9a75..e8ee687 100644 --- a/patterns/sections/phase-services-launch.php +++ b/patterns/sections/phase-services-launch.php @@ -4,14 +4,7 @@ * Slug: ls-theme/phase-services-launch * Categories: featured * Block Types: core/pattern - * Description: "Services in the Launch phase" section for the Launch lifecycle phase page — a - * centred eyebrow/heading/intro and a wrapped row of service tiles. One of six static per-phase - * patterns (phase-services-discover.php … phase-services-evolve.php) that replace the former - * ls-theme/phase-services dynamic block: each pattern hardcodes its own phase, so its content is - * fixed once inserted and stays correct whether or not the pattern is later flattened. Service - * labels, descriptions, URLs and icons are kept in sync with the master list in - * services-service-tiles.php. The phase accent uses the plain phase.launch token, which already - * resolves to the correct light/dark value for this adaptive surface. + * Description: "Services in the Launch phase" section for the Launch lifecycle phase page: a centred eyebrow, heading and intro above a row of service tiles. * Keywords: phase, launch, services, cards, section * Viewport Width: 1280 * Inserter: true @@ -19,6 +12,13 @@ * @package ls-theme */ +// One of six static per-phase patterns (phase-services-discover.php … phase-services-evolve.php) +// that replace the former ls-theme/phase-services dynamic block: each pattern hardcodes its own +// phase, so its content is fixed once inserted and stays correct whether or not the pattern is +// later flattened. Service labels, descriptions, URLs and icons are kept in sync with the master +// list in services-service-tiles.php. The phase accent uses the plain phase.launch token, which +// already resolves to the correct light/dark value for this adaptive surface. + $ls_services = array( array( 'label' => __( 'Hosting', 'ls-theme' ),