diff --git a/website/src/components/card-grid.js b/website/src/components/card-grid.js index 0281af48..cb1d4f73 100644 --- a/website/src/components/card-grid.js +++ b/website/src/components/card-grid.js @@ -90,16 +90,21 @@ function renderCategorySection(category, allAnchors) {
- ${categoryAnchors.map((anchor) => renderAnchorCard(anchor, color)).join('')} + ${categoryAnchors.map((anchor) => renderAnchorCard(anchor, color, category.id)).join('')}
` } /** - * Render a single anchor card + * Render a single anchor card. + * + * The optional `categoryId` argument is used to namespace the heading id + * used by `aria-labelledby`, since the same anchor may appear in multiple + * category sections (anchors can belong to more than one category) and + * the DOM must not contain duplicate ids. */ -function renderAnchorCard(anchor, categoryColor) { +function renderAnchorCard(anchor, categoryColor, categoryId) { const isUmbrella = anchor.subAnchors && anchor.subAnchors.length > 0 const umbrellaClass = isUmbrella ? ' anchor-card-umbrella' : '' const rolesCount = anchor.roles ? anchor.roles.length : 0 @@ -110,19 +115,21 @@ function renderAnchorCard(anchor, categoryColor) { const editTitle = i18n.t('card.edit') const copyLinkTitle = i18n.t('card.copyLink') const safeId = escapeHtml(anchor.id) + const safeCategoryId = escapeHtml(categoryId || 'uncat') + const cardTitleId = `anchor-card-title-${safeCategoryId}-${safeId}` return ` -
-

${escapeHtml(anchor.title)}

+

${escapeHtml(anchor.title)}

+ ` } diff --git a/website/src/components/header.js b/website/src/components/header.js index 7c04cec9..ef2e495f 100644 --- a/website/src/components/header.js +++ b/website/src/components/header.js @@ -11,7 +11,7 @@ export function renderHeader() {
- Semantic Anchors + Semantic Anchors ${i18n.t('header.slogan')}