diff --git a/components/breadcrumbs.js b/components/breadcrumbs.js
index 7ea706bd..4ba0a75f 100644
--- a/components/breadcrumbs.js
+++ b/components/breadcrumbs.js
@@ -106,6 +106,22 @@ const Breadcrumbs = (props) => {
);
+ const renderTextCrumb = (label) => (
+
{label}
+ );
+
+ const renderLinkCrumb = (href, label, onClick) => (
+
+
+ {label}
+
+
+ );
+
const { breadcrumbHref, caseResultsHref, breadcrumbLabel } =
resolveCaseBreadcrumbState({
query: router.query,
@@ -157,147 +173,121 @@ const Breadcrumbs = (props) => {
)}
{isPath("/searchresults") && (
<>
-
- {t("common:breadcrumb-search-results")}
-
+ {renderTextCrumb(
+ t("common:breadcrumb-search-results")
+ )}
>
)}
{isPath("/advancedsearch") && (
<>
-
- {t("common:breadcrumb-advanced-search")}
-
+ {renderTextCrumb(
+ t("common:breadcrumb-advanced-search")
+ )}
>
)}
{isPath("/addresssearch") && (
<>
-
- {t("common:breadcrumb-address-search")}
-
+ {renderTextCrumb(
+ t("common:breadcrumb-address-search")
+ )}
>
)}
{isPath("/myportal/addresssearch") && (
<>
{renderMyPortalCrumb()}
-
- {t("common:breadcrumb-address-search")}
-
+ {renderTextCrumb(
+ t("common:breadcrumb-address-search")
+ )}
>
)}
{isPath("/myportal/advancedsearch") && (
<>
{renderMyPortalCrumb()}
-
- {t("common:breadcrumb-advanced-search")}
-
+ {renderTextCrumb(
+ t("common:breadcrumb-advanced-search")
+ )}
>
)}
{isPath("/myportal/contactus") && (
<>
{renderMyPortalCrumb()}
-
- {t("common:footer-contact-us-link-label")}
-
+ {renderTextCrumb(
+ t("common:footer-contact-us-link-label")
+ )}
>
)}
{isPath("/contactus") && (
<>
-
- {t("common:footer-contact-us-link-label")}
-
+ {renderTextCrumb(
+ t("common:footer-contact-us-link-label")
+ )}
>
)}
{isPath("/addresssearchresults") && (
<>
{" "}
-
-
- {t("common:breadcrumb-address-search")}
-
-
-
- {t(
+ {renderLinkCrumb(
+ isWelsh
+ ? router.locale + "/chwiliadcyfeiriadau"
+ : "/addresssearch",
+ t("common:breadcrumb-address-search")
+ )}
+ {renderTextCrumb(
+ t(
"common:breadcrumb-address-search-results"
- )}
-
+ )
+ )}
>
)}
{isPath("/advancedsearchresults") && (
<>
{" "}
-
-
- {t("common:breadcrumb-advanced-search")}
-
-
-
- {t(
+ {renderLinkCrumb(
+ isWelsh
+ ? router.locale + "/advancedsearch"
+ : "/advancedsearch",
+ t("common:breadcrumb-advanced-search")
+ )}
+ {renderTextCrumb(
+ t(
"common:breadcrumb-advanced-search-results"
- )}
-
+ )
+ )}
>
)}
{isPath("/myportal/advancedsearchresults") && (
<>
{renderMyPortalCrumb()}
-
-
- {t("common:breadcrumb-advanced-search")}
-
-
-
- {t(
+ {renderLinkCrumb(
+ isWelsh
+ ? router.locale +
+ "/myportal/advancedsearch"
+ : "/myportal/advancedsearch",
+ t("common:breadcrumb-advanced-search")
+ )}
+ {renderTextCrumb(
+ t(
"common:breadcrumb-advanced-search-results"
- )}
-
+ )
+ )}
>
)}
{isPath("/myportal/addresssearchresults") && (
<>
{renderMyPortalCrumb()}
-
-
- {t("common:breadcrumb-address-search")}
-
-
-
- {t(
+ {renderLinkCrumb(
+ isWelsh
+ ? "/" +
+ router.locale +
+ "/fymhorth/chwiliadcyfeiriadau"
+ : "/myportal/addresssearch",
+ t("common:breadcrumb-address-search")
+ )}
+ {renderTextCrumb(
+ t(
"common:breadcrumb-address-search-results"
- )}
-
+ )
+ )}
>
)}
{isPath("/newappeal") && <>>}
@@ -393,9 +383,9 @@ const Breadcrumbs = (props) => {
{isPath("/viewall") && (
<>
{renderMyPortalCrumb()}
-
- {t("common:breadcrumb-your-cases")}
-
+ {renderTextCrumb(
+ t("common:breadcrumb-your-cases")
+ )}
>
)}
{isPath("/myportal/viewall") && (
@@ -482,42 +472,30 @@ const Breadcrumbs = (props) => {
<>
{" "}
{renderMyPortalCrumb()}
-
-
- {t("common:breadcrumb-address-search")}
-
-
-
- {
- // spinnerState();
- router.back();
- }}
- className="govuk-breadcrumbs__link"
- >
- {t(
- "common:breadcrumb-address-search-results"
- )}
-
-
+ {renderLinkCrumb(
+ isWelsh
+ ? "/" +
+ router.locale +
+ "/fymhorth/chwiliadcyfeiriadau"
+ : "/myportal/addresssearch",
+ t("common:breadcrumb-address-search")
+ )}
+ {renderLinkCrumb(
+ isWelsh
+ ? "/" +
+ router.locale +
+ "/fymhorth/canlyniadaucyfeiriadau?" +
+ nestedSearchString
+ : "/myportal/addresssearchresults?" +
+ nestedSearchString,
+ t(
+ "common:breadcrumb-address-search-results"
+ ),
+ () => {
+ // spinnerState();
+ router.back();
+ }
+ )}
{renderCaseReferenceCrumb(currentReference)}
>
)}
@@ -539,22 +517,16 @@ const Breadcrumbs = (props) => {
<>
{" "}
{renderMyPortalCrumb()}
-
- {t("dnsCommon:service-name")}
-
+ {renderTextCrumb(t("dnsCommon:service-name"))}
>
)}
{isPath("/myportal/dnsdetails") && (
<>
{renderMyPortalCrumb()}
-
-
- {t("dnsCommon:service-name")}
-
-
+ {renderLinkCrumb(
+ "/myportal/dnsapplications",
+ t("dnsCommon:service-name")
+ )}
{renderCaseReferenceCrumb(currentReference)}
>
)}
@@ -572,14 +544,10 @@ const Breadcrumbs = (props) => {
{t("common:breadcrumb-my-portal")}
-
-
- {t("dnsCommon:service-name")}
-
-
+ {renderLinkCrumb(
+ "/myportal/dnsapplications",
+ t("dnsCommon:service-name")
+ )}
{renderCaseReferenceCrumb(caseReferenceDisplay)}
>
)}
diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md
index cc893885..879906df 100644
--- a/memory-bank/change-log.md
+++ b/memory-bank/change-log.md
@@ -162,6 +162,34 @@ Follow-ups:
- Next bounded slice can target remaining repeated linked breadcrumb list-item patterns (e.g., recurring address-search result link pairs) via small local render helpers.
+### CL-22541-F: breadcrumbs multi-pattern helper bundle (text + link crumbs)
+
+date: 2026-04-09
+author: Cline
+scope: `components/breadcrumbs.js`
+type: change
+rationale: Deliver a slightly larger bounded slice by extracting and reusing multiple breadcrumb rendering patterns (plain text crumb and linked crumb) across several route branches.
+impact: Refactor-only JSX deduplication and consistency improvement in breadcrumb rendering; no intended route/auth/session/API/EN-CY/a11y behavior change.
+status: completed
+
+Summary:
+
+- Added reusable helpers in `components/breadcrumbs.js`:
+ - `renderTextCrumb(label)`
+ - `renderLinkCrumb(href, label, onClick)`
+- Replaced multiple repeated inline breadcrumb blocks across search/address/myportal/dns branches with helper calls.
+- Included onClick-capable link helper usage in the `/myportal/case/id/[incident]` address-results breadcrumb branch to preserve `router.back()` behavior.
+- Combined with existing `renderMyPortalCrumb` and `renderCaseReferenceCrumb` helpers for more consistent branch composition.
+
+Validation:
+
+- `npx eslint components/breadcrumbs.js` -> pass.
+- `node tests/phase22/index.test.cjs` -> pass (combined suite).
+
+Follow-ups:
+
+- Next slice recommendation: extract remaining repeated inline link crumbs for case/DNS branches that still hardcode `` (e.g., `/myportal/case`, `/myportal/case/[ticketnumber]`, `/dnsdetails`, `/dns/[developmentName]`) to complete link-pattern consolidation.
+
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
date: 2026-04-07