22541 extract shared anchor/back breadcrumb helper patterns

This commit is contained in:
2026-04-09 09:45:00 +01:00
parent 30bc729c70
commit e3e893ed58
2 changed files with 96 additions and 84 deletions
+68 -84
View File
@@ -122,6 +122,23 @@ const Breadcrumbs = (props) => {
</li> </li>
); );
const renderAnchorCrumb = (
href,
label,
onClick,
listItemClass = "govuk-breadcrumbs__list-item"
) => (
<li className={listItemClass}>
<a
className="govuk-breadcrumbs__link"
href={href}
onClick={onClick}
>
{label}
</a>
</li>
);
const { breadcrumbHref, caseResultsHref, breadcrumbLabel } = const { breadcrumbHref, caseResultsHref, breadcrumbLabel } =
resolveCaseBreadcrumbState({ resolveCaseBreadcrumbState({
query: router.query, query: router.query,
@@ -153,14 +170,10 @@ const Breadcrumbs = (props) => {
)} )}
{isPath("/myportal/searchresults") && ( {isPath("/myportal/searchresults") && (
<> <>
<li className="govuk-breadcrumbs__list-item"> {renderAnchorCrumb(
<a myPortalHref,
href={myPortalHref} t("common:breadcrumb-my-portal")
className="govuk-breadcrumbs__link" )}
>
{t("common:breadcrumb-my-portal")}
</a>
</li>
<li className="govuk-breadcrumbs__list-item"> <li className="govuk-breadcrumbs__list-item">
{t("common:breadcrumb-search-results")} {t("common:breadcrumb-search-results")}
</li> </li>
@@ -301,20 +314,16 @@ const Breadcrumbs = (props) => {
</Link> </Link>
</li> </li>
) : ( ) : (
<li className="govuk-breadcrumbs__link-item"> renderAnchorCrumb(
<a "#",
className="govuk-breadcrumbs__link" t("common:back-link"),
href="#" () =>
onClick={() => setCurrentSection(
setCurrentSection( appealType.currentSection -
appealType.currentSection - 1
1 ),
) "govuk-breadcrumbs__link-item"
} )
>
{t("common:back-link")}
</a>
</li>
))} ))}
</> </>
)} )}
@@ -333,22 +342,16 @@ const Breadcrumbs = (props) => {
</Link> </Link>
</li> </li>
) : ( ) : (
<> renderAnchorCrumb(
<li className="govuk-breadcrumbs__list-item backChevron"> "#",
<a t("common:back-link"),
className="govuk-breadcrumbs__link" () =>
href="#" setCurrentSection(
onClick={() => appealType.currentSection -
setCurrentSection( 1
appealType.currentSection - ),
1 "govuk-breadcrumbs__list-item backChevron"
) )
}
>
{t("common:back-link")}
</a>
</li>
</>
))} ))}
</> </>
)} )}
@@ -536,61 +539,42 @@ const Breadcrumbs = (props) => {
<> <>
{currentView.representationSubmit === true && {currentView.representationSubmit === true &&
currentView.representationSubmitConfirmation !== currentView.representationSubmitConfirmation !==
true && ( true &&
<li className="govuk-breadcrumbs__link-item backChevron"> renderAnchorCrumb(
<a "#",
className="govuk-breadcrumbs__link" t("common:back-link"),
href="#" () => {
onClick={() => { setRepresentationSubmit(qcount);
setRepresentationSubmit( },
qcount "govuk-breadcrumbs__link-item backChevron"
);
}}
>
{t("common:back-link")}
</a>
</li>
)} )}
{currentView.representationSubmit !== true && {currentView.representationSubmit !== true &&
hasRepDetails && hasRepDetails &&
repDetails?.representationType !== repDetails?.representationType !==
"Questionnaire" && ( "Questionnaire" &&
<li className="govuk-breadcrumbs__link-item backChevron"> renderAnchorCrumb(
<a "#",
className="govuk-breadcrumbs__link" t("common:back-link"),
href="#" () => {
onClick={() => { setRepresentationSubmit(false);
setRepresentationSubmit( },
false "govuk-breadcrumbs__link-item backChevron"
);
}}
>
{t("common:back-link")}
</a>
</li>
)} )}
{currentView.representationSubmit !== true && {currentView.representationSubmit !== true &&
hasRepDetails && hasRepDetails &&
repDetails?.representationType === repDetails?.representationType ===
"Questionnaire" && "Questionnaire" &&
showQuestionnaireSection > 1 && ( showQuestionnaireSection > 1 &&
<li className="govuk-breadcrumbs__link-item backChevron"> renderAnchorCrumb(
<a "#",
className="govuk-breadcrumbs__link" t("common:back-link"),
href="#" () => {
onClick={() => { setShowQuestionnaireSection(
setShowQuestionnaireSection( showQuestionnaireSection - 1
showQuestionnaireSection - );
1 setRepresentationSubmit(false);
); },
setRepresentationSubmit( "govuk-breadcrumbs__link-item backChevron"
false
);
}}
>
{t("common:back-link")}
</a>
</li>
)} )}
</> </>
)} )}
+28
View File
@@ -219,6 +219,34 @@ Follow-ups:
- Next slice recommendation: target remaining anchor/back-link duplication (`<a href="#">` and occasional `<a href={...}>`) by introducing a bounded helper for action/back crumbs while preserving existing non-Link semantics. - Next slice recommendation: target remaining anchor/back-link duplication (`<a href="#">` and occasional `<a href={...}>`) by introducing a bounded helper for action/back crumbs while preserving existing non-Link semantics.
### CL-22541-H: breadcrumbs anchor/back-link helper consolidation bundle
date: 2026-04-09
author: Cline
scope: `components/breadcrumbs.js`
type: change
rationale: Continue the larger bounded breadcrumbs refactor cadence by extracting repeated anchor/back-link crumb markup into one local helper while preserving non-Link semantics.
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 `renderAnchorCrumb(href, label, onClick, listItemClass)` in `components/breadcrumbs.js` for repeated `<a ...>` breadcrumb actions.
- Replaced repeated anchor/back-link crumb blocks in:
- `/myportal/searchresults` my-portal anchor crumb
- `/newappeal/[appealtypes]` and `/myportal/[appealtypes]` step-back crumbs
- `/myportal/representation` back-chevron action crumbs (all three state branches)
- Preserved original click handlers, href values, and class semantics (`govuk-breadcrumbs__link-item`, `backChevron`) to keep behavior parity.
Validation:
- `npx eslint components/breadcrumbs.js` -> pass.
- `node tests/phase22/index.test.cjs` -> pass (combined suite).
Follow-ups:
- Next slice recommendation: consolidate remaining one-off inline breadcrumb `<li><Link ...>` blocks still present in edge branches (e.g., `/newappeal/[appealtypes]`, `/myportal/[appealtypes]`, `/case`) and consider introducing an optional `renderBackCrumb(...)` semantic wrapper for readability.
### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction ### CL-00X: 22500 `components/elements/index.js` Phase 1 helper extraction
date: 2026-04-07 date: 2026-04-07