diff --git a/CHANGELOG.md b/CHANGELOG.md index e559f5c2f1..7110c3eb4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,12 @@ ([PR #N](https://github.com/alphagov/govuk-frontend/pull/N)) +- Prevent duplicate checkbox aria-describedby + + Addresses an edge case where a checkbox with a hint (but without a fieldset) is output with duplicate `aria-describeby` attributes. Fixes issue ([PR #1248](https://github.com/alphagov/govuk-frontend/pull/1248)) + + ([PR #1265](https://github.com/alphagov/govuk-frontend/pull/1265)) + ## 2.9.0 (Feature release) 🆕 New features: diff --git a/src/components/checkboxes/checkboxes.yaml b/src/components/checkboxes/checkboxes.yaml index 3500954d49..f49b3918db 100644 --- a/src/components/checkboxes/checkboxes.yaml +++ b/src/components/checkboxes/checkboxes.yaml @@ -229,6 +229,17 @@ examples: - value: yes text: I agree to the terms and conditions +- name: with single option (and hint) set 'aria-describedby' on input + data: + name: t-and-c-with-hint + errorMessage: + text: Please accept the terms and conditions + items: + - value: yes + text: I agree to the terms and conditions + hint: + text: Go on, you know you want to! + - name: with all fieldset attributes data: idPrefix: example @@ -380,7 +391,7 @@ examples: html: | - + - name: with optional form-group classes showing group error data: idPrefix: how-contacted-checked diff --git a/src/components/checkboxes/template.njk b/src/components/checkboxes/template.njk index 96e9d496e5..e8cdc8c9f6 100644 --- a/src/components/checkboxes/template.njk +++ b/src/components/checkboxes/template.njk @@ -54,15 +54,15 @@ {% set name = item.name if item.name else params.name %} {% set conditionalId = "conditional-" + id %} {% set hasHint = true if item.hint.text or item.hint.html %} - {% set itemHintId = id + '-item-hint' %} + {% set itemHintId = id + "-item-hint" if hasHint else "" %} + {% set itemDescribedBy = describedBy if not hasFieldset else "" %} + {% set itemDescribedBy = (itemDescribedBy + " " + itemHintId) | trim %}
0) %} aria-describedby="{{ describedBy }}"{% endif -%} {%- if item.conditional %} data-aria-controls="{{ conditionalId }}"{% endif -%} - {%- if hasHint %} aria-describedby="{{ itemHintId }}"{% endif -%} + {%- if itemDescribedBy %} aria-describedby="{{ itemDescribedBy }}"{% endif -%} {%- for attribute, value in item.attributes %} {{ attribute }}="{{ value }}"{% endfor -%}> {{ govukLabel({ html: item.html, diff --git a/src/components/checkboxes/template.test.js b/src/components/checkboxes/template.test.js index d4aa5d0a48..e18b3e3873 100644 --- a/src/components/checkboxes/template.test.js +++ b/src/components/checkboxes/template.test.js @@ -656,10 +656,18 @@ describe('Checkboxes', () => { }) describe('single checkbox without a fieldset', () => { - it('adds aria-describe to input if there is an error', () => { + it('adds aria-describedby to input if there is an error', () => { const $ = render('checkboxes', examples["with single option set 'aria-describedby' on input"]) const $input = $('input') expect($input.attr('aria-describedby')).toMatch('t-and-c-error') }) }) + + describe('single checkbox (with hint) without a fieldset', () => { + it('adds aria-describedby to input if there is an error and a hint', () => { + const $ = render('checkboxes', examples["with single option (and hint) set 'aria-describedby' on input"]) + const $input = $('input') + expect($input.attr('aria-describedby')).toMatch('t-and-c-with-hint-error t-and-c-with-hint-1-item-hint') + }) + }) })