design_system 0.13.2 → 0.15.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.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -3
  3. data/app/assets/stylesheets/design_system/_hljs.scss +131 -0
  4. data/app/assets/stylesheets/design_system/govuk.scss +43 -0
  5. data/app/assets/stylesheets/design_system/nhsuk.scss +55 -0
  6. data/app/components/design_system/base_component.rb +21 -0
  7. data/app/components/design_system/generic/action_link_component.rb +17 -0
  8. data/app/components/design_system/generic/alert_component.rb +25 -0
  9. data/app/components/design_system/generic/breadcrumbs_component.rb +18 -0
  10. data/app/components/design_system/generic/button_component.rb +51 -0
  11. data/app/components/design_system/generic/callout_component.html.erb +8 -0
  12. data/app/components/design_system/generic/callout_component.rb +15 -0
  13. data/app/components/design_system/generic/details_component.html.erb +4 -0
  14. data/app/components/design_system/generic/details_component.rb +13 -0
  15. data/app/components/design_system/generic/grid_component.html.erb +5 -0
  16. data/app/components/design_system/generic/grid_component.rb +31 -0
  17. data/app/components/design_system/generic/heading_component.rb +41 -0
  18. data/app/components/design_system/generic/inset_text_component.html.erb +1 -0
  19. data/app/components/design_system/generic/inset_text_component.rb +24 -0
  20. data/app/components/design_system/generic/link_component.rb +51 -0
  21. data/app/components/design_system/generic/list_component.html.erb +7 -0
  22. data/app/components/design_system/generic/list_component.rb +26 -0
  23. data/app/components/design_system/generic/notification_component.html.erb +15 -0
  24. data/app/components/design_system/generic/notification_component.rb +39 -0
  25. data/app/components/design_system/generic/panel_component.html.erb +4 -0
  26. data/app/components/design_system/generic/panel_component.rb +18 -0
  27. data/app/components/design_system/generic/paragraph_component.rb +46 -0
  28. data/app/components/design_system/generic/start_button_component.html.erb +4 -0
  29. data/app/components/design_system/generic/start_button_component.rb +17 -0
  30. data/app/components/design_system/generic/summary_card_component.html.erb +15 -0
  31. data/app/components/design_system/generic/summary_card_component.rb +40 -0
  32. data/app/components/design_system/generic/summary_list_component.html.erb +21 -0
  33. data/app/components/design_system/generic/summary_list_component.rb +59 -0
  34. data/app/components/design_system/generic/tab_component.html.erb +21 -0
  35. data/app/components/design_system/generic/tab_component.rb +14 -0
  36. data/app/components/design_system/generic/table_component.rb +46 -0
  37. data/app/components/design_system/govuk/action_link_component.html.erb +1 -0
  38. data/app/components/design_system/govuk/action_link_component.rb +8 -0
  39. data/app/components/design_system/govuk/alert_component.rb +6 -0
  40. data/app/components/design_system/govuk/breadcrumbs_component.html.erb +11 -0
  41. data/app/components/design_system/govuk/breadcrumbs_component.rb +7 -0
  42. data/app/components/design_system/govuk/button_component.rb +6 -0
  43. data/app/components/design_system/govuk/callout_component.html.erb +6 -0
  44. data/app/components/design_system/govuk/callout_component.rb +6 -0
  45. data/app/components/design_system/govuk/details_component.rb +6 -0
  46. data/app/components/design_system/govuk/grid_component.rb +6 -0
  47. data/app/components/design_system/govuk/heading_component.rb +6 -0
  48. data/app/components/design_system/govuk/inset_text_component.rb +6 -0
  49. data/app/components/design_system/govuk/link_component.rb +17 -0
  50. data/app/components/design_system/govuk/list_component.rb +6 -0
  51. data/app/components/design_system/govuk/notification_component.rb +6 -0
  52. data/app/components/design_system/govuk/panel_component.rb +10 -0
  53. data/app/components/design_system/govuk/paragraph_component.rb +6 -0
  54. data/app/components/design_system/govuk/start_button_component.rb +6 -0
  55. data/app/components/design_system/govuk/summary_card_component.html.erb +15 -0
  56. data/app/components/design_system/govuk/summary_card_component.rb +13 -0
  57. data/app/components/design_system/govuk/summary_list_component.rb +6 -0
  58. data/app/components/design_system/govuk/tab_component.rb +6 -0
  59. data/app/components/design_system/govuk/table_component.html.erb +30 -0
  60. data/app/components/design_system/govuk/table_component.rb +6 -0
  61. data/app/components/design_system/nhsuk/action_link_component.html.erb +7 -0
  62. data/app/components/design_system/nhsuk/action_link_component.rb +7 -0
  63. data/app/components/design_system/nhsuk/alert_component.rb +6 -0
  64. data/app/components/design_system/nhsuk/breadcrumbs_component.html.erb +16 -0
  65. data/app/components/design_system/nhsuk/breadcrumbs_component.rb +7 -0
  66. data/app/components/design_system/nhsuk/button_component.rb +6 -0
  67. data/app/components/design_system/nhsuk/callout_component.rb +6 -0
  68. data/app/components/design_system/nhsuk/details_component.rb +6 -0
  69. data/app/components/design_system/nhsuk/grid_component.rb +6 -0
  70. data/app/components/design_system/nhsuk/heading_component.rb +6 -0
  71. data/app/components/design_system/nhsuk/inset_text_component.html.erb +4 -0
  72. data/app/components/design_system/nhsuk/inset_text_component.rb +6 -0
  73. data/app/components/design_system/nhsuk/link_component.rb +17 -0
  74. data/app/components/design_system/nhsuk/list_component.rb +6 -0
  75. data/app/components/design_system/nhsuk/notification_component.rb +6 -0
  76. data/app/components/design_system/nhsuk/panel_component.rb +6 -0
  77. data/app/components/design_system/nhsuk/paragraph_component.rb +6 -0
  78. data/app/components/design_system/nhsuk/start_button_component.rb +6 -0
  79. data/app/components/design_system/nhsuk/summary_card_component.rb +6 -0
  80. data/app/components/design_system/nhsuk/summary_list_component.rb +19 -0
  81. data/app/components/design_system/nhsuk/tab_component.rb +6 -0
  82. data/app/components/design_system/nhsuk/table_component.html.erb +43 -0
  83. data/app/components/design_system/nhsuk/table_component.rb +6 -0
  84. data/app/controllers/concerns/design_system/branded.rb +6 -0
  85. data/app/helpers/design_system_helper.rb +65 -27
  86. data/app/javascript/design_system/controllers/clipboard_controller.js +41 -0
  87. data/app/javascript/design_system/controllers/code_highlight_controller.js +9 -0
  88. data/app/javascript/design_system/controllers/hello_world_controller.js +6 -0
  89. data/app/javascript/design_system/index.js +4 -0
  90. data/app/views/layouts/govuk/application.html.erb +20 -7
  91. data/app/views/layouts/nhsuk/application.html.erb +10 -7
  92. data/lib/design_system/brand_derivable.rb +9 -0
  93. data/lib/design_system/engine.rb +1 -0
  94. data/lib/design_system/generic/builders/base.rb +1 -1
  95. data/lib/design_system/generic/builders/code.rb +23 -0
  96. data/lib/design_system/generic/builders/elements/breadcrumbs.rb +4 -24
  97. data/lib/design_system/generic/builders/elements/headings.rb +3 -2
  98. data/lib/design_system/generic/builders/pagination_renderer.rb +5 -4
  99. data/lib/design_system/generic.rb +1 -14
  100. data/lib/design_system/govuk/builders/code.rb +11 -0
  101. data/lib/design_system/govuk/builders/fixed_elements.rb +0 -1
  102. data/lib/design_system/govuk.rb +1 -12
  103. data/lib/design_system/nhsuk/builders/code.rb +11 -0
  104. data/lib/design_system/nhsuk/builders/fixed_elements.rb +0 -1
  105. data/lib/design_system/nhsuk.rb +1 -12
  106. data/lib/design_system/registry.rb +19 -1
  107. data/lib/design_system/version.rb +1 -1
  108. data/public/design_system/static/design_system-0.15.0/design_system.js +53150 -0
  109. metadata +101 -50
  110. data/lib/design_system/generic/builders/action_link.rb +0 -17
  111. data/lib/design_system/generic/builders/button.rb +0 -33
  112. data/lib/design_system/generic/builders/callout.rb +0 -28
  113. data/lib/design_system/generic/builders/concerns/brand_derivable.rb +0 -14
  114. data/lib/design_system/generic/builders/details.rb +0 -30
  115. data/lib/design_system/generic/builders/grid.rb +0 -44
  116. data/lib/design_system/generic/builders/heading.rb +0 -38
  117. data/lib/design_system/generic/builders/inset_text.rb +0 -18
  118. data/lib/design_system/generic/builders/link.rb +0 -44
  119. data/lib/design_system/generic/builders/list.rb +0 -41
  120. data/lib/design_system/generic/builders/notification.rb +0 -68
  121. data/lib/design_system/generic/builders/panel.rb +0 -18
  122. data/lib/design_system/generic/builders/paragraph.rb +0 -28
  123. data/lib/design_system/generic/builders/summary_list.rb +0 -89
  124. data/lib/design_system/generic/builders/tab.rb +0 -14
  125. data/lib/design_system/generic/builders/table.rb +0 -73
  126. data/lib/design_system/govuk/builders/action_link.rb +0 -17
  127. data/lib/design_system/govuk/builders/button.rb +0 -55
  128. data/lib/design_system/govuk/builders/callout.rb +0 -26
  129. data/lib/design_system/govuk/builders/details.rb +0 -10
  130. data/lib/design_system/govuk/builders/elements/breadcrumbs.rb +0 -33
  131. data/lib/design_system/govuk/builders/grid.rb +0 -12
  132. data/lib/design_system/govuk/builders/heading.rb +0 -11
  133. data/lib/design_system/govuk/builders/inset_text.rb +0 -11
  134. data/lib/design_system/govuk/builders/link.rb +0 -21
  135. data/lib/design_system/govuk/builders/list.rb +0 -11
  136. data/lib/design_system/govuk/builders/notification.rb +0 -11
  137. data/lib/design_system/govuk/builders/panel.rb +0 -18
  138. data/lib/design_system/govuk/builders/paragraph.rb +0 -11
  139. data/lib/design_system/govuk/builders/summary_list.rb +0 -32
  140. data/lib/design_system/govuk/builders/tab.rb +0 -54
  141. data/lib/design_system/govuk/builders/table.rb +0 -77
  142. data/lib/design_system/nhsuk/builders/action_link.rb +0 -30
  143. data/lib/design_system/nhsuk/builders/button.rb +0 -11
  144. data/lib/design_system/nhsuk/builders/callout.rb +0 -11
  145. data/lib/design_system/nhsuk/builders/details.rb +0 -10
  146. data/lib/design_system/nhsuk/builders/elements/breadcrumbs.rb +0 -43
  147. data/lib/design_system/nhsuk/builders/grid.rb +0 -12
  148. data/lib/design_system/nhsuk/builders/heading.rb +0 -11
  149. data/lib/design_system/nhsuk/builders/inset_text.rb +0 -23
  150. data/lib/design_system/nhsuk/builders/link.rb +0 -21
  151. data/lib/design_system/nhsuk/builders/list.rb +0 -11
  152. data/lib/design_system/nhsuk/builders/notification.rb +0 -11
  153. data/lib/design_system/nhsuk/builders/panel.rb +0 -11
  154. data/lib/design_system/nhsuk/builders/paragraph.rb +0 -11
  155. data/lib/design_system/nhsuk/builders/summary_list.rb +0 -18
  156. data/lib/design_system/nhsuk/builders/tab.rb +0 -11
  157. data/lib/design_system/nhsuk/builders/table.rb +0 -68
  158. data/public/design_system/static/design_system-0.13.2/design_system.js +0 -1309
