@@ -90,16 +90,21 @@ function renderCategorySection(category, allAnchors) {
9090 </h2>
9191
9292 <div class="anchor-cards-grid">
93- ${ categoryAnchors . map ( ( anchor ) => renderAnchorCard ( anchor , color ) ) . join ( '' ) }
93+ ${ categoryAnchors . map ( ( anchor ) => renderAnchorCard ( anchor , color , category . id ) ) . join ( '' ) }
9494 </div>
9595 </section>
9696 `
9797}
9898
9999/**
100- * Render a single anchor card
100+ * Render a single anchor card.
101+ *
102+ * The optional `categoryId` argument is used to namespace the heading id
103+ * used by `aria-labelledby`, since the same anchor may appear in multiple
104+ * category sections (anchors can belong to more than one category) and
105+ * the DOM must not contain duplicate ids.
101106 */
102- function renderAnchorCard ( anchor , categoryColor ) {
107+ function renderAnchorCard ( anchor , categoryColor , categoryId ) {
103108 const isUmbrella = anchor . subAnchors && anchor . subAnchors . length > 0
104109 const umbrellaClass = isUmbrella ? ' anchor-card-umbrella' : ''
105110 const rolesCount = anchor . roles ? anchor . roles . length : 0
@@ -110,19 +115,21 @@ function renderAnchorCard(anchor, categoryColor) {
110115 const editTitle = i18n . t ( 'card.edit' )
111116 const copyLinkTitle = i18n . t ( 'card.copyLink' )
112117 const safeId = escapeHtml ( anchor . id )
118+ const safeCategoryId = escapeHtml ( categoryId || 'uncat' )
119+ const cardTitleId = `anchor-card-title-${ safeCategoryId } -${ safeId } `
113120
114121 return `
115- <article
122+ <div
116123 class="anchor-card${ umbrellaClass } "
117124 data-anchor="${ safeId } "
118125 data-roles="${ escapeHtml ( anchor . roles ? anchor . roles . join ( ',' ) : '' ) } "
119126 data-tags="${ escapeHtml ( anchor . tags ? anchor . tags . join ( ',' ) : '' ) } "
120127 tabindex="0"
121128 role="button"
122- aria-label ="${ escapeHtml ( i18n . t ( 'card.openDetails' ) . replace ( '{title}' , anchor . title ) ) } "
129+ aria-labelledby ="${ cardTitleId } "
123130 >
124131 <div class="anchor-card-header">
125- <h3 class="anchor-card-title">${ escapeHtml ( anchor . title ) } </h3>
132+ <h3 id=" ${ cardTitleId } " class="anchor-card-title">${ escapeHtml ( anchor . title ) } </h3>
126133 <div class="flex gap-1">
127134 <button
128135 class="anchor-copy-link-btn"
@@ -215,7 +222,7 @@ function renderAnchorCard(anchor, categoryColor) {
215222 </div>
216223
217224 <div class="anchor-card-indicator" style="background-color: ${ categoryColor } "></div>
218- </article >
225+ </div >
219226 `
220227}
221228
0 commit comments