govuk-components 5.5.0 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5fa50663dcfbb48693515d4cc519f16bb9e0be2a432e631fceff9327191b4965
4
- data.tar.gz: fc05c7022b6f3a4fa1205d6548e14c18ef790c3539d8557c345ccb1d72ec1eda
3
+ metadata.gz: ee7308a556bfe89c65bc0d7a239ffedf9266ae531b5fc320f7e85be9954fbf32
4
+ data.tar.gz: '09d4a6adc3c583c71bc8a40e60cf64ffb61d0cdc83b5505e1801134897a50028'
5
5
  SHA512:
6
- metadata.gz: da7f78f5378def00c0acdecb82c37dce7fdcd4ce9c1654a3cc46b1a180a3f322d3fdd881c1673f1a3cb065a0dedb56e6a7c9c3648298962e10f6b84f4016e96f
7
- data.tar.gz: e3f930679c6accfa1e462b3ea33881f34fb12426000ccd7a728e15db2c3af19a2bc7070f0d1c0836641b2ec97bad8f9b4e73d0accb5f49ea357b5a163e7ba898
6
+ metadata.gz: 175d8404af31999dcef4f7507745b3711da5a0c47cc00f2299f4a3c84a9efb400af417c8e43f2dc6ca6742d17a35a3f09eb5b9e44a931f1d9d1aee7fc36f264d
7
+ data.tar.gz: 98e3cf8d4d9822888ddd2a4b04489931523e9bda4deb9a112827efbc1d4bb1d8d5155d98b8b7340993097f8d5e74e2324c0f27a5ad1aeabb2aa6343b3ff263df
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Gem](https://img.shields.io/gem/dt/govuk-components?logo=rubygems)](https://rubygems.org/gems/govuk-components)
7
7
  [![Test coverage](https://api.codeclimate.com/v1/badges/cbcbc140f300b920d833/test_coverage)](https://codeclimate.com/github/x-govuk/govuk-components/test_coverage)
8
8
  [![Licence](https://img.shields.io/github/license/x-govuk/govuk-components)](https://github.com/x-govuk/govuk-components/blob/main/LICENSE.txt)
9
- [![GOV.UK Design System version](https://img.shields.io/badge/GOV.UK%20Design%20System-5.5.0-brightgreen)](https://design-system.service.gov.uk)
9
+ [![GOV.UK Design System version](https://img.shields.io/badge/GOV.UK%20Design%20System-5.6.0-brightgreen)](https://design-system.service.gov.uk)
10
10
  [![ViewComponent](https://img.shields.io/badge/ViewComponent-3.3.0-brightgreen)](https://viewcomponent.org/)
11
11
  [![Rails](https://img.shields.io/badge/Rails-7.0.8%20%E2%95%B1%207.1.3-E16D6D)](https://weblog.rubyonrails.org/releases/)
12
12
  [![Ruby](https://img.shields.io/badge/Ruby-3.1.6%20%20%E2%95%B1%203.2.4%20%20%E2%95%B1%203.3.4-E16D6D)](https://www.ruby-lang.org/en/downloads/)
@@ -27,6 +27,13 @@ class GovukComponent::Base < ViewComponent::Base
27
27
  end
28
28
 
29
29
  def brand(override = nil)
30
- override || config.brand
30
+ override || config.brand_overrides.fetch(class_prefix, config.brand)
31
+ end
32
+
33
+ # We want the main component and the subcomponents here so
34
+ # match on the second segment of the component class name
35
+ def class_prefix
36
+ # FIXME: this looks a bit dodgy...
37
+ self.class.name.match(/\w+::\w+/).to_s
31
38
  end
32
39
  end
@@ -9,7 +9,8 @@ class GovukComponent::HeaderComponent < GovukComponent::Base
9
9
  :menu_button_label,
10
10
  :navigation_label,
11
11
  :custom_navigation_classes,
12
- :custom_container_classes
12
+ :custom_container_classes,
13
+ :full_width_border
13
14
 
14
15
  def initialize(classes: [],
15
16
  html_attributes: {},
@@ -19,7 +20,8 @@ class GovukComponent::HeaderComponent < GovukComponent::Base
19
20
  navigation_label: config.default_header_navigation_label,
20
21
  service_name: config.default_header_service_name,
21
22
  service_url: config.default_header_service_url,
22
- container_classes: nil)
23
+ container_classes: nil,
24
+ full_width_border: false)
23
25
 
24
26
  @homepage_url = homepage_url
25
27
  @service_name = service_name
@@ -28,6 +30,7 @@ class GovukComponent::HeaderComponent < GovukComponent::Base
28
30
  @custom_navigation_classes = navigation_classes
29
31
  @navigation_label = navigation_label
30
32
  @custom_container_classes = container_classes
33
+ @full_width_border = full_width_border
31
34
 
32
35
  super(classes:, html_attributes:)
33
36
  end
@@ -35,7 +38,12 @@ class GovukComponent::HeaderComponent < GovukComponent::Base
35
38
  private
36
39
 
37
40
  def default_attributes
38
- { class: ["#{brand}-header"] }
41
+ {
42
+ class: class_names(
43
+ "#{brand}-header",
44
+ "#{brand}-header--full-width-border" => full_width_border
45
+ )
46
+ }
39
47
  end
40
48
 
41
49
  def navigation_html_attributes
@@ -0,0 +1,83 @@
1
+ class GovukComponent::ServiceNavigationComponent::NavigationItemComponent < GovukComponent::Base
2
+ attr_reader :text, :href, :current_path, :active_when, :current, :active
3
+
4
+ def initialize(text:, href: nil, current_path: nil, active_when: nil, current: false, active: false, classes: [], html_attributes: {})
5
+ @current = current
6
+ @active = active
7
+ @text = text
8
+ @href = href
9
+
10
+ @current_path = current_path
11
+ @active_when = active_when
12
+
13
+ super(classes:, html_attributes:)
14
+ end
15
+
16
+ def call
17
+ tag.li(**html_attributes) do
18
+ if href.present?
19
+ wrap_link(link_to(text, href, class: "#{brand}-service-navigation__link", **aria_current))
20
+ else
21
+ tag.span(text, class: "#{brand}-service-navigation__text")
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def wrap_link(link)
29
+ if current_or_active?
30
+ tag.strong(link, class: "#{brand}-service-navigation__active-fallback")
31
+ else
32
+ link
33
+ end
34
+ end
35
+
36
+ def current?
37
+ current || auto_current?
38
+ end
39
+
40
+ def active?
41
+ active || auto_active?
42
+ end
43
+
44
+ def current_or_active?
45
+ current? || active?
46
+ end
47
+
48
+ def auto_current?
49
+ return if current_path.blank?
50
+
51
+ current_path == href
52
+ end
53
+
54
+ def auto_active?
55
+ return if current_path.blank?
56
+
57
+ case active_when
58
+ when Regexp
59
+ active_when.match?(current_path)
60
+ when String
61
+ current_path.start_with?(active_when)
62
+ when Array
63
+ active_when.any? { |p| current_path.start_with?(p) }
64
+ else
65
+ false
66
+ end
67
+ end
68
+
69
+ def default_attributes
70
+ {
71
+ class: class_names(
72
+ "#{brand}-service-navigation__item",
73
+ "#{brand}-service-navigation__item--active" => current_or_active?
74
+ )
75
+ }
76
+ end
77
+
78
+ def aria_current
79
+ current = (current?) ? 'page' : true
80
+
81
+ { aria: { current: } }
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+ class GovukComponent::ServiceNavigationComponent::ServiceNameComponent < GovukComponent::Base
2
+ attr_reader :service_name, :service_url
3
+
4
+ def initialize(service_name:, service_url: nil, classes: [], html_attributes: {})
5
+ @service_name = service_name
6
+ @service_url = service_url
7
+
8
+ super(classes:, html_attributes:)
9
+ end
10
+
11
+ def call
12
+ text = (service_url.present?) ? build_link : build_span
13
+
14
+ tag.span(text, **html_attributes)
15
+ end
16
+
17
+ private
18
+
19
+ def build_link
20
+ link_to(service_name, service_url, class: "#{brand}-service-navigation__link")
21
+ end
22
+
23
+ def build_span
24
+ tag.span(service_name, class: "#{brand}-service-navigation__text")
25
+ end
26
+
27
+ def default_attributes
28
+ { class: "#{brand}-service-navigation__service-name" }
29
+ end
30
+ end
@@ -0,0 +1,92 @@
1
+ class GovukComponent::ServiceNavigationComponent < GovukComponent::Base
2
+ renders_one :start_slot
3
+ renders_one :end_slot
4
+
5
+ renders_one :service_name, "GovukComponent::ServiceNavigationComponent::ServiceNameComponent"
6
+ renders_many :navigation_items, ->(text:, href: nil, current_path: nil, active_when: nil, current: false, active: false, classes: [], html_attributes: {}) do
7
+ GovukComponent::ServiceNavigationComponent::NavigationItemComponent.new(
8
+ text:,
9
+ href:,
10
+ current_path: current_path || @current_path,
11
+ active_when:,
12
+ current:,
13
+ active:,
14
+ classes:,
15
+ html_attributes:
16
+ )
17
+ end
18
+
19
+ attr_reader :aria_label_text, :navigation_id
20
+
21
+ def initialize(service_name: nil, service_url: nil, navigation_items: [], current_path: nil, aria_label: "Service information", navigation_id: 'navigation', classes: [], html_attributes: {})
22
+ @service_name_text = service_name
23
+ @service_url = service_url
24
+ @current_path = current_path
25
+ @aria_label_text = aria_label
26
+ @navigation_id = navigation_id
27
+
28
+ if @service_name_text.present?
29
+ with_service_name(service_name: @service_name_text, service_url:)
30
+ end
31
+
32
+ navigation_items.each { |ni| with_navigation_item(current_path:, **ni) }
33
+
34
+ super(classes:, html_attributes:)
35
+ end
36
+
37
+ def call
38
+ outer_element do
39
+ tag.div(class: "#{brand}-width_container") do
40
+ safe_join(
41
+ [
42
+ start_slot,
43
+ tag.div(class: "#{brand}-service-navigation__container") do
44
+ safe_join([service_name, navigation].compact)
45
+ end,
46
+ end_slot
47
+ ]
48
+ )
49
+ end
50
+ end
51
+ end
52
+
53
+ def navigation
54
+ return unless navigation_items?
55
+
56
+ tag.nav(aria: { label: "Menu" }, class: "#{brand}-service-navigation__wrapper") do
57
+ safe_join([menu_button, navigation_list])
58
+ end
59
+ end
60
+
61
+ def navigation_list
62
+ tag.ul(safe_join(navigation_items), id: navigation_id, class: "#{brand}-service-navigation__list")
63
+ end
64
+
65
+ private
66
+
67
+ def outer_element(&block)
68
+ if service_name?
69
+ tag.section(**aria_attributes, **html_attributes, &block)
70
+ else
71
+ tag.div(**html_attributes, &block)
72
+ end
73
+ end
74
+
75
+ def default_attributes
76
+ { class: "#{brand}-service-navigation", data: { module: "#{brand}-service-navigation" } }
77
+ end
78
+
79
+ def aria_attributes
80
+ { aria: { label: aria_label_text } }
81
+ end
82
+
83
+ def menu_button
84
+ tag.button(
85
+ "Menu",
86
+ type: 'button',
87
+ class: ["#{brand}-service-navigation__toggle", "#{brand}-js-service-navigation-toggle"],
88
+ aria: { controls: navigation_id },
89
+ hidden: true
90
+ )
91
+ end
92
+ end
@@ -13,6 +13,7 @@ module GovukComponentsHelper
13
13
  govuk_pagination: 'GovukComponent::PaginationComponent',
14
14
  govuk_panel: 'GovukComponent::PanelComponent',
15
15
  govuk_phase_banner: 'GovukComponent::PhaseBannerComponent',
16
+ govuk_service_navigation: 'GovukComponent::ServiceNavigationComponent',
16
17
  govuk_section_break: 'GovukComponent::SectionBreakComponent',
17
18
  govuk_start_button: 'GovukComponent::StartButtonComponent',
18
19
  govuk_summary_list: 'GovukComponent::SummaryListComponent',
@@ -33,6 +33,7 @@ module Govuk
33
33
  # Default components configuration
34
34
  #
35
35
  # +:brand+ sets the value used to prefix all classes, used to allow the components to be branded for alternative (similar) design systems
36
+ # +:brand_overrides+ sets the value used to prefix classes and slots for the component class.
36
37
  # +:default_back_link_text+ Default text for the back link, defaults to +Back+
37
38
  # +:default_breadcrumbs_collapse_on_mobile+ false
38
39
  # +:default_breadcrumbs_hide_in_print+ false
@@ -75,6 +76,30 @@ module Govuk
75
76
  # +:enable_auto_table_scopes+ automatically adds a scope of 'col' to th elements in thead and 'row' to th elements in tbody.
76
77
  DEFAULTS = {
77
78
  brand: 'govuk',
79
+ brand_overrides: {
80
+ # 'GovukComponent::AccordionComponent' => 'another-brand',
81
+ # 'GovukComponent::BackLinkComponent' => 'another-brand',
82
+ # 'GovukComponent::BreadcrumbsComponent' => 'another-brand',
83
+ # 'GovukComponent::CookieBannerComponent' => 'another-brand',
84
+ # 'GovukComponent::DetailsComponent' => 'another-brand',
85
+ # 'GovukComponent::ExitThisPageComponent' => 'another-brand',
86
+ # 'GovukComponent::FooterComponent' => 'another-brand',
87
+ # 'GovukComponent::HeaderComponent' => 'another-brand',
88
+ # 'GovukComponent::InsetTextComponent' => 'another-brand',
89
+ # 'GovukComponent::NotificationBannerComponent' => 'another-brand',
90
+ # 'GovukComponent::PaginationComponent' => 'another-brand',
91
+ # 'GovukComponent::PanelComponent' => 'another-brand',
92
+ # 'GovukComponent::PhaseBannerComponent' => 'another-brand',
93
+ # 'GovukComponent::SectionBreakComponent' => 'another-brand',
94
+ # 'GovukComponent::ServiceNavigationComponent' => 'another-brand',
95
+ # 'GovukComponent::StartButtonComponent' => 'another-brand',
96
+ # 'GovukComponent::SummaryListComponent' => 'another-brand',
97
+ # 'GovukComponent::TableComponent' => 'another-brand',
98
+ # 'GovukComponent::TabComponent' => 'another-brand',
99
+ # 'GovukComponent::TagComponent' => 'another-brand',
100
+ # 'GovukComponent::TaskListComponent' => 'another-brand',
101
+ # 'GovukComponent::WarningTextComponent' => 'another-brand',
102
+ },
78
103
  default_back_link_text: 'Back',
79
104
  default_breadcrumbs_collapse_on_mobile: false,
80
105
  default_breadcrumbs_hide_in_print: false,
@@ -1,5 +1,5 @@
1
1
  module Govuk
2
2
  module Components
3
- VERSION = '5.5.0'.freeze
3
+ VERSION = '5.6.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk-components
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.0
4
+ version: 5.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DfE developers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-13 00:00:00.000000000 Z
11
+ date: 2024-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: html-attributes-utils
@@ -59,7 +59,7 @@ dependencies:
59
59
  version: '3.9'
60
60
  - - "<"
61
61
  - !ruby/object:Gem::Version
62
- version: '3.14'
62
+ version: '3.15'
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
@@ -69,7 +69,7 @@ dependencies:
69
69
  version: '3.9'
70
70
  - - "<"
71
71
  - !ruby/object:Gem::Version
72
- version: '3.14'
72
+ version: '3.15'
73
73
  - !ruby/object:Gem::Dependency
74
74
  name: deep_merge
75
75
  requirement: !ruby/object:Gem::Requirement
@@ -300,14 +300,14 @@ dependencies:
300
300
  requirements:
301
301
  - - "~>"
302
302
  - !ruby/object:Gem::Version
303
- version: 0.27.0
303
+ version: 0.28.0
304
304
  type: :development
305
305
  prerelease: false
306
306
  version_requirements: !ruby/object:Gem::Requirement
307
307
  requirements:
308
308
  - - "~>"
309
309
  - !ruby/object:Gem::Version
310
- version: 0.27.0
310
+ version: 0.28.0
311
311
  - !ruby/object:Gem::Dependency
312
312
  name: webrick
313
313
  requirement: !ruby/object:Gem::Requirement
@@ -360,6 +360,9 @@ files:
360
360
  - app/components/govuk_component/phase_banner_component.html.erb
361
361
  - app/components/govuk_component/phase_banner_component.rb
362
362
  - app/components/govuk_component/section_break_component.rb
363
+ - app/components/govuk_component/service_navigation_component.rb
364
+ - app/components/govuk_component/service_navigation_component/navigation_item_component.rb
365
+ - app/components/govuk_component/service_navigation_component/service_name_component.rb
363
366
  - app/components/govuk_component/start_button_component.rb
364
367
  - app/components/govuk_component/summary_list_component.rb
365
368
  - app/components/govuk_component/summary_list_component/action_component.rb