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