diff --git a/components/breadcrumbs.js b/components/breadcrumbs.js
index 47ccd1e4..92a51c49 100644
--- a/components/breadcrumbs.js
+++ b/components/breadcrumbs.js
@@ -121,6 +121,13 @@ const Breadcrumbs = (props) => {
);
+ const renderMyPortalSectionCrumbs = (sectionLabel) => (
+ <>
+ {renderMyPortalCrumb()}
+ {renderTextCrumb(sectionLabel)}
+ >
+ );
+
const renderCaseReferenceCrumb = (referenceValue) => (
{t("common:breadcrumb-case-reference")}: {referenceValue}
@@ -165,6 +172,18 @@ const Breadcrumbs = (props) => {
listItemClass = "govuk-breadcrumbs__link-item backChevron"
) => renderAnchorCrumb("#", t("common:back-link"), onClick, listItemClass);
+ const renderDnsCaseReferenceCrumbs = (referenceValue) => (
+ <>
+ {renderLinkCrumb(
+ isWelsh
+ ? router.locale + "/dnsapplications"
+ : "/dnsapplications",
+ t("dnsCommon:service-name")
+ )}
+ {renderCaseReferenceCrumb(referenceValue)}
+ >
+ );
+
const { breadcrumbHref, caseResultsHref, breadcrumbLabel } =
resolveCaseBreadcrumbState({
query: router.query,
@@ -226,30 +245,18 @@ const Breadcrumbs = (props) => {
)}
>
)}
- {isPath("/myportal/addresssearch") && (
- <>
- {renderMyPortalCrumb()}
- {renderTextCrumb(
- t("common:breadcrumb-address-search")
- )}
- >
- )}
- {isPath("/myportal/advancedsearch") && (
- <>
- {renderMyPortalCrumb()}
- {renderTextCrumb(
- t("common:breadcrumb-advanced-search")
- )}
- >
- )}
- {isPath("/myportal/contactus") && (
- <>
- {renderMyPortalCrumb()}
- {renderTextCrumb(
- t("common:footer-contact-us-link-label")
- )}
- >
- )}
+ {isPath("/myportal/addresssearch") &&
+ renderMyPortalSectionCrumbs(
+ t("common:breadcrumb-address-search")
+ )}
+ {isPath("/myportal/advancedsearch") &&
+ renderMyPortalSectionCrumbs(
+ t("common:breadcrumb-advanced-search")
+ )}
+ {isPath("/myportal/contactus") &&
+ renderMyPortalSectionCrumbs(
+ t("common:footer-contact-us-link-label")
+ )}
{isPath("/contactus") && (
<>
{renderTextCrumb(
@@ -586,28 +593,10 @@ const Breadcrumbs = (props) => {
>
)}
- {isPath("/dnsdetails") && (
- <>
- {renderLinkCrumb(
- isWelsh
- ? router.locale + "/dnsapplications"
- : "/dnsapplications",
- t("dnsCommon:service-name")
- )}
- {renderCaseReferenceCrumb(currentReference)}
- >
- )}
- {isPath("/dns/[developmentName]") && (
- <>
- {renderLinkCrumb(
- isWelsh
- ? router.locale + "/dnsapplications"
- : "/dnsapplications",
- t("dnsCommon:service-name")
- )}
- {renderCaseReferenceCrumb(caseReferenceDisplay)}
- >
- )}
+ {isPath("/dnsdetails") &&
+ renderDnsCaseReferenceCrumbs(currentReference)}
+ {isPath("/dns/[developmentName]") &&
+ renderDnsCaseReferenceCrumbs(caseReferenceDisplay)}
{isPath("/dns/application-view") && (
<>
{renderLinkCrumb(
diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md
index 61b80235..bfd6019b 100644
--- a/memory-bank/change-log.md
+++ b/memory-bank/change-log.md
@@ -305,6 +305,34 @@ Follow-ups:
- Next slice recommendation: extract a small grouped helper for recurring two-crumb route pairs (e.g., my-portal + section label, dns list + case reference) to reduce the remaining conditional chain while preserving explicit route behavior.
+### CL-22541-K: breadcrumbs grouped two-crumb helper extraction
+
+date: 2026-04-09
+author: Cline
+scope: `components/breadcrumbs.js`
+type: change
+rationale: Continue the same bounded refactor cadence by extracting recurring two-crumb patterns into small grouped helpers while preserving explicit route branches.
+impact: Refactor-only readability/deduplication improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
+status: completed
+
+Summary:
+
+- Added grouped helper `renderMyPortalSectionCrumbs(sectionLabel)` for recurring my-portal + section text pairs.
+- Added grouped helper `renderDnsCaseReferenceCrumbs(referenceValue)` for recurring DNS applications link + case-reference pairs.
+- Replaced duplicated route branches with grouped helper usage for:
+ - `/myportal/addresssearch`, `/myportal/advancedsearch`, `/myportal/contactus`
+ - `/dnsdetails`, `/dns/[developmentName]`
+- Preserved existing href behavior (including EN/CY DNS applications link), labels, and case-reference rendering.
+
+Validation:
+
+- `npx eslint components/breadcrumbs.js` -> pass.
+- `node tests/phase22/index.test.cjs` -> pass (combined suite).
+
+Follow-ups:
+
+- Next slice recommendation: extract a small route-to-renderer map for static single-branch crumbs (where branch has no bespoke side-effects) so the main JSX conditional chain shrinks further without altering explicit behavior in dynamic/sensitive branches.
+
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
date: 2026-04-07