dsfr-view-components 0.0.1 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -28
  3. data/app/components/dsfr_component/accordion_component/section_component.html.erb +15 -9
  4. data/app/components/dsfr_component/accordion_component/section_component.rb +11 -24
  5. data/app/components/dsfr_component/accordion_component.rb +5 -16
  6. data/app/components/dsfr_component/alert_component.rb +72 -5
  7. data/app/components/dsfr_component/badge_component.rb +30 -0
  8. data/app/components/dsfr_component/stepper_component.html.erb +18 -0
  9. data/app/components/dsfr_component/stepper_component.rb +26 -0
  10. data/app/components/dsfr_component/tag_component.rb +60 -31
  11. data/app/components/dsfr_component/tile_component.html.erb +19 -0
  12. data/app/components/dsfr_component/tile_component.rb +31 -0
  13. data/app/helpers/dsfr_components_helper.rb +11 -19
  14. data/app/helpers/dsfr_link_helper.rb +41 -90
  15. data/lib/dsfr/components/version.rb +1 -1
  16. data/lib/generators/dsfr_component/USAGE +28 -0
  17. data/lib/generators/dsfr_component/dsfr_component_generator.rb +50 -0
  18. data/lib/generators/dsfr_component/templates/component.haml.erb +13 -0
  19. data/lib/generators/dsfr_component/templates/component.rb.erb +32 -0
  20. data/lib/generators/dsfr_component/templates/component_helper.rb.erb +10 -0
  21. data/lib/generators/dsfr_component/templates/component_spec.rb.erb +5 -0
  22. metadata +84 -65
  23. data/app/components/dsfr_component/back_link_component.rb +0 -24
  24. data/app/components/dsfr_component/breadcrumbs_component.html.erb +0 -7
  25. data/app/components/dsfr_component/breadcrumbs_component.rb +0 -51
  26. data/app/components/dsfr_component/cookie_banner_component/message_component.rb +0 -62
  27. data/app/components/dsfr_component/cookie_banner_component.rb +0 -35
  28. data/app/components/dsfr_component/details_component.rb +0 -42
  29. data/app/components/dsfr_component/footer_component.html.erb +0 -49
  30. data/app/components/dsfr_component/footer_component.rb +0 -87
  31. data/app/components/dsfr_component/header_component.html.erb +0 -51
  32. data/app/components/dsfr_component/header_component.rb +0 -145
  33. data/app/components/dsfr_component/inset_text_component.rb +0 -28
  34. data/app/components/dsfr_component/notification_banner_component.html.erb +0 -14
  35. data/app/components/dsfr_component/notification_banner_component.rb +0 -93
  36. data/app/components/dsfr_component/pagination_component/adjacent_page.rb +0 -59
  37. data/app/components/dsfr_component/pagination_component/item.rb +0 -77
  38. data/app/components/dsfr_component/pagination_component/next_page.rb +0 -27
  39. data/app/components/dsfr_component/pagination_component/previous_page.rb +0 -21
  40. data/app/components/dsfr_component/pagination_component.rb +0 -129
  41. data/app/components/dsfr_component/panel_component.rb +0 -56
  42. data/app/components/dsfr_component/phase_banner_component.html.erb +0 -6
  43. data/app/components/dsfr_component/phase_banner_component.rb +0 -25
  44. data/app/components/dsfr_component/section_break_component.rb +0 -49
  45. data/app/components/dsfr_component/start_button_component.rb +0 -55
  46. data/app/components/dsfr_component/summary_list_component/action_component.rb +0 -42
  47. data/app/components/dsfr_component/summary_list_component/key_component.rb +0 -23
  48. data/app/components/dsfr_component/summary_list_component/row_component.rb +0 -57
  49. data/app/components/dsfr_component/summary_list_component/value_component.rb +0 -23
  50. data/app/components/dsfr_component/summary_list_component.html.erb +0 -5
  51. data/app/components/dsfr_component/summary_list_component.rb +0 -49
  52. data/app/components/dsfr_component/tab_component.html.erb +0 -11
  53. data/app/components/dsfr_component/tab_component.rb +0 -61
  54. data/app/components/dsfr_component/table_component/body_component.html.erb +0 -5
  55. data/app/components/dsfr_component/table_component/body_component.rb +0 -21
  56. data/app/components/dsfr_component/table_component/caption_component.rb +0 -37
  57. data/app/components/dsfr_component/table_component/cell_component.rb +0 -57
  58. data/app/components/dsfr_component/table_component/head_component.html.erb +0 -5
  59. data/app/components/dsfr_component/table_component/head_component.rb +0 -23
  60. data/app/components/dsfr_component/table_component/row_component.html.erb +0 -5
  61. data/app/components/dsfr_component/table_component/row_component.rb +0 -30
  62. data/app/components/dsfr_component/table_component.html.erb +0 -7
  63. data/app/components/dsfr_component/table_component.rb +0 -35
  64. data/app/components/dsfr_component/warning_text_component.rb +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13a375b911fee2a88bc620482b766be2d3348d0138d56f9f2cb2641f649e8d50
