diff --git a/CHANGELOG.md b/CHANGELOG.md
index 43208bdd63..9a2f6bb05b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@
useful summary for people upgrading their application, not a replication
of the commit log.
+## Unreleased
+
+- Add heading options to radio component (PR #635)
+
## 12.12.1
* Corrects name for checkboxes documentation (PR #638)
diff --git a/app/views/govuk_publishing_components/components/_radio.html.erb b/app/views/govuk_publishing_components/components/_radio.html.erb
index 02e1725034..c3fda2bffd 100644
--- a/app/views/govuk_publishing_components/components/_radio.html.erb
+++ b/app/views/govuk_publishing_components/components/_radio.html.erb
@@ -3,91 +3,109 @@
items ||= []
label ||= nil
+ heading ||= nil
+ is_page_heading ||= false
hint ||= nil
error_message ||= nil
error_items ||= nil
+
has_error = error_message || error_items&.any?
- hint_id = "hint-#{SecureRandom.hex(4)}"
+ hint_id = "hint-#{SecureRandom.hex(4)}" if hint
error_id = "error-#{SecureRandom.hex(4)}"
form_group_css_classes = %w(govuk-form-group)
form_group_css_classes << "govuk-form-group--error" if has_error
+ aria = "#{hint_id} #{"#{error_id}" if has_error}".strip if hint or has_error
+
# check if any item is set as being conditional
has_conditional = items.any? { |item| item.is_a?(Hash) && item[:conditional] }
%>
<%= content_tag :div, class: form_group_css_classes do %>
+ <%= tag.fieldset class: "govuk-fieldset", "aria-describedby": aria do %>
- <% if hint %>
- <%= render "govuk_publishing_components/components/hint", {
- id: hint_id,
- text: hint
- } %>
- <% end %>
+ <% if heading.present? %>
+ <% if is_page_heading %>
+ <%= tag.legend class: "govuk-fieldset__legend govuk-fieldset__legend--xl gem-c-title gem-c-title--margin-bottom-5" do %>
+ <%= tag.h1 heading, class: "gem-c-title__text" %>
+ <% end %>
+ <% else %>
+ <%= tag.legend heading, class: "govuk-fieldset__legend govuk-fieldset__legend--m" %>
+ <% end %>
+ <% end %>
- <% if error_message %>
- <%= render "govuk_publishing_components/components/error_message", {
- id: error_id,
- text: error_message
- } %>
- <% elsif error_items %>
- <%= render "govuk_publishing_components/components/error_message", {
- id: error_id,
- text: raw(error_items.map { |item| item[:text] }.join("
"))
- } %>
- <% end %>
+ <% if hint %>
+ <%= render "govuk_publishing_components/components/hint", {
+ id: hint_id,
+ text: hint
+ } %>
+ <% end %>
- <%= content_tag :div, class: "govuk-radios",
- data: {
- module: ('radios' if has_conditional)
- } do %>
- <% items.each_with_index do |item, index| %>
- <% if item === :or %>
-
- <%= t('components.radio.or') %>
-
- <% else %>
- <%
- item_next = items[index + 1] unless index === items.size - 1
- label_id = item[:id] ? item[:id] : "#{id_prefix}-#{index}"
- label_hint_id = "label-hint-#{SecureRandom.hex(4)}" if item[:hint_text].present?
- conditional_id = "conditional-#{SecureRandom.hex(4)}" if item[:conditional].present?
+ <% if error_message %>
+ <%= render "govuk_publishing_components/components/error_message", {
+ id: error_id,
+ text: error_message
+ } %>
+ <% elsif error_items %>
+ <%= render "govuk_publishing_components/components/error_message", {
+ id: error_id,
+ text: raw(error_items.map { |item| item[:text] }.join("
"))
+ } %>
+ <% end %>
+
+ <%= content_tag :div, class: "govuk-radios",
+ data: {
+ module: ('radios' if has_conditional)
+ } do %>
+ <% items.each_with_index do |item, index| %>
+ <% if item === :or %>
+
+ <%= t('components.radio.or') %>
+
+ <% else %>
+ <%
+ item_next = items[index + 1] unless index === items.size - 1
+ label_id = item[:id] ? item[:id] : "#{id_prefix}-#{index}"
+ label_hint_id = "label-hint-#{SecureRandom.hex(4)}" if item[:hint_text].present?
+ conditional_id = "conditional-#{SecureRandom.hex(4)}" if item[:conditional].present?
- data_attrs = { "aria-controls": conditional_id }
- data_attrs["tracking-url"] = item[:url] if item.key?(:url)
- %>
- <%= tag.div class: %w( gem-c-radio govuk-radios__item ) do %>
- <%= check_box_tag name,
- item[:value],
- item[:checked],
- {
- class: "govuk-radios__input",
- id: label_id,
- type: "radio",
- aria: {
- describedby: label_hint_id
- },
- data: data_attrs,
- }
+ data_attrs = { "aria-controls": conditional_id }
+ data_attrs["tracking-url"] = item[:url] if item.key?(:url)
%>
- <%= render "govuk_publishing_components/components/label", {
- hint_id: label_hint_id,
- html_for: label_id,
- classes: "govuk-radios__label",
- hint_text_classes: "govuk-radios__hint",
- hint_text: item[:hint_text],
- text: item[:text],
- bold: item[:bold]
- } %>
- <% end %>
+ <%= tag.div class: %w( gem-c-radio govuk-radios__item ) do %>
+ <%= check_box_tag name,
+ item[:value],
+ item[:checked],
+ {
+ class: "govuk-radios__input",
+ id: label_id,
+ type: "radio",
+ aria: {
+ describedby: label_hint_id
+ },
+ data: data_attrs,
+ }
+ %>
+ <%= render "govuk_publishing_components/components/label", {
+ hint_id: label_hint_id,
+ html_for: label_id,
+ classes: "govuk-radios__label",
+ hint_text_classes: "govuk-radios__hint",
+ hint_text: item[:hint_text],
+ text: item[:text],
+ bold: item[:bold]
+ } %>
+ <% end %>
- <% if item[:conditional] %>
-
- <%= item[:conditional] %>
-
- <% end %>
+ <% if item[:conditional] %>
+
+ <%= item[:conditional] %>
+
+ <% end %>
+ <% end %>
<% end %>
<% end %>
+
<% end %>
<% end %>
diff --git a/app/views/govuk_publishing_components/components/docs/radio.yml b/app/views/govuk_publishing_components/components/docs/radio.yml
index 4b985e999d..f7df1217a0 100644
--- a/app/views/govuk_publishing_components/components/docs/radio.yml
+++ b/app/views/govuk_publishing_components/components/docs/radio.yml
@@ -57,7 +57,61 @@ examples:
text: "Use GOV.UK Verify"
hint_text: "You'll have an account if you've already proved your identity with a certified company, such as the Post Office."
bold: true
- with_hint_text:
+ with_hint_on_form_group:
+ data:
+ name: "radio-group-error"
+ id_prefix: "hint"
+ hint: "You’ll need to prove your identity using one of the following methods"
+ items:
+ - value: "government-gateway"
+ text: "Use Government Gateway"
+ - value: "govuk-verify"
+ text: "Use GOV.UK Verify"
+ with_heading:
+ description: This adds a legend element containing the text supplied.
+ data:
+ name: "radio-group-heading"
+ heading: "Are you hungry?"
+ items:
+ - value: "yes"
+ text: "Yes"
+ - value: "no"
+ text: "No"
+ with_heading_and_hint:
+ data:
+ name: "radio-group-heading"
+ heading: "What is your favourite colour?"
+ hint: "If your favourite is not below, pick the colour closest to it."
+ items:
+ - value: "red"
+ text: "Red"
+ - value: "green"
+ text: "Green"
+ - value: "blue"
+ text: "Blue"
+ with_page_heading:
+ description: This adds a H1 element containing the text supplied.
+ data:
+ name: "radio-group-heading"
+ heading: "Is it raining?"
+ is_page_heading: true
+ items:
+ - value: "yes"
+ text: "Yes"
+ - value: "no"
+ text: "No"
+ with_page_heading_and_hint:
+ data:
+ name: "radio-group-heading"
+ heading: "Is it snowing?"
+ is_page_heading: true
+ hint: "Sleet or hail doesn’t count."
+ items:
+ - value: "yes"
+ text: "Yes"
+ - value: "no"
+ text: "No"
+ with_hint_text_on_radios:
data:
name: "radio-group-hint-text"
items:
@@ -120,21 +174,23 @@ examples:
hint_text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sapien justo, lobortis elementum tortor in, luctus interdum turpis. Nam sit amet nulla nec arcu condimentum dapibus quis varius metus. Suspendisse cursus tristique diam et vestibulum. Proin nec lacinia tortor. Morbi at nisi id lorem aliquam ullamcorper. Pellentesque laoreet sit amet leo sodales ultricies. Suspendisse maximus efficitur odio in tristique."
text: "Quisque tincidunt venenatis bibendum. Morbi volutpat magna euismod ipsum consequat cursus. Etiam bibendum interdum ultricies."
bold: true
- with_hint_on_form_group:
+ with_error_on_form_group:
data:
name: "radio-group-error"
- id_prefix: "hint"
- hint: "You’ll need to prove your identity using one of the following methods"
+ id_prefix: "error"
+ error_message: "Please select one option"
items:
- value: "government-gateway"
text: "Use Government Gateway"
- value: "govuk-verify"
text: "Use GOV.UK Verify"
- with_error_on_form_group:
+ with_error_and_hint_on_form_group:
+ description: ""
data:
name: "radio-group-error"
id_prefix: "error"
error_message: "Please select one option"
+ hint: "Choose the option that suits"
items:
- value: "government-gateway"
text: "Use Government Gateway"
diff --git a/spec/components/radio_spec.rb b/spec/components/radio_spec.rb
index 0f7e1909b2..3c2aca6ca6 100644
--- a/spec/components/radio_spec.rb
+++ b/spec/components/radio_spec.rb
@@ -29,6 +29,8 @@ def component_name
assert_select ".govuk-radios__input[name=radio-group-one-item]"
assert_select ".govuk-radios__item:first-child .govuk-radios__label", text: "Use Government Gateway"
+ assert_select "legend", false
+ assert_select "legend h1", false
end
it "renders radio-group with multiple items" do
@@ -51,6 +53,34 @@ def component_name
assert_select ".govuk-radios__item:last-child .govuk-radios__label", text: "Use GOV.UK Verify"
end
+ it "renders radio-group with a legend" do
+ render_component(
+ name: "favourite-smartie",
+ heading: "What is your favourite smartie?",
+ items: [
+ { label: "Red", value: "red" },
+ { label: "Blue", value: "blue" }
+ ]
+ )
+ assert_select ".govuk-radios"
+ assert_select "legend", "What is your favourite smartie?"
+ assert_select "legend h1", false
+ end
+
+ it "renders radio-group with the legend as the page heading" do
+ render_component(
+ name: "favourite-skittle",
+ heading: "What is your favourite skittle?",
+ is_page_heading: true,
+ items: [
+ { label: "Red", value: "red" },
+ { label: "Blue", value: "blue" }
+ ]
+ )
+ assert_select ".govuk-radios"
+ assert_select "legend h1", "What is your favourite skittle?"
+ end
+
it "renders radio-group with bold labels" do
render_component(
name: "radio-group-bold-labels",
@@ -199,6 +229,10 @@ def component_name
)
assert_select ".govuk-hint", text: "You’ll need to prove your identity using one of the following methods"
+
+ dom = Nokogiri::HTML(rendered)
+ hint_id = dom.xpath('//span')[0].attr('id')
+ assert_select ".govuk-fieldset[aria-describedby='#{hint_id}']"
end
it "renders radio-group with error message" do
@@ -218,6 +252,36 @@ def component_name
)
assert_select ".govuk-error-message", text: "Please select one option"
+
+ dom = Nokogiri::HTML(rendered)
+ error_id = dom.xpath('//span')[0].attr('id')
+ assert_select ".govuk-fieldset[aria-describedby='#{error_id}']"
+ end
+
+ it "renders radio-group with error message and hint text" do
+ render_component(
+ name: "radio-group-conditional",
+ hint: "You’ll need to prove your identity using one of the following methods",
+ error_message: "Please select one option",
+ items: [
+ {
+ value: "government-gateway",
+ text: "Use Government Gateway"
+ },
+ {
+ value: "govuk-verify",
+ text: "Use GOV.UK Verify"
+ }
+ ]
+ )
+
+ assert_select ".govuk-error-message", text: "Please select one option"
+
+ dom = Nokogiri::HTML(rendered)
+ hint_id = dom.xpath('//span')[0].attr('id')
+ error_id = dom.xpath('//span')[1].attr('id')
+ ids = hint_id + " " + error_id
+ assert_select ".govuk-fieldset[aria-describedby='#{ids}']"
end
it "renders radio-group with error items" do