@@ -0,0 +1,7 @@
1
+ <%= link_to options, html_options.merge(class: "#{brand}-action-link") do %>
2
+ <svg class="nhsuk-icon nhsuk-icon__arrow-right-circle" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" width="36" height="36">
3
+ <path d="M0 0h24v24H0z" fill="none"></path>
4
+ <path d="M12 2a10 10 0 0 0-9.95 9h11.64L9.74 7.05a1 1 0 0 1 1.41-1.41l5.66 5.65a1 1 0 0 1 0 1.42l-5.66 5.65a1 1 0 0 1-1.41 0 1 1 0 0 1 0-1.41L13.69 13H2.05A10 10 0 1 0 12 2z"></path>
5
+ </svg>
6
+ <span class="<%= brand %>-action-link__text"><%= name %></span>
7
+ <% end %>
@@ -0,0 +1,7 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ # NHS UK action link with arrow icon.
4
+ class ActionLinkComponent < DesignSystem::Generic::ActionLinkComponent
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class AlertComponent < DesignSystem::Generic::AlertComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ <nav aria-label="Breadcrumb" class="<%= brand %>-breadcrumb">
2
+ <ol class="<%= brand %>-breadcrumb__list">
3
+ <% breadcrumbs.each do |breadcrumb| %>
4
+ <li class="<%= brand %>-breadcrumb__list-item">
5
+ <%= link_to breadcrumb[:label], breadcrumb[:path],
6
+ class: "#{brand}-breadcrumb__link",
7
+ 'aria-current': current_page_aria(breadcrumb) %>
8
+ </li>
9
+ <% end %>
10
+ </ol>
11
+ <%= link_to breadcrumbs.last[:path],
12
+ class: "#{brand}-back-link",
13
+ 'aria-current': current_page_aria(breadcrumbs.last) do %>
14
+ <span class="<%= brand %>-u-visually-hidden">Back to</span> <%= breadcrumbs.last[:label] %>
15
+ <% end %>
16
+ </nav>
@@ -0,0 +1,7 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ # NHS breadcrumbs markup lives in the brand template.
4
+ class BreadcrumbsComponent < DesignSystem::Generic::BreadcrumbsComponent
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class ButtonComponent < DesignSystem::Generic::ButtonComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class CalloutComponent < DesignSystem::Generic::CalloutComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class DetailsComponent < DesignSystem::Generic::DetailsComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class GridComponent < DesignSystem::Generic::GridComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class HeadingComponent < DesignSystem::Generic::HeadingComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ <%= content_tag(:div, **inset_options) do %>
2
+ <span class="<%= brand %>-u-visually-hidden">Information: </span>
3
+ <%= content || content_tag(:p, text) %>
4
+ <% end %>
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class InsetTextComponent < DesignSystem::Generic::InsetTextComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ # NHS link: maps button :type values to nhsuk-button style classes.
4
+ class LinkComponent < DesignSystem::Generic::LinkComponent
5
+ private
6
+
7
+ def button_type_class_hash
8
+ {
9
+ button: "#{brand}-button",
10
+ secondary_button: "#{brand}-button #{brand}-button--secondary",
11
+ warning_button: "#{brand}-button #{brand}-button--warning",
12
+ reverse_button: "#{brand}-button #{brand}-button--reverse"
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class ListComponent < DesignSystem::Generic::ListComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class NotificationComponent < DesignSystem::Generic::NotificationComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class PanelComponent < DesignSystem::Generic::PanelComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class ParagraphComponent < DesignSystem::Generic::ParagraphComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class StartButtonComponent < DesignSystem::Generic::StartButtonComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class SummaryCardComponent < DesignSystem::Generic::SummaryCardComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ # NHS summary list: hidden action text uses the nhsuk-u-visually-hidden
4
+ # utility class.
5
+ class SummaryListComponent < DesignSystem::Generic::SummaryListComponent
6
+ private
7
+
8
+ def value_paragraph_class
9
+ nil
10
+ end
11
+
12
+ def render_hidden_text(hidden_text)
13
+ return '' if hidden_text.blank?
14
+
15
+ content_tag(:span, hidden_text, class: "#{brand}-u-visually-hidden")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class TabComponent < DesignSystem::Generic::TabComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,43 @@
1
+ <%= content_tag(:div, **options) do %>
2
+ <table class="<%= brand %>-table-responsive" role="table">
3
+ <% if table.caption %>
4
+ <caption class="<%= brand %>-table__caption">
5
+ <%= table.caption %>
6
+ </caption>
7
+ <% end %>
8
+ <thead class="<%= brand %>-table__head" role="rowgroup">
9
+ <tr class="<%= brand %>-table__row" role="row">
10
+ <% table.columns.each do |column| %>
11
+ <%= content_tag(:th, cell_content(column),
12
+ **html_cell_options(column, scope: 'col', class: header_classes(column),
13
+ role: 'columnheader')) %>
14
+ <% end %>
15
+ </tr>
16
+ </thead>
17
+ <tbody class="<%= brand %>-table__body">
18
+ <% table.rows.each do |row| %>
19
+ <tr class="<%= brand %>-table__row" role="row">
20
+ <% row.each_with_index do |cell, index| %>
21
+ <% if index.zero? %>
22
+ <%= content_tag(:th, **html_cell_options(cell, scope: 'row', class: header_classes(cell),
23
+ role: 'rowheader')) do %>
24
+ <%= content_tag(:span, table.columns[index][:content],
25
+ class: "#{brand}-table-responsive__heading",
26
+ aria: { hidden: true }) %>
27
+ <%= cell_content(cell) %>
28
+ <% end %>
29
+ <% else %>
30
+ <%= content_tag(:td, **html_cell_options(cell, class: data_cell_classes(cell),
31
+ role: 'cell')) do %>
32
+ <%= content_tag(:span, table.columns[index][:content],
33
+ class: "#{brand}-table-responsive__heading",
34
+ aria: { hidden: true }) %>
35
+ <%= cell_content(cell) %>
36
+ <% end %>
37
+ <% end %>
38
+ <% end %>
39
+ </tr>
40
+ <% end %>
41
+ </tbody>
42
+ </table>
43
+ <% end %>
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Nhsuk
3
+ class TableComponent < DesignSystem::Generic::TableComponent
4
+ end
5
+ end
6
+ end
@@ -7,6 +7,7 @@ module DesignSystem
7
7
  attr_reader :navigation_items
8
8
  attr_reader :footer_links
9
9
  attr_accessor :copyright_notice
10
+ attr_writer :govuk_footer_elements
10
11
 
11
12
  helper DesignSystemHelper
12
13
  end
@@ -15,6 +16,11 @@ module DesignSystem
15
16
  raise NotImplementedError, 'You need to implement #brand in your ApplicationController'
16
17
  end
17
18
 
19
+ # Hide the GOV.UK footer's Crown emblem, Open Government Licence and copyright logo if it is not yet a verified GOV.UK product
20
+ def govuk_footer_elements?
21
+ @govuk_footer_elements != :hidden
22
+ end
23
+
18
24
  def add_navigation_item(label, path, options = {})
19
25
  @navigation_items ||= []
20
26
  @navigation_items << { label:, path:, options: }
@@ -34,34 +34,43 @@ module DesignSystemHelper
34
34
  render(template: "layouts/#{brand}/#{design_system_layout}")
35
35
  end
36
36
 
37
- def ds_table(options = {}, &)
37
+ def ds_table(options = {}, &block)
38
38
  raise ArgumentError unless block_given?
39
39
 
40
- DesignSystem::Registry.builder(brand, 'table', self).render_table(options, &)
40
+ table = ::DesignSystem::Components::Table.new
41
+ block.call(table)
42
+ render ::DesignSystem::Registry.component(brand, :table).new(table:, **options)
41
43
  end
42
44
 
43
- def ds_summary_list(&)
45
+ def ds_summary_list(&block)
44
46
  raise ArgumentError unless block_given?
45
47
 
46
- DesignSystem::Registry.builder(brand, 'summary_list', self).render_summary_list(&)
48
+ summary_list = ::DesignSystem::Components::SummaryList.new
49
+ block.call(summary_list)
50
+ render ::DesignSystem::Registry.component(brand, :summary_list).new(summary_list:)
47
51
  end
48
52
 
49
- def ds_tab(&)
53
+ def ds_tab(&block)
50
54
  raise ArgumentError unless block_given?
51
55
 
52
- DesignSystem::Registry.builder(brand, 'tab', self).render_tabs(&)
56
+ tab = ::DesignSystem::Components::Tab.new(self)
57
+ block.call(tab)
58
+ render ::DesignSystem::Registry.component(brand, :tab).new(tab:)
53
59
  end
54
60
 
55
61
  def ds_start_button(text, href = '#', options = {})
56
- DesignSystem::Registry.builder(brand, 'button', self).render_start_button(text, href, options)
62
+ render DesignSystem::Registry.component(brand, :start_button).new(text, href, options)
57
63
  end
58
64
 
59
- def ds_button_tag(content_or_options = nil, options = nil, &)
60
- DesignSystem::Registry.builder(brand, 'button', self).render_button(content_or_options, options, &)
65
+ def ds_button_tag(content_or_options = nil, options = nil, &block)
66
+ component = DesignSystem::Registry.component(brand, :button).new(content_or_options, options)
67
+ render(component) { block ? capture(&block) : nil }
61
68
  end
62
69
 
63
- def ds_link_to(name = nil, options = nil, html_options = nil, &)
64
- DesignSystem::Registry.builder(brand, 'link', self).render_link_to(name, options, html_options, &)
70
+ def ds_link_to(name = nil, options = nil, html_options = nil, &block)
71
+ klass = DesignSystem::Registry.component(brand, :link)
72
+ component = klass.new(name, options, html_options, link_context: @link_context)
73
+ render(component) { block ? capture(&block) : nil }
65
74
  end
66
75
 
67
76
  def ds_pagination(collection = nil, options = {})
@@ -74,16 +83,22 @@ module DesignSystemHelper
74
83
  will_paginate(collection, defaults.merge!(options))
75
84
  end
76
85
 
77
- def ds_alert(message = nil, &)
78
- DesignSystem::Registry.builder(brand, 'notification', self).render_alert(message, &)
86
+ def ds_alert(message = nil, &block)
87
+ component = DesignSystem::Registry.component(brand, :alert).new(message)
88
+ render(component) { block ? capture(&block) : nil }
79
89
  end
80
90
 
81
- def ds_notice(message = nil, header: nil, type: :information, &)
82
- DesignSystem::Registry.builder(brand, 'notification', self).render_notice(message, header:, type:, &)
91
+ def ds_notice(message = nil, type: :information, content_heading: { text: nil, tag: :h3 }, &block)
92
+ previous_link_context = @link_context
93
+ @link_context = :notification_banner
94
+ component = DesignSystem::Registry.component(brand, :notification).new(message:, type:, content_heading:)
95
+ render(component) { block ? capture(&block) : nil }
96
+ ensure
97
+ @link_context = previous_link_context
83
98
  end
84
99
 
85
100
  def ds_heading(text, level: 2, **options)
86
- DesignSystem::Registry.builder(brand, 'heading', self).render_heading(text, level:, **options)
101
+ render DesignSystem::Registry.component(brand, :heading).new(text, level:, **options)
87
102
  end
88
103
 
89
104
  def ds_timeago(date, refresh_interval: 60_000, format: :long)
@@ -102,38 +117,61 @@ module DesignSystemHelper
102
117
  end
103
118
 
104
119
  def ds_panel(title, body)
105
- DesignSystem::Registry.builder(brand, 'panel', self).render_panel(title, body)
120
+ render DesignSystem::Registry.component(brand, :panel).new(title:, body:)
121
+ end
122
+
123
+ def ds_summary_card(title:, actions: [], &block)
124
+ component = DesignSystem::Registry.component(brand, :summary_card).new(title:, actions:)
125
+ render(component) { block ? capture(&block) : nil }
106
126
  end
107
127
 
108
128
  def ds_callout(label, body)
109
- DesignSystem::Registry.builder(brand, 'callout', self).render_callout(label, body)
129
+ render DesignSystem::Registry.component(brand, :callout).new(label:, body:)
110
130
  end
111
131
 
112
- def ds_details(summary_text, &)
132
+ def ds_details(summary_text, &block)
113
133
  raise ArgumentError unless block_given?
114
134
 
115
- DesignSystem::Registry.builder(brand, 'details', self).render_details(summary_text, &)
135
+ component = DesignSystem::Registry.component(brand, :details).new(summary_text)
136
+ render(component) { capture(&block) }
116
137
  end
117
138
 
118
139
  def ds_action_link(name = nil, options = nil, html_options = nil)
119
- DesignSystem::Registry.builder(brand, 'action_link', self).render_action_link(name, options, html_options)
140
+ render DesignSystem::Registry.component(brand, :action_link).new(name, options, html_options)
120
141
  end
121
142
 
122
- def ds_grid(options = {}, &)
143
+ def ds_grid(options = {}, &block)
123
144
  raise ArgumentError unless block_given?
124
145
 
125
- DesignSystem::Registry.builder(brand, 'grid', self).render_grid(options, &)
146
+ grid = ::DesignSystem::Components::Grid.new
147
+ block.call(grid)
148
+ render ::DesignSystem::Registry.component(brand, :grid).new(grid:, **options)
126
149
  end
127
150
 
128
151
  def ds_paragraph(text = nil, size: nil, **options, &block)
129
- DesignSystem::Registry.builder(brand, 'paragraph', self).render_paragraph(text, size:, **options, &block)
152
+ component = DesignSystem::Registry.component(brand, :paragraph).new(text:, size:, **options)
153
+ render(component) { block ? capture(&block) : nil }
130
154
  end
131
155
 
132
156
  def ds_list(type: :default, **options, &block)
133
- DesignSystem::Registry.builder(brand, 'list', self).render_list(type:, **options, &block)
157
+ raise ArgumentError, 'block required' unless block_given?
158
+
159
+ list_data = ::DesignSystem::Components::List.new
160
+ block.call(list_data)
161
+ render ::DesignSystem::Registry.component(brand, :list).new(list: list_data, type:, **options)
162
+ end
163
+
164
+ def ds_inset_text(text = nil, **options, &block)
165
+ component = DesignSystem::Registry.component(brand, :inset_text).new(text:, **options)
166
+ output = if block
167
+ render(component) { capture(&block) }
168
+ else
169
+ render(component)
170
+ end
171
+ output.presence
134
172
  end
135
173
 
136
- def ds_inset_text(text = nil, ...)
137
- DesignSystem::Registry.builder(brand, 'inset_text', self).render_inset_text(text, ...)
174
+ def ds_code(code, language)
175
+ DesignSystem::Registry.builder(brand, 'code', self).render_code(code, language)
138
176
  end
139
177
  end
@@ -0,0 +1,41 @@
1
+ // app/javascript/controllers/clipboard_controller.js
2
+ import { Controller } from '@hotwired/stimulus'
3
+
4
+ export default class extends Controller {
5
+ static targets = ['source', 'buttonText']
6
+
7
+ // Copies the selected text to the clipboard.
8
+ copy () {
9
+ if (navigator.clipboard && this.hasSourceTarget) {
10
+ // The selected text to be copied.
11
+ const copytext = this.sourceTarget.value || this.sourceTarget.innerText
12
+
13
+ navigator.clipboard.writeText(copytext)
14
+ .then(() => {
15
+ // Fired when the text is successfully copied to the clipboard.
16
+ this.showCopiedMessage()
17
+ }).catch(err => {
18
+ // Fired if an error occurs while copying the text to the clipboard.
19
+ console.error('Failed to copy text: ', err)
20
+ })
21
+ } else {
22
+ // Fired if the Clipboard API is not available or the source target is missing.
23
+ console.error('Clipboard API not available or source target missing')
24
+ }
25
+ }
26
+
27
+ showCopiedMessage () {
28
+ // The text to be displayed in the button.
29
+ this.buttonTextTarget.textContent = 'Copied!'
30
+
31
+ // The time interval after which the button text should be reset to "Copy".
32
+ const resetInterval = 2000
33
+
34
+ // Resets the button text to "Copy" after the specified time interval.
35
+ const resetButtonText = () => {
36
+ this.buttonTextTarget.textContent = 'Copy'
37
+ }
38
+
39
+ setTimeout(resetButtonText, resetInterval)
40
+ }
41
+ }
@@ -0,0 +1,9 @@
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import hljs from 'highlight.js'
3
+
4
+ // Connects to data-controller="code-highlight"
5
+ export default class extends Controller {
6
+ connect () {
7
+ hljs.highlightElement(this.element)
8
+ }
9
+ }
@@ -1,7 +1,13 @@
1
1
  import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  export default class extends Controller {
4
+ static targets = ['name', 'greeting']
5
+
4
6
  connect () {
5
7
  console.log('Hello from the Design System!')
6
8
  }
9
+
10
+ greet () {
11
+ this.greetingTarget.textContent = `Hello, ${this.nameTarget.value}!`
12
+ }
7
13
  }
@@ -1,10 +1,14 @@
1
1
  // Import and register all your controllers
2
+ import ClipboardController from './controllers/clipboard_controller'
3
+ import CodeHighlightController from './controllers/code_highlight_controller'
2
4
  import HelloWorldController from './controllers/hello_world_controller'
3
5
  import ShowPasswordController from './controllers/show_password_controller'
4
6
  import Timeago from '@stimulus-components/timeago'
5
7
 
6
8
  // Register design system controllers with Stimulus
7
9
  export const registerControllers = (application) => {
10
+ application.register('ds--clipboard', ClipboardController)
11
+ application.register('ds--code-highlight', CodeHighlightController)
8
12
  application.register('ds--hello-world', HelloWorldController)
9
13
  application.register('ds--show-password', ShowPasswordController)
10
14
  application.register('timeago', Timeago)
@@ -53,7 +53,7 @@
53
53
  <header class="govuk-header" data-module="govuk-header">
54
54
  <div class="govuk-header__container govuk-width-container">
55
55
  <div class="govuk-header__logo">
56
- <a href="#" class="govuk-header__link govuk-header__link--homepage">
56
+ <a href="<%= main_app.root_path %>" class="govuk-header__link govuk-header__link--homepage">
57
57
  <svg
58
58
  focusable="false"
59
59
  role="img"
@@ -120,12 +120,17 @@
120
120
  <%= yield :breadcrumbs %>
121
121
  <%= yield :backlink %>
122
122
  <main class="govuk-main-wrapper" id="main-content">
123
- <%= render :partial => 'layouts/alert_and_notice' %>
124
- <%= yield %>
123
+ <% if content_for?(:main_content_wrapper) %>
124
+ <%= yield :main_content_wrapper %>
125
+ <% else %>
126
+ <%= render :partial => 'layouts/alert_and_notice' %>
127
+ <%= yield %>
128
+ <% end %>
125
129
  </main>
126
130
  </div>
127
131
  <footer class="govuk-footer">
128
132
  <div class="govuk-width-container">
133
+ <% if controller.govuk_footer_elements? %>
129
134
  <svg
130
135
  focusable="false"
131
136
  role="presentation"
@@ -146,6 +151,7 @@
146
151
  <path d="M33.1,9.8c.2-.1.3-.3.5-.5l4.6,2.4v-6.8l-4.6,1.5c-.1-.2-.3-.3-.5-.5l1.9-5.9h-6.7l1.9,5.9c-.2.1-.3.3-.5.5l-4.6-1.5v6.8l4.6-2.4c.1.2.3.3.5.5l-2.6,8c-.9,2.8,1.2,5.7,4.1,5.7h0c3,0,5.1-2.9,4.1-5.7l-2.6-8ZM37,37.9s-3.4,3.8-4.1,6.1c2.2,0,4.2-.5,6.4-2.8l-.7,8.5c-2-2.8-4.4-4.1-5.7-3.8.1,3.1.5,6.7,5.8,7.2,3.7.3,6.7-1.5,7-3.8.4-2.6-2-4.3-3.7-1.6-1.4-4.5,2.4-6.1,4.9-3.2-1.9-4.5-1.8-7.7,2.4-10.9,3,4,2.6,7.3-1.2,11.1,2.4-1.3,6.2,0,4,4.6-1.2-2.8-3.7-2.2-4.2.2-.3,1.7.7,3.7,3,4.2,1.9.3,4.7-.9,7-5.9-1.3,0-2.4.7-3.9,1.7l2.4-8c.6,2.3,1.4,3.7,2.2,4.5.6-1.6.5-2.8,0-5.3l5,1.8c-2.6,3.6-5.2,8.7-7.3,17.5-7.4-1.1-15.7-1.7-24.5-1.7h0c-8.8,0-17.1.6-24.5,1.7-2.1-8.9-4.7-13.9-7.3-17.5l5-1.8c-.5,2.5-.6,3.7,0,5.3.8-.8,1.6-2.3,2.2-4.5l2.4,8c-1.5-1-2.6-1.7-3.9-1.7,2.3,5,5.2,6.2,7,5.9,2.3-.4,3.3-2.4,3-4.2-.5-2.4-3-3.1-4.2-.2-2.2-4.6,1.6-6,4-4.6-3.7-3.7-4.2-7.1-1.2-11.1,4.2,3.2,4.3,6.4,2.4,10.9,2.5-2.8,6.3-1.3,4.9,3.2-1.8-2.7-4.1-1-3.7,1.6.3,2.3,3.3,4.1,7,3.8,5.4-.5,5.7-4.2,5.8-7.2-1.3-.2-3.7,1-5.7,3.8l-.7-8.5c2.2,2.3,4.2,2.7,6.4,2.8-.7-2.3-4.1-6.1-4.1-6.1h10.6,0Z" />
147
152
  </g>
148
153
  </svg>
154
+ <% end %>
149
155
  <div class="govuk-footer__meta">
150
156
  <div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
151
157
  <h2 class="govuk-visually-hidden">Support links</h2>
@@ -160,6 +166,7 @@
160
166
  <% end %>
161
167
  <% end %>
162
168
  </ul>
169
+ <% if controller.govuk_footer_elements? %>
163
170
  <svg
164
171
  aria-hidden="true"
165
172
  focusable="false"
@@ -179,14 +186,20 @@
179
186
  href="https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/"
180
187
  rel="license">Open Government Licence v3.0</a>, except where otherwise stated
181
188
  </span>
189
+ <% end %>
190
+ <% if controller.copyright_notice.present? && !controller.govuk_footer_elements? %>
191
+ <div class="govuk-footer__meta-custom">
192
+ <%= controller.copyright_notice %>
193
+ </div>
194
+ <% end %>
182
195
  </div>
183
- <div class="govuk-footer__meta-item">
184
- <% if controller.copyright_notice.present? %>
196
+ <% if controller.copyright_notice.present? && controller.govuk_footer_elements? %>
197
+ <div class="govuk-footer__meta-item">
185
198
  <span class="govuk-footer__link govuk-footer__copyright-logo">
186
199
  <%= controller.copyright_notice %>
187
200
  </span>
188
- <% end %>
189
- </div>
201
+ </div>
202
+ <% end %>
190
203
  </div>
191
204
  </div>
192
205
  </footer>
@@ -30,7 +30,7 @@
30
30
 
31
31
  <div class="nhsuk-header__container nhsuk-width-container">
32
32
  <div class="nhsuk-header__service">
33
- <a class="nhsuk-header__service-logo nhsuk-header__link--service" href="/" aria-label="NHS homepage">
33
+ <a class="nhsuk-header__service-logo nhsuk-header__link--service" href="<%= main_app.root_path %>" aria-label="NHS homepage">
34
34
  <svg class="nhsuk-header__logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 80" height="40" width="100" focusable="false" role="img" aria-label="NHS">
35
35
  <title>NHS</title>
36
36
  <path fill="currentcolor" d="M200 0v80H0V0h200Zm-27.5 5.5c-14.5 0-29 5-29 22 0 10.2 7.7 13.5 14.7 16.3l.7.3c5.4 2 10.1 3.9 10.1 8.4 0 6.5-8.5 7.5-14 7.5s-12.5-1.5-16-3.5L135 70c5.5 2 13.5 3.5 20 3.5 15.5 0 32-4.5 32-22.5 0-19.5-25.5-16.5-25.5-25.5 0-5.5 5.5-6.5 12.5-6.5a35 35 0 0 1 14.5 3l4-13.5c-4.5-2-12-3-20-3Zm-131 2h-22l-14 65H22l9-45h.5l13.5 45h21.5l14-65H64l-9 45h-.5l-13-45Zm63 0h-18l-13 65h17l6-28H117l-5.5 28H129l13.5-65H125L119.5 32h-20l5-24.5Z" />
@@ -68,13 +68,16 @@
68
68
  <%= yield :backlink %>
69
69
 
70
70
  <main class="nhsuk-main-wrapper " id="maincontent" role="main">
71
- <%= render :partial => 'layouts/alert_and_notice' %>
72
- <div class="nhsuk-grid-row">
73
- <div class="nhsuk-grid-column-full">
74
- <%= yield %>
71
+ <% if content_for?(:main_content_wrapper) %>
72
+ <%= yield :main_content_wrapper %>
73
+ <% else %>
74
+ <%= render :partial => 'layouts/alert_and_notice' %>
75
+ <div class="nhsuk-grid-row">
76
+ <div class="nhsuk-grid-column-full">
77
+ <%= yield %>
78
+ </div>
75
79
  </div>
76
- </div>
77
-
80
+ <% end %>
78
81
  </main>
79
82
  </div>
80
83
 
@@ -0,0 +1,9 @@
1
+ module DesignSystem
2
+ # Mixin that derives the design-system brand name from the including class's
3
+ # second-level namespace (e.g. `DesignSystem::Govuk::PanelComponent` → `'govuk'`).
4
+ module BrandDerivable
5
+ def brand
6
+ self.class.name.split('::')[1].underscore
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,6 @@
1
1
  require 'action_dispatch/middleware/remote_ip'
2
2
  require 'stimulus-rails'
3
+ require 'view_component'
3
4
 
4
5
  module DesignSystem
5
6
  # This is the main engine class for the design system.
@@ -5,7 +5,7 @@ module DesignSystem
5
5
  module Builders
6
6
  # This is the base class for design system builders.
7
7
  class Base
8
- include DesignSystem::Generic::Builders::Concerns::BrandDerivable
8
+ include DesignSystem::BrandDerivable
9
9
  include DesignSystem::Helpers::CssHelper
10
10
 
11
11
  delegate :button_tag, :capture, :content_for, :content_tag, :link_to, :link_to_unless_current, to: :@context