govuk-components 5.5.0 → 5.6.0

Sign up to get free protection for your applications and to get access to all the features.
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