diff --git a/components/breadcrumbs.js b/components/breadcrumbs.js
index ad41a3fc..6763bd83 100644
--- a/components/breadcrumbs.js
+++ b/components/breadcrumbs.js
@@ -139,6 +139,11 @@ const Breadcrumbs = (props) => {
);
+ const renderBackCrumb = (
+ onClick,
+ listItemClass = "govuk-breadcrumbs__link-item backChevron"
+ ) => renderAnchorCrumb("#", t("common:back-link"), onClick, listItemClass);
+
const { breadcrumbHref, caseResultsHref, breadcrumbLabel } =
resolveCaseBreadcrumbState({
query: router.query,
@@ -302,57 +307,38 @@ const Breadcrumbs = (props) => {
{isPath("/newappeal/[appealtypes]") && (
<>
{appealType.currentSection > 1 &&
- (appealType.currentSection === 9999 ? (
-
-
- {t(
- "common:service-name-breadcrumb"
- )}
-
-
- ) : (
- renderAnchorCrumb(
- "#",
- t("common:back-link"),
- () =>
- setCurrentSection(
- appealType.currentSection -
- 1
- ),
- "govuk-breadcrumbs__link-item"
- )
- ))}
+ (appealType.currentSection === 9999
+ ? renderLinkCrumb(
+ "/",
+ t(
+ "common:service-name-breadcrumb"
+ )
+ )
+ : renderBackCrumb(
+ () =>
+ setCurrentSection(
+ appealType.currentSection -
+ 1
+ ),
+ "govuk-breadcrumbs__link-item"
+ ))}
>
)}
{isPath("/myportal/[appealtypes]") && (
<>
{appealType.currentSection > 1 &&
- (appealType.currentSection === 9999 ? (
-
-
- {t(
- "common:service-name-breadcrumb"
- )}
-
-
- ) : (
- renderAnchorCrumb(
- "#",
- t("common:back-link"),
- () =>
- setCurrentSection(
- appealType.currentSection -
- 1
- ),
- "govuk-breadcrumbs__list-item backChevron"
- )
- ))}
+ (appealType.currentSection === 9999
+ ? renderLinkCrumb(
+ "/",
+ t(
+ "common:service-name-breadcrumb"
+ )
+ )
+ : renderBackCrumb(() =>
+ setCurrentSection(
+ appealType.currentSection - 1
+ )
+ ))}
>
)}
{isPath("/newappeal/selectappeal") && (
@@ -509,29 +495,23 @@ const Breadcrumbs = (props) => {
)}
{isPath("/case") && (
<>
-
- {
- // spinnerState();
- router.back();
- }}
- className="govuk-breadcrumbs__link"
- >
- {t("common:breadcrumb-search-results")}
-
-
+ {renderLinkCrumb(
+ isWelsh
+ ? router.locale +
+ "/searchresults?q=" +
+ router.query.q +
+ "&page=" +
+ router.query.page
+ : "/searchresults?q=" +
+ router.query.q +
+ "&page=" +
+ router.query.page,
+ t("common:breadcrumb-search-results"),
+ () => {
+ // spinnerState();
+ router.back();
+ }
+ )}
{renderCaseReferenceCrumb(currentReference)}
>
)}
@@ -540,42 +520,27 @@ const Breadcrumbs = (props) => {
{currentView.representationSubmit === true &&
currentView.representationSubmitConfirmation !==
true &&
- renderAnchorCrumb(
- "#",
- t("common:back-link"),
- () => {
- setRepresentationSubmit(qcount);
- },
- "govuk-breadcrumbs__link-item backChevron"
- )}
+ renderBackCrumb(() => {
+ setRepresentationSubmit(qcount);
+ })}
{currentView.representationSubmit !== true &&
hasRepDetails &&
repDetails?.representationType !==
"Questionnaire" &&
- renderAnchorCrumb(
- "#",
- t("common:back-link"),
- () => {
- setRepresentationSubmit(false);
- },
- "govuk-breadcrumbs__link-item backChevron"
- )}
+ renderBackCrumb(() => {
+ setRepresentationSubmit(false);
+ })}
{currentView.representationSubmit !== true &&
hasRepDetails &&
repDetails?.representationType ===
"Questionnaire" &&
showQuestionnaireSection > 1 &&
- renderAnchorCrumb(
- "#",
- t("common:back-link"),
- () => {
- setShowQuestionnaireSection(
- showQuestionnaireSection - 1
- );
- setRepresentationSubmit(false);
- },
- "govuk-breadcrumbs__link-item backChevron"
- )}
+ renderBackCrumb(() => {
+ setShowQuestionnaireSection(
+ showQuestionnaireSection - 1
+ );
+ setRepresentationSubmit(false);
+ })}
>
)}
{isPath("/account/personaldetails") && (
diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md
index 00b1ed2b..393cffac 100644
--- a/memory-bank/change-log.md
+++ b/memory-bank/change-log.md
@@ -247,6 +247,34 @@ Follow-ups:
- Next slice recommendation: consolidate remaining one-off inline breadcrumb `` blocks still present in edge branches (e.g., `/newappeal/[appealtypes]`, `/myportal/[appealtypes]`, `/case`) and consider introducing an optional `renderBackCrumb(...)` semantic wrapper for readability.
+### CL-22541-I: breadcrumbs edge branch consolidation + semantic back-crumb wrapper
+
+date: 2026-04-09
+author: Cline
+scope: `components/breadcrumbs.js`
+type: change
+rationale: Continue the same bounded breadcrumbs refactor cadence by consolidating remaining edge inline Link/back crumbs and introducing a semantic back-crumb wrapper for readability.
+impact: Refactor-only JSX deduplication/readability improvement; no intended route/auth/session/API/EN-CY/a11y behavior change.
+status: completed
+
+Summary:
+
+- Added semantic helper `renderBackCrumb(onClick, listItemClass?)` that delegates to `renderAnchorCrumb(...)` with existing back-link text.
+- Replaced remaining one-off inline edge crumbs in:
+ - `/newappeal/[appealtypes]` and `/myportal/[appealtypes]` (`currentSection === 9999` service-name link and back-link branch)
+ - `/case` search-results link crumb (including existing `router.back()` callback)
+ - `/myportal/representation` back-link branches now use `renderBackCrumb(...)`.
+- Preserved existing href targets, callback behavior, and class semantics (including special `govuk-breadcrumbs__link-item` usage).
+
+Validation:
+
+- `npx eslint components/breadcrumbs.js` -> pass.
+- `node tests/phase22/index.test.cjs` -> pass (combined suite).
+
+Follow-ups:
+
+- Next slice recommendation: consider extracting a small, route-keyed breadcrumb branch map/helper grouping in `components/breadcrumbs.js` (purely structural) to reduce the long inline conditional chain while keeping one-slice behavior parity.
+
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
date: 2026-04-07