diff --git a/CHANGELOG.md b/CHANGELOG.md
index 18b6e907bd..50bb4256d1 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 context option to heading component ([PR #4510](https://github.com/alphagov/govuk_publishing_components/pull/4510))
+
## 46.4.0
* Add canonical_url value to GA4 page view tracking ([PR #4500](https://github.com/alphagov/govuk_publishing_components/pull/4500))
diff --git a/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss b/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss
index 2f3c1e7756..7f0ec54fef 100644
--- a/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss
+++ b/app/assets/stylesheets/govuk_publishing_components/components/_heading.scss
@@ -1,6 +1,7 @@
@import "govuk_publishing_components/individual_component_support";
-.gem-c-heading {
+.gem-c-heading,
+.gem-c-heading__text {
margin: 0;
}
@@ -9,18 +10,6 @@
@include govuk-font(27, $weight: bold);
}
-// special case for publications and consultations pages
-// separated to allow normalisation of the component for wider use
-.gem-c-heading--mobile-top-margin {
- margin-top: govuk-spacing(6);
- margin-bottom: govuk-spacing(3);
-
- @include govuk-media-query($from: tablet) {
- margin-top: 0;
- margin-bottom: govuk-spacing(6);
- }
-}
-
.gem-c-heading--padding {
padding: govuk-spacing(3) 0;
}
@@ -43,7 +32,10 @@
}
.gem-c-heading--inverse {
- color: govuk-colour("white");
+ .gem-c-heading__context,
+ .gem-c-heading__text {
+ color: govuk-colour("white");
+ }
}
// stylelint-disable declaration-no-important
diff --git a/app/views/govuk_publishing_components/components/_heading.html.erb b/app/views/govuk_publishing_components/components/_heading.html.erb
index 6f00dad922..885697098c 100644
--- a/app/views/govuk_publishing_components/components/_heading.html.erb
+++ b/app/views/govuk_publishing_components/components/_heading.html.erb
@@ -3,21 +3,36 @@
brand ||= false
lang = local_assigns[:lang].presence
+ context ||= false
+ context_locale ||= false
+ context_inside ||= false
brand_helper = GovukPublishingComponents::AppHelpers::BrandHelper.new(brand)
heading_helper = GovukPublishingComponents::Presenters::HeadingHelper.new(local_assigns)
shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
- classes = %w(gem-c-heading)
- classes << heading_helper.classes
- classes << brand_helper.brand_class
- classes << brand_helper.border_color_class
-
- component_helper.add_class(classes.join(" "))
+ component_helper.add_class("gem-c-heading")
+ component_helper.add_class(heading_helper.classes)
+ component_helper.add_class(brand_helper.brand_class)
+ component_helper.add_class(brand_helper.border_color_class)
component_helper.set_id(heading_helper.id)
- element = shared_helper.get_heading_level
%>
-<%= content_tag(element, component_helper.all_attributes) do %>
- <%= text %>
+<% context_block = capture do %>
+ >
+ <%= context %>
+
+<% end %>
+
+<%= tag.div(**component_helper.all_attributes) do %>
+ <% if context && !context_inside %>
+ <%= context_block %>
+ <% end %>
+
+ <%= content_tag(shared_helper.get_heading_level, class: heading_helper.heading_classes) do %>
+ <% if context && context_inside %>
+ <%= context_block %>
+ <% end %>
+ <%= text %>
+ <% end %>
<% end %>
diff --git a/app/views/govuk_publishing_components/components/docs/heading.yml b/app/views/govuk_publishing_components/components/docs/heading.yml
index 6a9ccba742..da5dfab816 100644
--- a/app/views/govuk_publishing_components/components/docs/heading.yml
+++ b/app/views/govuk_publishing_components/components/docs/heading.yml
@@ -15,7 +15,7 @@ accessibility_criteria: |
- be part of a correct heading structure for a page
- be semantically represented as a heading
- convey the heading level
-uses_component_wrapper_helper: true
+uses_component_wrapper_helper: true
examples:
default:
data:
@@ -47,14 +47,6 @@ examples:
data:
text: 'Really big bottom margin'
margin_bottom: 9
- with_mobile_top_margin:
- description: |
- On publications and consultations the layout of the page requires that the heading component have spacing above it on mobile. Since this is a specific use case, this is now an option on the component rather than the default behaviour.
-
- It is intended that this option will ultimately be deprecated once more of the frontend is componentised and a general component model of margins is implemented.
- data:
- text: 'Consultation description'
- mobile_top_margin: true
with_border:
description: A top border can be applied to the component of different thicknesses. Accepted values are `1` (`1px`), `2` (`2px`) and `5` (`5px`). Note that this works best with padding applied.
data:
@@ -82,3 +74,35 @@ examples:
data:
text: "Ein gweinidogion"
lang: "cy"
+ with_context:
+ description: Context is applied sometimes where the heading is used as a page title H1. Note that the text size of the context is larger than the default size of the heading, so a larger `font_size` should be applied as shown.
+ data:
+ text: I like toast
+ context: Food opinion
+ font_size: "xl"
+ with_context_inside:
+ description: |
+ If the context should be considered part of the page heading, you can nest the context within the
.
+ data:
+ context: Publication
+ text: My page title
+ font_size: "xl"
+ context_inside: true
+ with_context_language_labelled:
+ description: |
+ Sometimes this component appears on a page that has been translated. The title will naturally be supplied in the required language but the context string may fall back to the default. In these instances we need to label the language so the page remains semantic and screenreaders can handle the switch.
+
+ The `lang` attribute **must** be set to a [valid BCP47 string](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang#Language_tag_syntax). A valid code can be the two or three letter language code - for example, English is `en` or `eng`, Korean is `ko` or `kor` - but if in doubt please check.
+ data:
+ context: Publication
+ context_locale: en
+ text: My page title
+ font_size: "xl"
+ with_context_inverted:
+ data:
+ context: Publication
+ text: My page title
+ font_size: "xl"
+ inverse: true
+ context:
+ dark_background: true
diff --git a/lib/govuk_publishing_components/presenters/heading_helper.rb b/lib/govuk_publishing_components/presenters/heading_helper.rb
index f36fb7c436..008521135f 100644
--- a/lib/govuk_publishing_components/presenters/heading_helper.rb
+++ b/lib/govuk_publishing_components/presenters/heading_helper.rb
@@ -1,17 +1,17 @@
module GovukPublishingComponents
module Presenters
class HeadingHelper
- attr_reader :heading_tag, :id, :classes
+ attr_reader :heading_tag, :id, :classes, :heading_classes
def initialize(options)
@id = options[:id]
@classes = ""
- @classes << heading_size(options[:font_size])
- @classes << " gem-c-heading--mobile-top-margin" if options[:mobile_top_margin]
@classes << " gem-c-heading--padding" if options[:padding]
@classes << " gem-c-heading--border-top-#{options[:border_top]}" if [1, 2, 5].include? options[:border_top]
@classes << " gem-c-heading--inverse" if options[:inverse]
+
+ @heading_classes = "gem-c-heading__text #{heading_size(options[:font_size])}"
end
private
diff --git a/spec/components/chart_spec.rb b/spec/components/chart_spec.rb
index 615f30e23e..2f9430702c 100644
--- a/spec/components/chart_spec.rb
+++ b/spec/components/chart_spec.rb
@@ -75,7 +75,7 @@ def component_name
data[:chart_heading] = "hello"
render_component(data)
- assert_select "h2.gem-c-heading", text: "hello"
+ assert_select ".gem-c-heading h2.gem-c-heading__text", text: "hello"
end
it "displays a heading with a custom heading level" do
@@ -83,7 +83,7 @@ def component_name
data[:chart_heading_level] = 4
render_component(data)
- assert_select "h4.gem-c-heading", text: "hello"
+ assert_select ".gem-c-heading h4.gem-c-heading__text", text: "hello"
end
it "can be rendered without a visible heading" do
diff --git a/spec/components/heading_spec.rb b/spec/components/heading_spec.rb
index c9aeee5d40..0d7daadc69 100644
--- a/spec/components/heading_spec.rb
+++ b/spec/components/heading_spec.rb
@@ -13,50 +13,50 @@ def component_name
it "renders a heading correctly" do
render_component(text: "Download documents")
- assert_select "h2.gem-c-heading", text: "Download documents"
+ assert_select ".gem-c-heading h2", text: "Download documents"
end
it "renders a different heading level" do
render_component(text: "Original consultation", heading_level: 3)
- assert_select "h3.gem-c-heading", text: "Original consultation"
+ assert_select ".gem-c-heading h3", text: "Original consultation"
end
it "adds xl font size" do
render_component(text: "Extra large", font_size: "xl")
- assert_select ".gem-c-heading.govuk-heading-xl"
+ assert_select ".gem-c-heading h2.govuk-heading-xl"
end
it "adds l font size" do
render_component(text: "Large", font_size: "l")
- assert_select ".gem-c-heading.govuk-heading-l"
+ assert_select ".gem-c-heading h2.govuk-heading-l"
end
it "adds m font size" do
render_component(text: "Medium", font_size: "m")
- assert_select ".gem-c-heading.govuk-heading-m"
+ assert_select ".gem-c-heading h2.govuk-heading-m"
end
it "supports legacy font size option of 24" do
render_component(text: "Medium", font_size: 24)
- assert_select ".gem-c-heading.govuk-heading-m"
+ assert_select ".gem-c-heading h2.govuk-heading-m"
end
it "adds s font size" do
render_component(text: "Small", font_size: "s")
- assert_select ".gem-c-heading.govuk-heading-s"
+ assert_select ".gem-c-heading h2.govuk-heading-s"
end
it "supports legacy font size option of 19" do
render_component(text: "Small", font_size: 19)
- assert_select ".gem-c-heading.govuk-heading-s"
+ assert_select ".gem-c-heading h2.govuk-heading-s"
end
it "adds default font size if given no or an invalid value" do
render_component(text: "font size not specified")
- assert_select ".gem-c-heading.gem-c-heading--font-size-27"
+ assert_select ".gem-c-heading h2.gem-c-heading--font-size-27"
render_component(text: "font size 199", font_size: 199)
- assert_select ".gem-c-heading.gem-c-heading--font-size-27"
+ assert_select ".gem-c-heading h2.gem-c-heading--font-size-27"
end
it "has a specified id attribute" do
@@ -64,11 +64,6 @@ def component_name
assert_select ".gem-c-heading[id='custom-id']", text: "Consultation description"
end
- it "adds the correct class for publications and consultations page" do
- render_component(text: "Consistency is nice", mobile_top_margin: true)
- assert_select ".gem-c-heading.gem-c-heading--mobile-top-margin"
- end
-
it "adds padding" do
render_component(text: "Padddddding", padding: true)
assert_select ".gem-c-heading.gem-c-heading--padding"
@@ -108,4 +103,25 @@ def component_name
render_component(text: "Inverted", inverse: true)
assert_select ".gem-c-heading.gem-c-heading--inverse"
end
+
+ it "renders a context" do
+ render_component(text: "Hello World", context: "Format")
+ assert_select ".gem-c-heading h2", text: "Hello World"
+ assert_select ".gem-c-heading .gem-c-heading__context", text: "Format"
+ end
+
+ it "renders no title context inside" do
+ render_component(text: "Hello World", context: "Format")
+ assert_select ".gem-c-heading h2 > .gem-c-heading__context", false
+ end
+
+ it "title context appears inside" do
+ render_component(text: "Hello World", context: "Format", context_inside: true)
+ assert_select ".gem-c-heading h2 > .gem-c-heading__context", text: "Format"
+ end
+
+ it "applies context language if supplied to a context string" do
+ render_component(text: "Bonjour Monde", context: "hello", context_locale: "en")
+ assert_select ".govuk-caption-xl[lang='en']"
+ end
end