4
- data.tar.gz: 85f677a71346315a8c128f156b32c74b6436528bfa5ed98fcaf490d352fdeb71
3
+ metadata.gz: 35d3263e9f55cf1b2f6e8ed013475acb11322715f8982ae24d43d121a5268e30
4
+ data.tar.gz: 6eb24fccd1294b6096bef1cf43714654a4d9a89174ac7d74c3e4a3c5845487d3
5
5
  SHA512:
6
- metadata.gz: 6b10dd868701e33699626fa4753fd7a017128f87b91394c72100d24b014c16206e5285ca81778d045c025241c56a6a97805859b6af75d1c946ba917677818dc7
7
- data.tar.gz: e81ae1788e01bc3e24ec2cc07a4ccfd2cf8fef13fd6d6a5a865423cdf584d65a5303c0965681ff2a922e2cb50bc61bbffb3eca87f20c7cf4224bbd51a355ee06
6
+ metadata.gz: f158d2adc525722af4ff7b3d8819411f0821edba991fb68885ec9142ad819c8d12f380817807c810b48298f09ee5f0c204c611fa35ba6944f69605849f490bca
7
+ data.tar.gz: 0303b1cded5664bf372c160c27acb619bbbdfb196b276e1ea45596d9c6657bda599e6230b0cecf9ef9be991f2b008ff6b822c901945e7f02b2dc230fe9bfa31d
data/README.md CHANGED
@@ -1,37 +1,35 @@
1
1
  # Composants du DSFR
2
2
 
