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,26 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Plain, bullet, or numbered list rendered by ds_list.
4
+ class ListComponent < DesignSystem::BaseComponent
5
+ def initialize(list:, type: :default, **options)
6
+ super()
7
+ @list = list
8
+ @type = type.to_sym
9
+ @options = options
10
+ end
11
+
12
+ attr_reader :list, :type, :options
13
+
14
+ def tag_name
15
+ type == :number ? :ol : :ul
16
+ end
17
+
18
+ def list_options
19
+ classes = ["#{brand}-list"]
20
+ classes << "#{brand}-list--bullet" if type == :bullet
21
+ classes << "#{brand}-list--number" if type == :number
22
+ css_class_options_merge(options, classes)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ <% success = type == :success %>
2
+ <div class="<%= brand %>-notification-banner<%= " #{brand}-notification-banner--success" if success %>"
3
+ role="<%= success ? 'alert' : 'region' %>"
4
+ aria-labelledby="<%= brand %>-notification-banner-title"
5
+ data-module="<%= brand %>-notification-banner">
6
+ <div class="<%= brand %>-notification-banner__header">
7
+ <h2 class="<%= brand %>-notification-banner__title" id="<%= brand %>-notification-banner-title"><%= success ? 'Success' : 'Important' %></h2>
8
+ </div>
9
+ <div class="<%= brand %>-notification-banner__content">
10
+ <% if heading_text.present? %>
11
+ <%= content_tag(heading_tag, heading_text, class: "#{brand}-notification-banner__heading") %>
12
+ <% end %>
13
+ <%= body %>
14
+ </div>
15
+ </div>
@@ -0,0 +1,39 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Notification banner rendered by ds_notice. Shows an "Important"/"Success"
4
+ # header followed by a content area with an optional heading and the
5
+ # message (or block) body.
6
+ class NotificationComponent < DesignSystem::BaseComponent
7
+ TYPES = %i[information success].freeze
8
+ HEADING_TAGS = %i[h3 p].freeze
9
+
10
+ def initialize(message: nil, type: :information, content_heading: {})
11
+ super()
12
+ @message = message
13
+ @type = type
14
+ @content_heading = content_heading || {}
15
+
16
+ return if TYPES.include?(type)
17
+
18
+ raise ArgumentError, "Invalid notification type: #{type}. Must be one of: #{TYPES.join(', ')}"
19
+ end
20
+
21
+ attr_reader :message, :type, :content_heading
22
+
23
+ def heading_tag
24
+ tag = content_heading.fetch(:tag, :h3)
25
+ raise ArgumentError, "Invalid content_heading tag: #{tag}." unless HEADING_TAGS.include?(tag)
26
+
27
+ tag
28
+ end
29
+
30
+ def heading_text
31
+ content_heading[:text]
32
+ end
33
+
34
+ def body
35
+ content.presence || message
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ <div class="<%= panel_classes.join(' ') %>">
2
+ <h1 class="<%= brand %>-panel__title"><%= title %></h1>
3
+ <div class="<%= brand %>-panel__body"><%= body %></div>
4
+ </div>
@@ -0,0 +1,18 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Confirmation/transaction panel rendered by ds_panel.
4
+ class PanelComponent < DesignSystem::BaseComponent
5
+ def initialize(title:, body:)
6
+ super()
7
+ @title = title
8
+ @body = body
9
+ end
10
+
11
+ attr_reader :title, :body
12
+
13
+ def panel_classes
14
+ ["#{brand}-panel"]
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,46 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Body paragraph with typography styling, rendered by ds_paragraph.
4
+ # Content can be passed as the `text` argument or as a block. An optional
5
+ # `size` selects a smaller body style.
6
+ class ParagraphComponent < DesignSystem::BaseComponent
7
+ FONT_SIZES = %i[s].freeze
8
+
9
+ def initialize(text: nil, size: nil, **options)
10
+ super()
11
+ @text = text
12
+ @size = size
13
+ @options = options
14
+ end
15
+
16
+ attr_reader :text, :size, :options
17
+
18
+ # Renders nothing when neither block content nor text is supplied,
19
+ # matching the previous builder behaviour.
20
+ def render?
21
+ body.present?
22
+ end
23
+
24
+ def call
25
+ content_tag(:p, body, **paragraph_options)
26
+ end
27
+
28
+ private
29
+
30
+ def body
31
+ content.presence || text
32
+ end
33
+
34
+ def paragraph_options
35
+ { class: classes }.merge(options)
36
+ end
37
+
38
+ def classes
39
+ return "#{brand}-body" if size.nil?
40
+ raise ArgumentError, "Invalid size: #{size}" unless size.in?(FONT_SIZES)
41
+
42
+ "#{brand}-body-#{size}"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,4 @@
1
+ <%= content_tag(:a, href: href, class: "#{brand}-button #{brand}-button--start",
2
+ role: 'button', draggable: 'false', **options) do %>
3
+ <span class="<%= brand %>-button-text"><%= text %></span><svg class="<%= brand %>-button__start-icon" xmlns="http://www.w3.org/2000/svg" width="17.5" height="19" viewBox="0 0 33 40" aria-hidden="true" focusable="false"><path fill="currentColor" d="M0 0h13l20 20-20 20H0l20-20z"></path></svg>
4
+ <% end %>
@@ -0,0 +1,17 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # The "start a service" CTA. GOV.UK defined the pattern and NHS adopted it
4
+ # unchanged — both brands ship identical markup with only the brand-derived
5
+ # CSS prefix differing, so the implementation lives here.
6
+ class StartButtonComponent < DesignSystem::BaseComponent
7
+ def initialize(text, href, options = {})
8
+ super()
9
+ @text = text
10
+ @href = href
11
+ @options = options.merge('data-module': "#{brand}-button")
12
+ end
13
+
14
+ attr_reader :text, :href, :options
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ <div class="<%= brand %>-card">
2
+ <div class="<%= brand %>-card__heading-container">
3
+ <%= ds_heading(title, class: "#{brand}-card__heading #{brand}-heading-m") %>
4
+ <% if actions.any? %>
5
+ <ul class="<%= brand %>-card__actions">
6
+ <% actions.each do |action| %>
7
+ <li class="<%= brand %>-card__action"><%= render_action(action) %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% end %>
11
+ </div>
12
+ <div class="<%= brand %>-card__content">
13
+ <%= content %>
14
+ </div>
15
+ </div>
@@ -0,0 +1,40 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Card that groups a titled summary list (or any content) with optional
4
+ # actions, rendered by ds_summary_card. The GOV.UK brand renders a
5
+ # summary-card variant via its own subclass and template.
6
+ #
7
+ # Each action is a hash of { text:, href:, hidden_text: }, where
8
+ # hidden_text is appended in a visually hidden span to give the link an
9
+ # accessible, unambiguous name (e.g. " (Karen Francis)").
10
+ class SummaryCardComponent < DesignSystem::BaseComponent
11
+ include DesignSystemHelper
12
+
13
+ def initialize(title:, actions: [])
14
+ super()
15
+ @title = title
16
+ @actions = Array(actions)
17
+ end
18
+
19
+ attr_reader :title, :actions
20
+
21
+ def render_action(action)
22
+ link_to(action[:href] || '#', class: "#{brand}-link") do
23
+ safe_join([action[:text], render_hidden_text(action[:hidden_text])])
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def render_hidden_text(hidden_text)
30
+ return '' if hidden_text.blank?
31
+
32
+ content_tag(:span, hidden_text, class: visually_hidden_class)
33
+ end
34
+
35
+ def visually_hidden_class
36
+ "#{brand}-u-visually-hidden"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ <dl class="<%= brand %>-summary-list">
2
+ <% summary_list.rows.each do |row| %>
3
+ <div class="<%= brand %>-summary-list__row<%= " #{brand}-summary-list__row--no-actions" if row[:actions].blank? %>">
4
+ <dt class="<%= brand %>-summary-list__key"><%= row[:key][:content] %></dt>
5
+ <dd class="<%= brand %>-summary-list__value"><%= value_content(row) %></dd>
6
+ <% if row[:actions].present? %>
7
+ <dd class="<%= brand %>-summary-list__actions">
8
+ <% if row[:actions].length == 1 %>
9
+ <%= render_action(row[:actions].first) %>
10
+ <% else %>
11
+ <ul class="<%= brand %>-summary-list__actions-list">
12
+ <% row[:actions].each do |action| %>
13
+ <li class="<%= brand %>-summary-list__actions-list-item"><%= render_action(action) %></li>
14
+ <% end %>
15
+ </ul>
16
+ <% end %>
17
+ </dd>
18
+ <% end %>
19
+ </div>
20
+ <% end %>
21
+ </dl>
@@ -0,0 +1,59 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Summary list (dl) rendered by ds_summary_list. Each row has a key, one
4
+ # or more values, and optional actions. Brands override paragraph class
5
+ # and hidden text via subclasses.
6
+ class SummaryListComponent < DesignSystem::BaseComponent
7
+ def initialize(summary_list:)
8
+ super()
9
+ @summary_list = summary_list
10
+ end
11
+
12
+ attr_reader :summary_list
13
+
14
+ def value_content(row)
15
+ if row[:values].blank?
16
+ ''
17
+ elsif row[:values].length == 1
18
+ wrap_value(row[:values].first)
19
+ else
20
+ safe_join(row[:values].map { |value| wrap_value(value, paragraph: true) })
21
+ end
22
+ end
23
+
24
+ def render_action(action)
25
+ options = action[:options].dup
26
+ path = options.delete(:path) || '#'
27
+ hidden_text = options.delete(:hidden_text)
28
+
29
+ link_to(path, { class: "#{brand}-link" }.merge(options)) do
30
+ safe_join([action[:content], render_hidden_text(hidden_text)])
31
+ end
32
+ end
33
+
34
+ def wrap_value(value, paragraph: false)
35
+ content = if value[:options]&.dig(:path)
36
+ link_to(value[:content], value[:options][:path] || '#', class: "#{brand}-link")
37
+ else
38
+ value[:content]
39
+ end
40
+
41
+ return content unless paragraph
42
+
43
+ content_tag(:p, content, class: value_paragraph_class)
44
+ end
45
+
46
+ private
47
+
48
+ def value_paragraph_class
49
+ "#{brand}-body"
50
+ end
51
+
52
+ def render_hidden_text(hidden_text)
53
+ return '' if hidden_text.blank?
54
+
55
+ content_tag(:span, hidden_text, class: "#{brand}-visually-hidden")
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,21 @@
1
+ <div class="<%= brand %>-tabs" data-module="<%= brand %>-tabs">
2
+ <% if tab.title %>
3
+ <h2 class="<%= brand %>-tabs__title"><%= tab.title %></h2>
4
+ <% end %>
5
+
6
+ <% if tab.tabs.present? %>
7
+ <ul class="<%= brand %>-tabs__list">
8
+ <% tab.tabs.each do |name, _content, id, selected| %>
9
+ <li class="<%= brand %>-tabs__list-item<%= " #{brand}-tabs__list-item--selected" if selected %>">
10
+ <a class="<%= brand %>-tabs__tab" href="#<%= id %>"><%= name %></a>
11
+ </li>
12
+ <% end %>
13
+ </ul>
14
+
15
+ <% tab.tabs.each do |_name, content, id, selected| %>
16
+ <div class="<%= brand %>-tabs__panel<%= " #{brand}-tabs__panel--hidden" unless selected %>" id="<%= id %>">
17
+ <%= content %>
18
+ </div>
19
+ <% end %>
20
+ <% end %>
21
+ </div>
@@ -0,0 +1,14 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Tabs rendered by ds_tab: a list of tab links followed by their panels,
4
+ # with the selected panel visible. Brand subclasses inherit unchanged.
5
+ class TabComponent < DesignSystem::BaseComponent
6
+ def initialize(tab:)
7
+ super()
8
+ @tab = tab
9
+ end
10
+
11
+ attr_reader :tab
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ module DesignSystem
2
+ module Generic
3
+ # Table rendered by ds_table. Wraps a caption, header row and body rows
4
+ # built via the Table data object. Brands override markup via their own
5
+ # templates; cell helpers live here for reuse.
6
+ class TableComponent < DesignSystem::BaseComponent
7
+ def initialize(table:, **options)
8
+ super()
9
+ @table = table
10
+ @options = options
11
+ end
12
+
13
+ attr_reader :table, :options
14
+
15
+ def cell_content(cell)
16
+ if cell[:content].is_a?(Numeric)
17
+ cell[:content].to_s
18
+ elsif cell[:content].is_a?(Proc)
19
+ capture(&cell[:content])
20
+ else
21
+ cell[:content]
22
+ end
23
+ end
24
+
25
+ def cell_numeric?(cell)
26
+ cell[:options][:type] == 'numeric'
27
+ end
28
+
29
+ def html_cell_options(cell, **extra)
30
+ cell[:options].except(:type).merge(extra)
31
+ end
32
+
33
+ def header_classes(cell)
34
+ classes = "#{brand}-table__header"
35
+ classes += " #{brand}-table__header--numeric" if cell_numeric?(cell)
36
+ classes
37
+ end
38
+
39
+ def data_cell_classes(cell)
40
+ classes = "#{brand}-table__cell"
41
+ classes += " #{brand}-table__cell--numeric" if cell_numeric?(cell)
42
+ classes
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1 @@
1
+ <%= link_to name, options, html_options.merge(class: "#{brand}-button") %>
@@ -0,0 +1,8 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ # GOV.UK doesn't have a dedicated action-link pattern, so we render a
4
+ # button-styled link.
5
+ class ActionLinkComponent < DesignSystem::Generic::ActionLinkComponent
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class AlertComponent < DesignSystem::Generic::AlertComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ <nav class="<%= brand %>-breadcrumbs" aria-label="Breadcrumb">
2
+ <ol class="<%= brand %>-breadcrumbs__list">
3
+ <% breadcrumbs.each do |breadcrumb| %>
4
+ <li class="<%= brand %>-breadcrumbs__list-item">
5
+ <%= link_to breadcrumb[:label], breadcrumb[:path],
6
+ class: "#{brand}-breadcrumbs__link",
7
+ 'aria-current': current_page_aria(breadcrumb) %>
8
+ </li>
9
+ <% end %>
10
+ </ol>
11
+ </nav>
@@ -0,0 +1,7 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ # GOV.UK 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 Govuk
3
+ class ButtonComponent < DesignSystem::Generic::ButtonComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ <div class="<%= brand %>-warning-text">
2
+ <span class="<%= brand %>-warning-text__icon" aria-hidden="true">!</span>
3
+ <strong class="<%= brand %>-warning-text__text">
4
+ <span class="<%= brand %>-visually-hidden">Warning</span><%= label %> <%= body %>
5
+ </strong>
6
+ </div>
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class CalloutComponent < DesignSystem::Generic::CalloutComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class DetailsComponent < DesignSystem::Generic::DetailsComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class GridComponent < DesignSystem::Generic::GridComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class HeadingComponent < DesignSystem::Generic::HeadingComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class InsetTextComponent < DesignSystem::Generic::InsetTextComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ # GOV.UK link: maps button :type values to govuk-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--inverse"
13
+ }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class ListComponent < DesignSystem::Generic::ListComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class NotificationComponent < DesignSystem::Generic::NotificationComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ # GOV.UK confirmation panel.
4
+ class PanelComponent < DesignSystem::Generic::PanelComponent
5
+ def panel_classes
6
+ super + ["#{brand}-panel--confirmation"]
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class ParagraphComponent < DesignSystem::Generic::ParagraphComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class StartButtonComponent < DesignSystem::Generic::StartButtonComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ <div class="<%= brand %>-summary-card">
2
+ <div class="<%= brand %>-summary-card__title-wrapper">
3
+ <%= ds_heading(title, class: "#{brand}-summary-card__title") %>
4
+ <% if actions.any? %>
5
+ <ul class="<%= brand %>-summary-card__actions">
6
+ <% actions.each do |action| %>
7
+ <li class="<%= brand %>-summary-card__action"><%= render_action(action) %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% end %>
11
+ </div>
12
+ <div class="<%= brand %>-summary-card__content">
13
+ <%= content %>
14
+ </div>
15
+ </div>
@@ -0,0 +1,13 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ # GOV.UK summary card: uses the summary-card block names and the
4
+ # govuk-visually-hidden class for action suffixes.
5
+ class SummaryCardComponent < DesignSystem::Generic::SummaryCardComponent
6
+ private
7
+
8
+ def visually_hidden_class
9
+ "#{brand}-visually-hidden"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class SummaryListComponent < DesignSystem::Generic::SummaryListComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class TabComponent < DesignSystem::Generic::TabComponent
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,30 @@
1
+ <%= content_tag(:div, **options) do %>
2
+ <table class="<%= brand %>-table">
3
+ <% if table.caption %>
4
+ <caption class="<%= brand %>-table__caption <%= brand %>-table__caption--m"><%= table.caption %></caption>
5
+ <% end %>
6
+ <thead class="<%= brand %>-table__head" role="rowgroup">
7
+ <tr class="<%= brand %>-table__row" role="row">
8
+ <% table.columns.each do |column| %>
9
+ <%= content_tag(:th, cell_content(column),
10
+ **html_cell_options(column, scope: 'col', class: header_classes(column))) %>
11
+ <% end %>
12
+ </tr>
13
+ </thead>
14
+ <tbody class="<%= brand %>-table__body">
15
+ <% table.rows.each do |row| %>
16
+ <tr class="<%= brand %>-table__row" role="row">
17
+ <% row.each_with_index do |cell, index| %>
18
+ <% if index.zero? %>
19
+ <%= content_tag(:th, cell_content(cell),
20
+ **html_cell_options(cell, scope: 'row', class: header_classes(cell))) %>
21
+ <% else %>
22
+ <%= content_tag(:td, cell_content(cell),
23
+ **html_cell_options(cell, class: data_cell_classes(cell))) %>
24
+ <% end %>
25
+ <% end %>
26
+ </tr>
27
+ <% end %>
28
+ </tbody>
29
+ </table>
30
+ <% end %>
@@ -0,0 +1,6 @@
1
+ module DesignSystem
2
+ module Govuk
3
+ class TableComponent < DesignSystem::Generic::TableComponent
4
+ end
5
+ end
6
+ end