dsfr-view-components 0.0.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +47 -123
- data/app/components/dsfr_component/accordion_component/section_component.html.erb +15 -9
- data/app/components/dsfr_component/accordion_component/section_component.rb +11 -24
- data/app/components/dsfr_component/accordion_component.rb +5 -16
- data/app/components/dsfr_component/alert_component.rb +72 -5
- data/app/components/dsfr_component/badge_component.rb +30 -0
- data/app/components/dsfr_component/base.rb +2 -0
- data/app/components/dsfr_component/button_component.rb +63 -0
- data/app/components/dsfr_component/header_component/direct_link_component.rb +22 -0
- data/app/components/dsfr_component/header_component/direct_link_dropdown_component.rb +34 -0
- data/app/components/dsfr_component/header_component/tool_link_component.rb +20 -0
- data/app/components/dsfr_component/header_component.html.erb +80 -37
- data/app/components/dsfr_component/header_component.rb +17 -135
- data/app/components/dsfr_component/modal_component.html.erb +30 -0
- data/app/components/dsfr_component/modal_component.rb +33 -0
- data/app/components/dsfr_component/stepper_component.html.erb +18 -0
- data/app/components/dsfr_component/stepper_component.rb +26 -0
- data/app/components/dsfr_component/tag_component.rb +60 -31
- data/app/components/dsfr_component/tile_component.html.erb +19 -0
- data/app/components/dsfr_component/tile_component.rb +38 -0
- data/app/helpers/dsfr_components_helper.rb +17 -19
- data/app/helpers/dsfr_link_helper.rb +41 -90
- data/lib/dsfr/components/version.rb +1 -1
- data/lib/generators/dsfr_component/USAGE +28 -0
- data/lib/generators/dsfr_component/dsfr_component_generator.rb +50 -0
- data/lib/generators/dsfr_component/templates/component.haml.erb +13 -0
- data/lib/generators/dsfr_component/templates/component.rb.erb +32 -0
- data/lib/generators/dsfr_component/templates/component_helper.rb.erb +10 -0
- data/lib/generators/dsfr_component/templates/component_spec.rb.erb +5 -0
- metadata +90 -63
- data/app/components/dsfr_component/back_link_component.rb +0 -24
- data/app/components/dsfr_component/breadcrumbs_component.html.erb +0 -7
- data/app/components/dsfr_component/breadcrumbs_component.rb +0 -51
- data/app/components/dsfr_component/cookie_banner_component/message_component.rb +0 -62
- data/app/components/dsfr_component/cookie_banner_component.rb +0 -35
- data/app/components/dsfr_component/details_component.rb +0 -42
- data/app/components/dsfr_component/footer_component.html.erb +0 -49
- data/app/components/dsfr_component/footer_component.rb +0 -87
- data/app/components/dsfr_component/inset_text_component.rb +0 -28
- data/app/components/dsfr_component/notification_banner_component.html.erb +0 -14
- data/app/components/dsfr_component/notification_banner_component.rb +0 -93
- data/app/components/dsfr_component/pagination_component/adjacent_page.rb +0 -59
- data/app/components/dsfr_component/pagination_component/item.rb +0 -77
- data/app/components/dsfr_component/pagination_component/next_page.rb +0 -27
- data/app/components/dsfr_component/pagination_component/previous_page.rb +0 -21
- data/app/components/dsfr_component/pagination_component.rb +0 -129
- data/app/components/dsfr_component/panel_component.rb +0 -56
- data/app/components/dsfr_component/phase_banner_component.html.erb +0 -6
- data/app/components/dsfr_component/phase_banner_component.rb +0 -25
- data/app/components/dsfr_component/section_break_component.rb +0 -49
- data/app/components/dsfr_component/start_button_component.rb +0 -55
- data/app/components/dsfr_component/summary_list_component/action_component.rb +0 -42
- data/app/components/dsfr_component/summary_list_component/key_component.rb +0 -23
- data/app/components/dsfr_component/summary_list_component/row_component.rb +0 -57
- data/app/components/dsfr_component/summary_list_component/value_component.rb +0 -23
- data/app/components/dsfr_component/summary_list_component.html.erb +0 -5
- data/app/components/dsfr_component/summary_list_component.rb +0 -49
- data/app/components/dsfr_component/tab_component.html.erb +0 -11
- data/app/components/dsfr_component/tab_component.rb +0 -61
- data/app/components/dsfr_component/table_component/body_component.html.erb +0 -5
- data/app/components/dsfr_component/table_component/body_component.rb +0 -21
- data/app/components/dsfr_component/table_component/caption_component.rb +0 -37
- data/app/components/dsfr_component/table_component/cell_component.rb +0 -57
- data/app/components/dsfr_component/table_component/head_component.html.erb +0 -5
- data/app/components/dsfr_component/table_component/head_component.rb +0 -23
- data/app/components/dsfr_component/table_component/row_component.html.erb +0 -5
- data/app/components/dsfr_component/table_component/row_component.rb +0 -30
- data/app/components/dsfr_component/table_component.html.erb +0 -7
- data/app/components/dsfr_component/table_component.rb +0 -35
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26127e695550fca9861568104cb2e15f13f81c77d8ab97788db823215bdcd43e
|
4
|
+
data.tar.gz: 90059e2796a0b0e63f6fed13bb9183866dd01ec796d190e342fd9f458d5a1bdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f14bbd9482cf8dfa9473d024c388a30db71225c31fcee52bf69d2dfed43802892dc3cfb56e21f1273d187378cf0e905e801ed9092958839ed3ec9329fc58ece9
|
7
|
+
data.tar.gz: 30e838fb64e6e0fb1fb11adea4967aaf4cdeed2fc8763d8e46ffe4823f1e3a98c4512e974a001e86fcefe47b113dec303e49e3e7e4517727098edda9439c498f
|
data/README.md
CHANGED
@@ -1,74 +1,73 @@
|
|
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
|
-
|
17
|
+
## Développement en cours ⚠️
|
10
18
|
|
11
|
-
|
12
|
-
|
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
|
-
|
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
|
-
|
25
|
+
```sh
|
26
|
+
bin/rails g dsfr_component FancyButton --params title:String count:Integer
|
27
|
+
```
|
24
28
|
|
25
29
|
## Documentation
|
26
30
|
|
27
|
-
|
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
|
+
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.
|
31
32
|
|
32
|
-
|
33
|
+
## Installation
|
33
34
|
|
34
|
-
|
35
|
+
Pour utiliser cette gem dans votre application Rails, il faut ajouter cette ligne dans `config/application.rb`:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
require "dsfr/components"
|
39
|
+
```
|
35
40
|
|
36
41
|
## Composants disponibles
|
37
42
|
|
38
43
|
Cette gem a pour but de supporter tous les composants proposés par le Design Système de l'État hormis ceux concernant les formulaires. Ceux-ci seront fournis dans une gem indépendante dans le futur.
|
39
44
|
|
40
|
-
|
45
|
+
10/36 composants sont disponibles :
|
41
46
|
|
42
|
-
- [
|
43
|
-
- [
|
44
|
-
- [
|
45
|
-
- [ ] Badge
|
47
|
+
- [x] Accordéon - Accordion
|
48
|
+
- [x] Alertes - Alert
|
49
|
+
- [x] Badge
|
46
50
|
- [ ] Bandeau d'information importante
|
47
51
|
- [ ] Barre de recherche - Search bar
|
48
|
-
- [
|
52
|
+
- [x] Boutons - Buttons
|
49
53
|
- [ ] Groupe de bouton
|
50
54
|
- [ ] Bouton FranceConnect
|
51
|
-
- [ ] Boutons radio
|
52
|
-
- [ ] Boutons radio 'riches'
|
53
|
-
- [ ] Case à cocher - Checkbox
|
54
55
|
- [ ] Cartes - Cards
|
55
|
-
- [ ] Champ de saisie - Input
|
56
56
|
- [ ] Citation - Quote
|
57
57
|
- [ ] Contenu médias - Responsive médias
|
58
|
-
- [
|
58
|
+
- [x] En-tête - Header
|
59
59
|
- [ ] Fil d'Ariane - Breadcrumb
|
60
60
|
- [ ] Gestionnaire de consentement - Consent banner
|
61
61
|
- [ ] Icônes de favoris - Favicons
|
62
|
-
- [
|
62
|
+
- [x] Indicateur d'étape - Stepper
|
63
63
|
- [ ] Interrupteur - Toggle switch
|
64
64
|
- [ ] Lettre d'information et réseaux sociaux - Newsletter & Follow us
|
65
|
-
- [
|
65
|
+
- [x] Liens - Links
|
66
66
|
- [ ] Liens d'évitement - Skiplinks
|
67
|
-
- [ ] Liste déroulante - Select
|
68
67
|
- [ ] Menu latéral - Side menu
|
69
68
|
- [ ] Mise en avant - Call out
|
70
69
|
- [ ] Mise en exergue - Highlight
|
71
|
-
- [
|
70
|
+
- [x] Modale - Modal
|
72
71
|
- [ ] Navigation principale - Main navigation
|
73
72
|
- [ ] Onglets - Tabs
|
74
73
|
- [ ] Pagination
|
@@ -78,9 +77,9 @@ Les composants disponibles sont :
|
|
78
77
|
- [ ] Sélecteur de langue
|
79
78
|
- [ ] Sommaire - Summary
|
80
79
|
- [ ] Tableau - Table
|
81
|
-
- [
|
80
|
+
- [x] Tag
|
82
81
|
- [ ] Téléchargement de fichier
|
83
|
-
- [
|
82
|
+
- [x] Tuile - Tile
|
84
83
|
|
85
84
|
<!--
|
86
85
|
This library also provides helpers for creating [links](https://govuk-components.netlify.app/helpers/link),
|
@@ -88,92 +87,9 @@ This library also provides helpers for creating [links](https://govuk-components
|
|
88
87
|
and [back to top links](https://govuk-components.netlify.app/helpers/back-to-top-link).
|
89
88
|
-->
|
90
89
|
|
91
|
-
|
92
|
-
## Alternative syntax
|
93
|
-
|
94
|
-
All of the components can be rendered in two ways:
|
95
|
-
|
96
|
-
* directly using Rails’ `#render` method:
|
97
|
-
|
98
|
-
```erb
|
99
|
-
<%= render DsfrComponent::WarningTextComponent.new do %>
|
100
|
-
A serious warning
|
101
|
-
<% end %>
|
102
|
-
```
|
103
|
-
|
104
|
-
* via the helper wrapper:
|
105
|
-
|
106
|
-
```erb
|
107
|
-
<%= dsfr_warning_text do %>
|
108
|
-
A serious warning
|
109
|
-
<% end %>
|
110
|
-
```
|
111
|
-
|
112
|
-
The naming convention for helpers is `dsfr_` followed by the component’s name in snake case. You can see the full list in [DsfrComponentsHelper](app/helpers/dsfr_components_helper.rb).
|
113
|
-
|
114
|
-
## Example use
|
115
|
-
|
116
|
-
This library allows components to be rendered with Rails’ `render` method or via the provided helpers. Here we’ll use the `dsfr_tabs` to render three tabbed sections:
|
117
|
-
|
118
|
-
```erb
|
119
|
-
<%= dsfr_tabs(title: 'Days of the week') do |component| %>
|
120
|
-
<% component.tab(label: 'Monday') do %>
|
121
|
-
<p>Monday’s child is fair of face</p>
|
122
|
-
<% end %>
|
123
|
-
|
124
|
-
<% component.tab(label: 'Tuesday') do %>
|
125
|
-
<p>Tuesday’s child is full of grace</p>
|
126
|
-
<% end %>
|
127
|
-
|
128
|
-
<% component.tab(label: 'Wednesday') do %>
|
129
|
-
<p>Wednesday’s child is full of woe</p>
|
130
|
-
<% end %>
|
131
|
-
<% end %>
|
132
|
-
```
|
133
|
-
|
134
|
-
Here are the rendered tabs:
|
90
|
+
## Services utilisant cette gem
|
135
91
|
|
136
|
-
|
137
|
-
|
138
|
-
For examples on usage see the [guide page](https://govuk-components.netlify.app/).
|
139
|
-
|
140
|
-
## Setup
|
141
|
-
|
142
|
-
Add this line to your `config/application.rb`:
|
143
|
-
|
144
|
-
```ruby
|
145
|
-
require "govuk/components"
|
146
|
-
```
|
147
|
-
|
148
|
-
## Services using this library
|
149
|
-
|
150
|
-
* [Apply for teacher training](https://github.com/DFE-Digital/apply-for-teacher-training)
|
151
|
-
* [Find postgraduate teacher training](https://github.com/DFE-Digital/find-teacher-training)
|
152
|
-
* [Get help with technology](https://github.com/DFE-Digital/get-help-with-tech)
|
153
|
-
* [Publish teacher training courses](https://github.com/DFE-Digital/publish-teacher-training)
|
154
|
-
* [Register trainee teachers](https://github.com/DFE-Digital/register-trainee-teachers)
|
155
|
-
* [Teaching Vacancies](https://github.com/DFE-Digital/teaching-vacancies)
|
156
|
-
|
157
|
-
## Installation
|
158
|
-
|
159
|
-
Ajouter cette ligne à votre Gemfile:
|
160
|
-
|
161
|
-
```ruby
|
162
|
-
gem 'dsfr-components'
|
163
|
-
```
|
164
|
-
|
165
|
-
And then execute:
|
166
|
-
|
167
|
-
```sh
|
168
|
-
bundle
|
169
|
-
```
|
170
|
-
|
171
|
-
Or install it yourself as:
|
172
|
-
|
173
|
-
```sh
|
174
|
-
gem install govuk-components
|
175
|
-
```
|
176
|
-
-->
|
92
|
+
- [Collectif Objets](https://collectif-objets.beta.gouv.fr/) - [code source](https://github.com/betagouv/collectif-objets)
|
177
93
|
|
178
94
|
## Contribuer
|
179
95
|
|
@@ -191,7 +107,12 @@ bundle install
|
|
191
107
|
bundle exec rspec spec
|
192
108
|
```
|
193
109
|
|
194
|
-
|
110
|
+
Pour développer avec les tests en continu :
|
111
|
+
```sh
|
112
|
+
bundle exec guard
|
113
|
+
```
|
114
|
+
|
115
|
+
Lancer le guide de documentation :
|
195
116
|
|
196
117
|
```sh
|
197
118
|
make watch-guide
|
@@ -207,7 +128,10 @@ bundle exec rails server
|
|
207
128
|
|
208
129
|
Déployer une nouvelle version de la gem :
|
209
130
|
|
210
|
-
|
131
|
+
```sh
|
132
|
+
VERSION=1.3.2 make deploy_gem
|
133
|
+
```
|
134
|
+
|
211
135
|
|
212
136
|
## Licence
|
213
137
|
|
@@ -1,11 +1,17 @@
|
|
1
|
-
<%= tag.
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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 :
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@
|
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
|
19
|
-
|
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("
|
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, ->(
|
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
|
-
|
9
|
-
|
7
|
+
title: title,
|
8
|
+
id: id,
|
10
9
|
&block
|
11
10
|
)
|
12
11
|
end
|
13
12
|
|
14
|
-
|
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(
|
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
|
-
|
2
|
+
TYPES = %i[error success info warning].freeze
|
3
|
+
SIZES = %i[sm md].freeze
|
3
4
|
|
4
|
-
|
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
|
-
|
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
|
@@ -5,6 +5,8 @@ class DsfrComponent::Base < ViewComponent::Base
|
|
5
5
|
|
6
6
|
delegate :config, to: Dsfr::Components
|
7
7
|
|
8
|
+
HEADING_LEVELS = [1, 2, 3, 4, 5, 6].freeze
|
9
|
+
|
8
10
|
def initialize(classes:, html_attributes:)
|
9
11
|
if classes.nil?
|
10
12
|
Rails.logger.warn("classes is nil, if no custom classes are needed omit the param")
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module DsfrComponent
|
2
|
+
class ButtonComponent < DsfrComponent::Base
|
3
|
+
SIZES = %i[sm md lg].freeze
|
4
|
+
ICON_POSITIONS = %i[left right].freeze
|
5
|
+
ICON_LEVELS = %i[primary secondary tertiary].freeze
|
6
|
+
|
7
|
+
# @param label [String] Le label du bouton (optionnel si un icône présent)
|
8
|
+
# @param icon [String] Le nom de l’icône à afficher (exemple `arrow-right-line`) (optionnel)
|
9
|
+
# @param icon_position [String] Position de l’icône : :left (défaut) ou :right (optionnel)
|
10
|
+
# @param title [String] Le titre du bouton permettant d’afficher une infobulle (optionnel)
|
11
|
+
# @param level [String] Le niveau du bouton : :primary (défaut), :secondary ou :tertiary (optionnel)
|
12
|
+
# @param size [String] La taille du bouton : :sm, :md (défaut), :lg (optionnel)
|
13
|
+
def initialize(label: nil, title: nil, icon: nil, icon_position: :left, level: nil, size: nil, classes: [], html_attributes: {})
|
14
|
+
@label = label
|
15
|
+
@title = title
|
16
|
+
@icon = icon
|
17
|
+
@icon_position = icon_position
|
18
|
+
@level = level
|
19
|
+
@outline = outline
|
20
|
+
@size = size
|
21
|
+
|
22
|
+
validate_size
|
23
|
+
validate_icon_position
|
24
|
+
validate_level
|
25
|
+
validate_label
|
26
|
+
|
27
|
+
super(classes: classes, html_attributes: html_attributes)
|
28
|
+
end
|
29
|
+
|
30
|
+
def call
|
31
|
+
tag.button(**html_attributes) { label }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :label, :icon, :icon_position, :level, :outline, :size
|
37
|
+
|
38
|
+
def default_attributes
|
39
|
+
classes = ["fr-btn"]
|
40
|
+
classes << "fr-btn--#{level}" if level.present?
|
41
|
+
classes << "fr-btn--#{size}" if size.present?
|
42
|
+
classes << "fr-icon-#{icon}" if icon.present?
|
43
|
+
classes << "fr-btn--icon-#{icon_position}" if icon.present? && label.present?
|
44
|
+
{ class: classes }
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_size
|
48
|
+
raise(ArgumentError, "`size` should be one of #{SIZES}") if size.present? && SIZES.exclude?(size)
|
49
|
+
end
|
50
|
+
|
51
|
+
def validate_icon_position
|
52
|
+
raise(ArgumentError, "`icon_position` should be one of #{ICON_POSITIONS}") if icon_position.present? && ICON_POSITIONS.exclude?(icon_position)
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_level
|
56
|
+
raise(ArgumentError, "`level` should be one of #{ICON_LEVELS}") if level.present? && ICON_LEVELS.exclude?(level)
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate_label
|
60
|
+
raise(ArgumentError, "`label` is required unless an icon is specified") if label.blank? && icon.blank?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class DsfrComponent::HeaderComponent::DirectLinkComponent < DsfrComponent::Base
|
2
|
+
def initialize(title:, path:, active: false, classes: [], html_attributes: {})
|
3
|
+
@title = title
|
4
|
+
@path = path
|
5
|
+
@active = active
|
6
|
+
|
7
|
+
super(classes: classes, html_attributes: html_attributes)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
tag.a(title, **html_attributes)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :title, :path, :active
|
17
|
+
|
18
|
+
def default_attributes
|
19
|
+
{ href: path, class: 'fr-nav__link', target: "_self" } \
|
20
|
+
.merge(active ? { "aria-current": 'page' } : {})
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class DsfrComponent::HeaderComponent::DirectLinkDropdownComponent < DsfrComponent::Base
|
2
|
+
renders_many :links, DsfrComponent::HeaderComponent::DirectLinkComponent
|
3
|
+
|
4
|
+
def initialize(title:, active: false, classes: [], html_attributes: {})
|
5
|
+
@title = title
|
6
|
+
@active = active
|
7
|
+
|
8
|
+
super(classes: classes, html_attributes: html_attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
tag.button(title, **html_attributes) +
|
13
|
+
tag.div(class: 'fr-collapse fr-menu', id: menu_id) do
|
14
|
+
tag.ul(class: 'fr-menu__list') do
|
15
|
+
links.map do |link|
|
16
|
+
tag.li link.call
|
17
|
+
end.join.html_safe
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :title, :active
|
25
|
+
|
26
|
+
def default_attributes
|
27
|
+
{ class: 'fr-nav__btn', "aria-expanded": "false", "aria-controls": menu_id } \
|
28
|
+
.merge(active ? { "aria-current": 'true' } : {})
|
29
|
+
end
|
30
|
+
|
31
|
+
def menu_id
|
32
|
+
@menu_id ||= "menu-#{title.parameterize}"
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class DsfrComponent::HeaderComponent::ToolLinkComponent < DsfrComponent::Base
|
2
|
+
def initialize(title:, path:, classes: [], html_attributes: {})
|
3
|
+
@title = title
|
4
|
+
@path = path
|
5
|
+
|
6
|
+
super(classes: classes, html_attributes: html_attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
tag.a title, href: path, **html_attributes
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
attr_reader :title, :path
|
16
|
+
|
17
|
+
def default_attributes
|
18
|
+
{ class: 'fr-btn' }
|
19
|
+
end
|
20
|
+
end
|