3
+ [![Tests](https://github.com/betagouv/dsfr-view-components/workflows/Tests/badge.svg)](https://github.com/betagouv/dsfr-view-components/actions?query=workflow%3ATests)
4
+ [![Gem Version](https://badge.fury.io/rb/dsfr-view-components.svg)](https://badge.fury.io/rb/dsfr-view-components)
5
+ [![Gem](https://img.shields.io/gem/dt/dsfr-view-components?logo=rubygems)](https://rubygems.org/gems/dsfr-view-components)
6
+ [![GitHub license](https://img.shields.io/github/license/betagouv/dsfr-view-components)](https://github.com/betagouv/dsfr-view-components/blob/main/LICENSE)
7
+ [![Rails](https://img.shields.io/badge/Rails-6.1.5%20%E2%95%B1%207.0.3-E16D6D)](https://weblog.rubyonrails.org/releases/)
8
+ [![Ruby](https://img.shields.io/badge/Ruby-2.7.6%20%20%E2%95%B1%203.0.3%20%20%E2%95%B1%203.1.2-E16D6D)](https://www.ruby-lang.org/en/downloads/)
9
+
10
+ [![Design Système de lʼÉtat](https://img.shields.io/badge/Design%20Système%20de%20lʼÉtat-1.8.4-brightgreen)](https://www.systeme-de-design.gouv.fr/)
11
+
3
12
  Cette gem fournit des composants pour le Design Système de l'État (DSFR) en s'appuyant sur le [framework ViewComponent](https://github.com/ViewComponent/view_component).
4
13
 
5
14
  C'est un fork de [govuk-components](https://github.com/DFE-Digital/govuk-components) qui propose l'équivalent pour le GOV.UK Design System.
6
15
 
7
- ⚠️ Cette gem est en cours de développement et n'est pas adaptée à un usage en production. N'hésitez pas à contribuer pour nous aider à avancer !
8
16
 
9
- [![Tests](https://github.com/betagouv/dsfr-view-components/workflows/Tests/badge.svg)](https://github.com/betagouv/dsfr-view-components/actions?query=workflow%3ATests)
17
+ ## Développement en cours ⚠️
10
18
 
11
- <!--
12
- [![Maintainability](https://api.codeclimate.com/v1/badges/cbcbc140f300b920d833/maintainability)](https://codeclimate.com/github/DFE-Digital/govuk-components/maintainability)
13
- [![Gem Version](https://badge.fury.io/rb/govuk-components.svg)](https://badge.fury.io/rb/govuk-components)
14
- [![Gem](https://img.shields.io/gem/dt/govuk-components?logo=rubygems)](https://rubygems.org/gems/govuk-components)
15
- [![Test Coverage](https://api.codeclimate.com/v1/badges/cbcbc140f300b920d833/test_coverage)](https://codeclimate.com/github/DFE-Digital/govuk-components/test_coverage)
16
- [![GitHub license](https://img.shields.io/github/license/DFE-Digital/govuk-components)](https://github.com/DFE-Digital/govuk-components/blob/main/LICENSE)
17
- [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-4.3.0-brightgreen)](https://design-system.service.gov.uk)
18
- [![Rails](https://img.shields.io/badge/Rails-6.1.5%20%E2%95%B1%207.0.3-E16D6D)](https://weblog.rubyonrails.org/releases/)
19
- [![Ruby](https://img.shields.io/badge/Ruby-2.7.6%20%20%E2%95%B1%203.0.3%20%20%E2%95%B1%203.1.2-E16D6D)](https://www.ruby-lang.org/en/downloads/)
19
+ Cette gem est en cours de développement et n'est pas encore
20
+ recommandée pour un usage en production.
20
21
 
21
- This gem provides a suite of reusable components for the [GOV.UK Design System](https://design-system.service.gov.uk/). It is intended to provide a lightweight alternative to the [GOV.UK Publishing Components](https://github.com/alphagov/dsfr_publishing_components) library and is built with GitHub’s [ViewComponent](https://github.com/github/view_component) framework.
22
+ N'hésitez pas à contribuer pour nous aider à avancer, un générateur de
23
+ composant est même fourni pour vous faciliter la tâche :
22
24
 
23
- It aims to implement the functionality from the original Nunjucks macros in a way that will feel more familiar to Rails developers. Blocks are preferred over strings of HTML, beneath the surface each component is just a Ruby object, everything is inheritable and overrideable.
25
+ ```sh
26
+ bin/rails g dsfr_component FancyButton --params title:String count:Integer
27
+ ```
24
28
 
25
29
  ## Documentation
26
30
 
27
- The gem comes with [a full guide](https://govuk-components.netlify.app/) that
28
- covers most aspects of day-to-day use, along with code and output examples. The
29
- examples in the guide (and the guide itself) are built using the components,
30
- so it will always be up to date.
31
-
32
- [![Netlify Status](https://api.netlify.com/api/v1/badges/d40a5a0a-b086-4c35-b046-97fbcbf9f219/deploy-status)](https://app.netlify.com/sites/govuk-components/deploys)
31
+ Un [guide complet est disponible](https://betagouv.github.io/dsfr-view-components/). Il contient des instructions pour l'installation et l'usage de cette gem. Les exemples présents éxecutent le code et seront donc toujours à jour.
33
32
 
34
- -->
35
33
 
36
34
  ## Composants disponibles
37
35
 
@@ -39,10 +37,10 @@ Cette gem a pour but de supporter tous les composants proposés par le Design Sy
39
37
 
40
38
  Les composants disponibles sont :
41
39
 
42
- - [ ] Accordéon - Accordion
40
+ - [x] Accordéon - Accordion
43
41
  - [ ] Ajout de fichier - File upload
44
- - [ ] Alertes - Alert
45
- - [ ] Badge
42
+ - [x] Alertes - Alert
43
+ - [x] Badge
46
44
  - [ ] Bandeau d'information importante
47
45
  - [ ] Barre de recherche - Search bar
48
46
  - [ ] Boutons - Buttons
@@ -59,10 +57,10 @@ Les composants disponibles sont :
59
57
  - [ ] Fil d'Ariane - Breadcrumb
60
58
  - [ ] Gestionnaire de consentement - Consent banner
61
59
  - [ ] Icônes de favoris - Favicons
62
- - [ ] Indicateur d'étape
60
+ - [x] Indicateur d'étape - Stepper
63
61
  - [ ] Interrupteur - Toggle switch
64
62
  - [ ] Lettre d'information et réseaux sociaux - Newsletter &amp; Follow us
65
- - [ ] Liens - Links
63
+ - [x] Liens - Links
66
64
  - [ ] Liens d'évitement - Skiplinks
67
65
  - [ ] Liste déroulante - Select
68
66
  - [ ] Menu latéral - Side menu
@@ -80,7 +78,7 @@ Les composants disponibles sont :
80
78
  - [ ] Tableau - Table
81
79
  - [ ] Tag
82
80
  - [ ] Téléchargement de fichier
83
- - [ ] Tuile - Tile
81
+ - [x] Tuile - Tile
84
82
 
85
83
  <!--
86
84
  This library also provides helpers for creating [links](https://govuk-components.netlify.app/helpers/link),
@@ -191,7 +189,12 @@ bundle install
191
189
  bundle exec rspec spec
192
190
  ```
193
191
 
194
- Lancer le guide de documentation :
192
+ Pour développer avec les tests en continu :
193
+ ```sh
194
+ bundle exec guard
195
+ ```
196
+
197
+ Lancer le guide de documentation :
195
198
 
196
199
  ```sh
197
200
  make watch-guide
@@ -207,7 +210,10 @@ bundle exec rails server
207
210
 
208
211
  Déployer une nouvelle version de la gem :
209
212
 
210
- TODO
213
+ ```sh
214
+ VERSION=1.3.2 make deploy_gem
215
+ ```
216
+
211
217
 
212
218
  ## Licence
213
219
 
@@ -1,11 +1,17 @@
1
- <%= tag.div(id: id(suffix: 'section'), **html_attributes) do %>
2
- <div class="govuk-accordion__section-header">
3
- <%= content_tag(heading_level, class: "govuk-accordion__section-heading") do %>
4
- <%= tag.span(heading_content, id: id, class: "govuk-accordion__section-button", aria: { expanded: expanded?, controls: id(suffix: 'content') }) %>
5
- <% end %>
6
- <% if summary_content.present? %>
7
- <%= tag.div(summary_content, id: id(suffix: 'summary'), class: %w(govuk-accordion__section-summary govuk-body)) %>
8
- <% end %>
1
+ <%= tag.section(**html_attributes) do %>
2
+ <h3 class="fr-accordion__title">
3
+ <button
4
+ class="fr-accordion__btn"
5
+ aria-expanded="<%= expanded? ? "true" : "false" %>"
6
+ aria-controls="<%= id %>"
7
+ >
8
+ <%= title %>
9
+ </button>
10
+ </h3>
11
+ <div
12
+ id="<%= id %>"
13
+ class="fr-collapse <%= "fr-collapse--expanded" if expanded? %>"
14
+ >
15
+ <%= content %>
9
16
  </div>
10
- <%= tag.div(content, id: id(suffix: 'content'), class: %w(govuk-accordion__section-content), aria: { labelledby: id }) %>
11
17
  <% end %>
@@ -1,39 +1,26 @@
1
1
  class DsfrComponent::AccordionComponent::SectionComponent < DsfrComponent::Base
2
- attr_reader :heading_text, :summary_text, :expanded, :heading_level
3
-
4
- renders_one :heading_html
5
- renders_one :summary_html
2
+ attr_reader :title, :expanded
6
3
 
7
4
  alias_method :expanded?, :expanded
8
5
 
9
- def initialize(heading_text:, summary_text:, expanded:, heading_level:, classes: [], html_attributes: {})
10
- @heading_text = heading_text
11
- @summary_text = summary_text
12
- @expanded = expanded
13
- @heading_level = heading_level
6
+ # @param title [String] section title
7
+ # @param expanded [Boolean] toggles section folding
8
+ # @param id [String] the HTML id, optional if you want to reuse the anchor
9
+ def initialize(title:, expanded: false, id: nil, classes: [], html_attributes: {})
10
+ @title = title
11
+ @expanded = expanded
12
+ @id = id
14
13
 
15
14
  super(classes: classes, html_attributes: html_attributes)
16
15
  end
17
16
 
18
- def id(suffix: nil)
19
- # generate a random number if we don't have heading_text to avoid attempting
20
- # to parameterize a potentially-huge chunk of HTML
21
- @prefix ||= heading_text&.parameterize || SecureRandom.hex(4)
22
-
23
- [@prefix, suffix].compact.join('-')
24
- end
25
-
26
- def heading_content
27
- heading_html || heading_text || fail(ArgumentError, "no heading_text or heading_html")
28
- end
29
-
30
- def summary_content
31
- summary_html || summary_text
17
+ def id
18
+ @id ||= "accordion-section-#{SecureRandom.hex(4)}"
32
19
  end
33
20
 
34
21
  private
35
22
 
36
23
  def default_attributes
37
- { class: class_names("govuk-accordion__section", "govuk-accordion__section--expanded" => expanded?).split }
24
+ { class: class_names("fr-accordion").split }
38
25
  end
39
26
  end
@@ -1,33 +1,22 @@
1
1
  class DsfrComponent::AccordionComponent < DsfrComponent::Base
2
- renders_many :sections, ->(heading_text: nil, summary_text: nil, expanded: false, classes: [], html_attributes: {}, &block) do
2
+ renders_many :sections, ->(title: nil, expanded: false, id: nil, classes: [], html_attributes: {}, &block) do
3
3
  DsfrComponent::AccordionComponent::SectionComponent.new(
4
4
  classes: classes,
5
5
  expanded: expanded,
6
- heading_level: heading_level, # set once at parent level, passed to all children
7
6
  html_attributes: html_attributes,
8
- summary_text: summary_text,
9
- heading_text: heading_text,
7
+ title: title,
8
+ id: id,
10
9
  &block
11
10
  )
12
11
  end
13
12
 
14
- attr_reader :id, :heading_level
15
-
16
- def initialize(heading_level: 2, classes: [], html_attributes: {})
17
- @heading_level = heading_tag(heading_level)
18
-
13
+ def initialize(classes: [], html_attributes: {})
19
14
  super(classes: classes, html_attributes: html_attributes)
20
15
  end
21
16
 
22
17
  private
23
18
 
24
19
  def default_attributes
25
- { class: %w(govuk-accordion), data: { module: 'govuk-accordion' } }
26
- end
27
-
28
- def heading_tag(level)
29
- fail(ArgumentError, "heading_level must be 1-6") unless level.in?(1..6)
30
-
31
- %(h#{level})
20
+ { class: %w(fr-accordions-group) }
32
21
  end
33
22
  end
@@ -1,22 +1,89 @@
1
1
  class DsfrComponent::AlertComponent < DsfrComponent::Base
2
- attr_reader :title
2
+ TYPES = %i[error success info warning].freeze
3
+ SIZES = %i[sm md].freeze
3
4
 
4
- def initialize(title:, classes: [], html_attributes: {})
5
+ # @param type [Symbol] alert type (and matching color) `:success`, `:info`, `:warning` ou `:error`
6
+ # @param title [String] alert title. cannot be set in size `:sm`
7
+ # @param size [Symbol] alert size : `:md` (default) or `:sm`
8
+ # @param close_button [Boolean] display a close button to remove the alert
9
+ # @note in size MD the title is required but the content is optional. In size SM there should be not title but the content is required
10
+ def initialize(type:, title: nil, size: :md, close_button: false, classes: [], html_attributes: {})
5
11
  @title = title
12
+ @type = type
13
+ @size = size
14
+ @close_button = close_button
6
15
 
7
16
  super(classes: classes, html_attributes: html_attributes)
8
17
  end
9
18
 
10
19
  def call
20
+ raise ArgumentError, "SM alerts cannot have titles but must have a content" if @size == :sm && (@title.present? || content.blank?)
21
+ raise ArgumentError, "MD Alerts must have a title" if @size == :md && @title.blank?
22
+
11
23
  tag.div(**html_attributes) do
12
- tag.h3(class: "fr-alert__title") { title }
13
- tag.p { content }
24
+ safe_join([title_tag, content_tag, close_button_tag])
14
25
  end
15
26
  end
16
27
 
17
28
  private
18
29
 
30
+ attr_reader :title, :type, :size, :close_button
31
+
19
32
  def default_attributes
20
- { class: %w(fr-alert) }
33
+ { class: %w(fr-alert) + [type_class, size_class].compact }
34
+ end
35
+
36
+ def title_tag
37
+ return nil if title.blank?
38
+
39
+ tag.h3(class: "fr-alert__title") { title }
40
+ end
41
+
42
+ def content_tag
43
+ return nil if content.blank?
44
+
45
+ tag.p { content }
46
+ end
47
+
48
+ def close_button_tag
49
+ return nil unless close_button
50
+
51
+ tag.button(
52
+ class: "fr-btn--close fr-btn",
53
+ title: "Masquer le message",
54
+ onclick: "const alert = this.parentNode; alert.parentNode.removeChild(alert)"
55
+ ) do
56
+ "Masquer le message"
57
+ end
58
+ end
59
+
60
+ def type_class
61
+ fail(ArgumentError, type_error_message) unless valid_type?
62
+
63
+ "fr-alert--#{type}"
64
+ end
65
+
66
+ def valid_type?
67
+ type.in?(TYPES)
68
+ end
69
+
70
+ def type_error_message
71
+ "invalid alert type #{type}, supported types are #{TYPES.to_sentence}"
72
+ end
73
+
74
+ def size_class
75
+ return nil if size == :md
76
+
77
+ fail(ArgumentError, size_error_message) unless valid_size?
78
+
79
+ "fr-alert--#{size}"
80
+ end
81
+
82
+ def valid_size?
83
+ size.in?(SIZES)
84
+ end
85
+
86
+ def size_error_message
87
+ "invalid alert size #{size}, supported sizes are #{SIZES.to_sentence}"
21
88
  end
22
89
  end
@@ -0,0 +1,30 @@
1
+ module DsfrComponent
2
+ class BadgeComponent < DsfrComponent::Base
3
+ STATUSES = %i[success error info warning new].freeze
4
+
5
+ # @param status [BadgeComponent::STATUSES]
6
+ def initialize(status:, classes: [], html_attributes: {})
7
+ raise(ArgumentError, "`status` should be one of #{STATUSES}") unless STATUSES.include?(status)
8
+
9
+ @status = status
10
+
11
+ classes.push("fr-badge--#{@status}")
12
+
13
+ super(classes: classes, html_attributes: html_attributes)
14
+ end
15
+
16
+ def call
17
+ tag.div(**html_attributes) do
18
+ content
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :status
25
+
26
+ def default_attributes
27
+ { class: 'fr-badge' }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ <%= tag.div(**html_attributes) do %>
2
+ <h2 class="fr-stepper__title">
3
+ <span class="fr-stepper__state">
4
+ Étape <%= value %> sur <%= max %>
5
+ </span>
6
+ <%= title %>
7
+ </h2>
8
+ <div
9
+ class="fr-stepper__steps"
10
+ data-fr-current-step="<%= value %>"
11
+ data-fr-steps="<%= max %>"></div>
12
+ <% if next_title %>
13
+ <p class="fr-stepper__details">
14
+ <span class="fr-text--bold">Étape suivante :</span>
15
+ <%= next_title %>
16
+ </p>
17
+ <% end %>
18
+ <% end %>
@@ -0,0 +1,26 @@
1
+ module DsfrComponent
2
+ class StepperComponent < DsfrComponent::Base
3
+ # @param title [String] Titre de l’étape en cours
4
+ # @param value [Integer] Numéro de l’étape en cours (commence à 1)
5
+ # @param max [Integer] Nombre d’étapes total
6
+ # @param next_title [String] Titre de l’étape suivante (sauf pour la dernière étape)
7
+ def initialize(title:, value:, max:, next_title: nil, classes: [], html_attributes: {})
8
+ @title = title
9
+ @value = value
10
+ @max = max
11
+ @next_title = next_title
12
+
13
+ raise ArgumentError, "Les étapes doivent aller de 1 jusqu´à 8 au maximum" if @value < 1 || @value > @max || @max > 8
14
+
15
+ super(classes: classes, html_attributes: html_attributes)
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :title, :value, :max, :next_title
21
+
22
+ def default_attributes
23
+ { class: 'fr-stepper' }
24
+ end
25
+ end
26
+ end
@@ -1,44 +1,73 @@
1
- class DsfrComponent::TagComponent < DsfrComponent::Base
2
- attr_reader :text, :colour
1
+ module DsfrComponent
2
+ class TagComponent < DsfrComponent::Base
3
+ SIZES = %i[sm md].freeze
3
4
 
4
- COLOURS = %w(grey green turquoise blue red purple pink orange yellow).freeze
5
+ # @param title [String] tag title
6
+ # @param icon [String] icon name (optional)
7
+ # @param size [Symbol] tag size : `:md` (default) or `:sm` (optional)
8
+ # @param url [String] for clickable tags only (optional)
9
+ # @param selected [Boolean] adds a check, useful for filters list, cannot be used with `url` (optional)
10
+ # @param dismissable [Boolean] adds a close icon on the right, cannot be used with `url` or `icon` (optional)
11
+ def initialize(title:, icon: nil, size: nil, url: nil, selected: nil, dismissable: nil, classes: [], html_attributes: {})
12
+ @title = title
13
+ @icon = icon
14
+ @size = size
15
+ @url = url
16
+ @selected = selected
17
+ @dismissable = dismissable
5
18
 
6
- def initialize(text: nil, colour: config.default_tag_colour, classes: [], html_attributes: {})
7
- @text = text
8
- @colour = colour
19
+ super(classes: classes, html_attributes: html_attributes)
20
+ end
9
21
 
10
- super(classes: classes, html_attributes: html_attributes)
11
- end
22
+ def call
23
+ validate_size && validate_selected && validate_dismissable
24
+ tag.send(tag_name, **html_attributes) { title }
25
+ end
12
26
 
13
- def call
14
- tag.strong(tag_content, **html_attributes)
15
- end
27
+ private
16
28
 
17
- private
29
+ attr_reader :title, :icon, :size, :url, :selected, :dismissable
18
30
 
19
- def tag_content
20
- @text || content || fail(ArgumentError, "no text or content")
21
- end
31
+ def validate_size
32
+ raise(ArgumentError, "`size` should be one of #{SIZES}") if size.present? && SIZES.exclude?(size)
33
+ end
22
34
 
23
- def default_attributes
24
- {
25
- class: ["govuk-tag", colour_class]
26
- }
27
- end
35
+ def validate_selected
36
+ raise ArgumentError, "selected cannot be used together with an URL" if !selected.nil? && url.present?
37
+ end
28
38
 
29
- def colour_class
30
- return nil if colour.blank?
39
+ def validate_dismissable
40
+ raise ArgumentError, "dismissable cannot be used together with url or icon" if \
41
+ dismissable && (url.present? || icon.present?)
42
+ end
31
43
 
32
- fail(ArgumentError, colour_error_message) unless valid_colour?
44
+ def default_attributes
45
+ attrs = { class: css_classes }
46
+ attrs.merge!(href: url, target: "_self") if url.present?
47
+ unless selected.nil? # meaningful when false
48
+ aria_pressed = selected ? "true" : "false"
49
+ attrs.merge!("aria-pressed": aria_pressed)
50
+ end
51
+ attrs.merge!("aria-label": "Retirer #{title}") if dismissable
52
+ attrs
53
+ end
33
54
 
34
- %(govuk-tag--#{colour})
35
- end
36
-
37
- def valid_colour?
38
- @colour.in?(COLOURS)
39
- end
55
+ def css_classes
56
+ classes = %w[fr-tag]
57
+ classes += %W[fr-fi-#{icon} fr-tag--icon-left] if icon.present?
58
+ classes << "fr-tag--sm" if size == :sm
59
+ classes << "fr-tag--dismiss" if dismissable
60
+ classes
61
+ end
40
62
 
41
- def colour_error_message
42
- "invalid tag colour #{colour}, supported colours are #{COLOURS.to_sentence}"
63
+ def tag_name
64
+ if url.present?
65
+ :a
66
+ elsif !selected.nil? || dismissable
67
+ :button
68
+ else
69
+ :p
70
+ end
71
+ end
43
72
  end
44
73
  end
@@ -0,0 +1,19 @@
1
+ <%= tag.div(**html_attributes) do %>
2
+ <div class="fr-tile__body">
3
+ <h4 class="fr-tile__title">
4
+ <a class="fr-tile__link" href="<%= url %>">
5
+ <%= title %>
6
+ </a>
7
+ </h4>
8
+ <% if description.present? %>
9
+ <p class="fr-tile__desc">
10
+ <%= description %>
11
+ </p>
12
+ <% end %>
13
+ </div>
14
+ <% if image_src.present? %>
15
+ <div class="fr-tile__img">
16
+ <img src="<%= image_src %>" class="fr-responsive-img" alt="<%= image_alt %>">
17
+ </div>
18
+ <% end %>
19
+ <% end %>
@@ -0,0 +1,31 @@
1
+ module DsfrComponent
2
+ class TileComponent < DsfrComponent::Base
3
+ # @param title [String] title (required)
4
+ # @param url [String] url (required)
5
+ # @param image_src [String] chemin vers l'image (optional)
6
+ # @param image_alt [String] L'alternative de l'image. Doit a priori être vide si l'image est illustrative et n'apporte pas de valeur sémantique.
7
+ # @param description [String] description (optional)
8
+ # @param orientation [String] :horizontal or :vertical
9
+ def initialize(title:, url:, image_src: nil, image_alt: "", description: nil, orientation: :vertical, classes: [], html_attributes: {})
10
+ @title = title
11
+ @url = url
12
+ @image_src = image_src
13
+ @image_alt = image_alt
14
+ @description = description
15
+ @orientation = orientation
16
+ @background = background
17
+
18
+ super(classes: classes, html_attributes: html_attributes)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :title, :url, :image_src, :image_alt, :description, :orientation, :background
24
+
25
+ def default_attributes
26
+ k = %w[fr-tile fr-enlarge-link]
27
+ k << "fr-tile--horizontal" if orientation.to_sym == :horizontal
28
+ { class: k.join(" ") }
29
+ end
30
+ end
31
+ end
@@ -1,25 +1,16 @@
1
+ # rubocop:disable Style/TrailingCommaInHashLiteral
1
2
  module DsfrComponentsHelper
2
- {
3
+ HELPER_NAME_TO_CLASS_NAME = {
4
+ dsfr_alert: 'DsfrComponent::AlertComponent',
3
5
  dsfr_accordion: 'DsfrComponent::AccordionComponent',
4
- dsfr_back_link: 'DsfrComponent::BackLinkComponent',
5
- dsfr_breadcrumbs: 'DsfrComponent::BreadcrumbsComponent',
6
- dsfr_cookie_banner: 'DsfrComponent::CookieBannerComponent',
7
- dsfr_details: 'DsfrComponent::DetailsComponent',
8
- dsfr_footer: 'DsfrComponent::FooterComponent',
9
- dsfr_header: 'DsfrComponent::HeaderComponent',
10
- dsfr_inset_text: 'DsfrComponent::InsetTextComponent',
11
- dsfr_notification_banner: 'DsfrComponent::NotificationBannerComponent',
12
- dsfr_pagination: 'DsfrComponent::PaginationComponent',
13
- dsfr_panel: 'DsfrComponent::PanelComponent',
14
- dsfr_phase_banner: 'DsfrComponent::PhaseBannerComponent',
15
- dsfr_section_break: 'DsfrComponent::SectionBreakComponent',
16
- dsfr_start_button: 'DsfrComponent::StartButtonComponent',
17
- dsfr_summary_list: 'DsfrComponent::SummaryListComponent',
18
- dsfr_table: 'DsfrComponent::TableComponent',
19
- dsfr_tabs: 'DsfrComponent::TabComponent',
6
+ dsfr_accordion_section: 'DsfrComponent::AccordionComponent::SectionComponent',
7
+ dsfr_tile: 'DsfrComponent::TileComponent',
8
+ dsfr_badge: 'DsfrComponent::BadgeComponent',
20
9
  dsfr_tag: 'DsfrComponent::TagComponent',
21
- dsfr_warning_text: 'DsfrComponent::WarningTextComponent',
22
- }.each do |name, klass|
10
+ dsfr_stepper: 'DsfrComponent::StepperComponent',
11
+ # DO NOT REMOVE: new component mapping here
12
+ }.freeze
13
+ HELPER_NAME_TO_CLASS_NAME.each do |name, klass|
23
14
  define_method(name) do |*args, **kwargs, &block|
24
15
  capture do
25
16
  render(klass.constantize.new(*args, **kwargs)) do |com|
@@ -29,5 +20,6 @@ module DsfrComponentsHelper
29
20
  end
30
21
  end
31
22
  end
23
+ # rubocop:enable Style/TrailingCommaInHashLiteral
32
24
 
33
25
  ActiveSupport.on_load(:action_view) { include DsfrComponentsHelper }