dsfr-view-components 0.0.1
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.
- checksums.yaml +7 -0
- data/README.md +214 -0
- data/Rakefile +22 -0
- data/app/components/dsfr_component/accordion_component/section_component.html.erb +11 -0
- data/app/components/dsfr_component/accordion_component/section_component.rb +39 -0
- data/app/components/dsfr_component/accordion_component.html.erb +5 -0
- data/app/components/dsfr_component/accordion_component.rb +33 -0
- data/app/components/dsfr_component/alert_component.rb +22 -0
- data/app/components/dsfr_component/back_link_component.rb +24 -0
- data/app/components/dsfr_component/base.rb +28 -0
- data/app/components/dsfr_component/breadcrumbs_component.html.erb +7 -0
- data/app/components/dsfr_component/breadcrumbs_component.rb +51 -0
- data/app/components/dsfr_component/cookie_banner_component/message_component.rb +62 -0
- data/app/components/dsfr_component/cookie_banner_component.rb +35 -0
- data/app/components/dsfr_component/details_component.rb +42 -0
- data/app/components/dsfr_component/footer_component.html.erb +49 -0
- data/app/components/dsfr_component/footer_component.rb +87 -0
- data/app/components/dsfr_component/header_component.html.erb +51 -0
- data/app/components/dsfr_component/header_component.rb +145 -0
- data/app/components/dsfr_component/inset_text_component.rb +28 -0
- data/app/components/dsfr_component/notification_banner_component.html.erb +14 -0
- data/app/components/dsfr_component/notification_banner_component.rb +93 -0
- data/app/components/dsfr_component/pagination_component/adjacent_page.rb +59 -0
- data/app/components/dsfr_component/pagination_component/item.rb +77 -0
- data/app/components/dsfr_component/pagination_component/next_page.rb +27 -0
- data/app/components/dsfr_component/pagination_component/previous_page.rb +21 -0
- data/app/components/dsfr_component/pagination_component.rb +129 -0
- data/app/components/dsfr_component/panel_component.rb +56 -0
- data/app/components/dsfr_component/phase_banner_component.html.erb +6 -0
- data/app/components/dsfr_component/phase_banner_component.rb +25 -0
- data/app/components/dsfr_component/section_break_component.rb +49 -0
- data/app/components/dsfr_component/start_button_component.rb +55 -0
- data/app/components/dsfr_component/summary_list_component/action_component.rb +42 -0
- data/app/components/dsfr_component/summary_list_component/key_component.rb +23 -0
- data/app/components/dsfr_component/summary_list_component/row_component.rb +57 -0
- data/app/components/dsfr_component/summary_list_component/value_component.rb +23 -0
- data/app/components/dsfr_component/summary_list_component.html.erb +5 -0
- data/app/components/dsfr_component/summary_list_component.rb +49 -0
- data/app/components/dsfr_component/tab_component.html.erb +11 -0
- data/app/components/dsfr_component/tab_component.rb +61 -0
- data/app/components/dsfr_component/table_component/body_component.html.erb +5 -0
- data/app/components/dsfr_component/table_component/body_component.rb +21 -0
- data/app/components/dsfr_component/table_component/caption_component.rb +37 -0
- data/app/components/dsfr_component/table_component/cell_component.rb +57 -0
- data/app/components/dsfr_component/table_component/head_component.html.erb +5 -0
- data/app/components/dsfr_component/table_component/head_component.rb +23 -0
- data/app/components/dsfr_component/table_component/row_component.html.erb +5 -0
- data/app/components/dsfr_component/table_component/row_component.rb +30 -0
- data/app/components/dsfr_component/table_component.html.erb +7 -0
- data/app/components/dsfr_component/table_component.rb +35 -0
- data/app/components/dsfr_component/tag_component.rb +44 -0
- data/app/components/dsfr_component/traits/custom_html_attributes.rb +7 -0
- data/app/components/dsfr_component/traits.rb +1 -0
- data/app/components/dsfr_component/warning_text_component.rb +37 -0
- data/app/components/dsfr_component.rb +1 -0
- data/app/helpers/dsfr_back_to_top_link_helper.rb +14 -0
- data/app/helpers/dsfr_components_helper.rb +33 -0
- data/app/helpers/dsfr_link_helper.rb +123 -0
- data/app/helpers/dsfr_skip_link_helper.rb +13 -0
- data/config/routes.rb +2 -0
- data/lib/dsfr/components/engine.rb +110 -0
- data/lib/dsfr/components/helpers/css_utilities.rb +22 -0
- data/lib/dsfr/components/version.rb +5 -0
- data/lib/dsfr/components.rb +6 -0
- data/lib/tasks/dsfr/components_tasks.rake +4 -0
- metadata +482 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13a375b911fee2a88bc620482b766be2d3348d0138d56f9f2cb2641f649e8d50
|
4
|
+
data.tar.gz: 85f677a71346315a8c128f156b32c74b6436528bfa5ed98fcaf490d352fdeb71
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6b10dd868701e33699626fa4753fd7a017128f87b91394c72100d24b014c16206e5285ca81778d045c025241c56a6a97805859b6af75d1c946ba917677818dc7
|
7
|
+
data.tar.gz: e81ae1788e01bc3e24ec2cc07a4ccfd2cf8fef13fd6d6a5a865423cdf584d65a5303c0965681ff2a922e2cb50bc61bbffb3eca87f20c7cf4224bbd51a355ee06
|
data/README.md
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
# Composants du DSFR
|
2
|
+
|
3
|
+
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
|
+
|
5
|
+
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
|
+
|
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
|
+
|
9
|
+
[](https://github.com/betagouv/dsfr-view-components/actions?query=workflow%3ATests)
|
10
|
+
|
11
|
+
<!--
|
12
|
+
[](https://codeclimate.com/github/DFE-Digital/govuk-components/maintainability)
|
13
|
+
[](https://badge.fury.io/rb/govuk-components)
|
14
|
+
[](https://rubygems.org/gems/govuk-components)
|
15
|
+
[](https://codeclimate.com/github/DFE-Digital/govuk-components/test_coverage)
|
16
|
+
[](https://github.com/DFE-Digital/govuk-components/blob/main/LICENSE)
|
17
|
+
[](https://design-system.service.gov.uk)
|
18
|
+
[](https://weblog.rubyonrails.org/releases/)
|
19
|
+
[](https://www.ruby-lang.org/en/downloads/)
|
20
|
+
|
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
|
+
|
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.
|
24
|
+
|
25
|
+
## Documentation
|
26
|
+
|
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
|
+
[](https://app.netlify.com/sites/govuk-components/deploys)
|
33
|
+
|
34
|
+
-->
|
35
|
+
|
36
|
+
## Composants disponibles
|
37
|
+
|
38
|
+
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
|
+
|
40
|
+
Les composants disponibles sont :
|
41
|
+
|
42
|
+
- [ ] Accordéon - Accordion
|
43
|
+
- [ ] Ajout de fichier - File upload
|
44
|
+
- [ ] Alertes - Alert
|
45
|
+
- [ ] Badge
|
46
|
+
- [ ] Bandeau d'information importante
|
47
|
+
- [ ] Barre de recherche - Search bar
|
48
|
+
- [ ] Boutons - Buttons
|
49
|
+
- [ ] Groupe de bouton
|
50
|
+
- [ ] Bouton FranceConnect
|
51
|
+
- [ ] Boutons radio
|
52
|
+
- [ ] Boutons radio 'riches'
|
53
|
+
- [ ] Case à cocher - Checkbox
|
54
|
+
- [ ] Cartes - Cards
|
55
|
+
- [ ] Champ de saisie - Input
|
56
|
+
- [ ] Citation - Quote
|
57
|
+
- [ ] Contenu médias - Responsive médias
|
58
|
+
- [ ] En-tête - Header
|
59
|
+
- [ ] Fil d'Ariane - Breadcrumb
|
60
|
+
- [ ] Gestionnaire de consentement - Consent banner
|
61
|
+
- [ ] Icônes de favoris - Favicons
|
62
|
+
- [ ] Indicateur d'étape
|
63
|
+
- [ ] Interrupteur - Toggle switch
|
64
|
+
- [ ] Lettre d'information et réseaux sociaux - Newsletter & Follow us
|
65
|
+
- [ ] Liens - Links
|
66
|
+
- [ ] Liens d'évitement - Skiplinks
|
67
|
+
- [ ] Liste déroulante - Select
|
68
|
+
- [ ] Menu latéral - Side menu
|
69
|
+
- [ ] Mise en avant - Call out
|
70
|
+
- [ ] Mise en exergue - Highlight
|
71
|
+
- [ ] Modale - Modal
|
72
|
+
- [ ] Navigation principale - Main navigation
|
73
|
+
- [ ] Onglets - Tabs
|
74
|
+
- [ ] Pagination
|
75
|
+
- [ ] Paramètres d'affichage - Display
|
76
|
+
- [ ] Partage - Share
|
77
|
+
- [ ] Pied de page - Footer
|
78
|
+
- [ ] Sélecteur de langue
|
79
|
+
- [ ] Sommaire - Summary
|
80
|
+
- [ ] Tableau - Table
|
81
|
+
- [ ] Tag
|
82
|
+
- [ ] Téléchargement de fichier
|
83
|
+
- [ ] Tuile - Tile
|
84
|
+
|
85
|
+
<!--
|
86
|
+
This library also provides helpers for creating [links](https://govuk-components.netlify.app/helpers/link),
|
87
|
+
[buttons](https://govuk-components.netlify.app/helpers/button), [skip links](https://govuk-components.netlify.app/helpers/skip-link)
|
88
|
+
and [back to top links](https://govuk-components.netlify.app/helpers/back-to-top-link).
|
89
|
+
-->
|
90
|
+
|
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:
|
135
|
+
|
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
|
+
-->
|
177
|
+
|
178
|
+
## Contribuer
|
179
|
+
|
180
|
+
Nous conseillons d'utiliser [rbenv](https://github.com/rbenv/rbenv) pour gérer vos versions de ruby :
|
181
|
+
|
182
|
+
```sh
|
183
|
+
rbenv local 3.1.2
|
184
|
+
rbenv install
|
185
|
+
```
|
186
|
+
|
187
|
+
Lancer les tests :
|
188
|
+
|
189
|
+
```sh
|
190
|
+
bundle install
|
191
|
+
bundle exec rspec spec
|
192
|
+
```
|
193
|
+
|
194
|
+
Lancer le guide de documentation :
|
195
|
+
|
196
|
+
```sh
|
197
|
+
make watch-guide
|
198
|
+
```
|
199
|
+
|
200
|
+
Lancer la dummy app pour itérer sur les composants :
|
201
|
+
|
202
|
+
```sh
|
203
|
+
cd spec/dummy
|
204
|
+
bundle install && npm install
|
205
|
+
bundle exec rails server
|
206
|
+
```
|
207
|
+
|
208
|
+
Déployer une nouvelle version de la gem :
|
209
|
+
|
210
|
+
TODO
|
211
|
+
|
212
|
+
## Licence
|
213
|
+
|
214
|
+
Le code source et la gem sont ouverts sous la licence [MIT](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Dsfr::Components'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,11 @@
|
|
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 %>
|
9
|
+
</div>
|
10
|
+
<%= tag.div(content, id: id(suffix: 'content'), class: %w(govuk-accordion__section-content), aria: { labelledby: id }) %>
|
11
|
+
<% end %>
|
@@ -0,0 +1,39 @@
|
|
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
|
6
|
+
|
7
|
+
alias_method :expanded?, :expanded
|
8
|
+
|
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
|
14
|
+
|
15
|
+
super(classes: classes, html_attributes: html_attributes)
|
16
|
+
end
|
17
|
+
|
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
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def default_attributes
|
37
|
+
{ class: class_names("govuk-accordion__section", "govuk-accordion__section--expanded" => expanded?).split }
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class DsfrComponent::AccordionComponent < DsfrComponent::Base
|
2
|
+
renders_many :sections, ->(heading_text: nil, summary_text: nil, expanded: false, classes: [], html_attributes: {}, &block) do
|
3
|
+
DsfrComponent::AccordionComponent::SectionComponent.new(
|
4
|
+
classes: classes,
|
5
|
+
expanded: expanded,
|
6
|
+
heading_level: heading_level, # set once at parent level, passed to all children
|
7
|
+
html_attributes: html_attributes,
|
8
|
+
summary_text: summary_text,
|
9
|
+
heading_text: heading_text,
|
10
|
+
&block
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :id, :heading_level
|
15
|
+
|
16
|
+
def initialize(heading_level: 2, classes: [], html_attributes: {})
|
17
|
+
@heading_level = heading_tag(heading_level)
|
18
|
+
|
19
|
+
super(classes: classes, html_attributes: html_attributes)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
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})
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class DsfrComponent::AlertComponent < DsfrComponent::Base
|
2
|
+
attr_reader :title
|
3
|
+
|
4
|
+
def initialize(title:, classes: [], html_attributes: {})
|
5
|
+
@title = title
|
6
|
+
|
7
|
+
super(classes: classes, html_attributes: html_attributes)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
tag.div(**html_attributes) do
|
12
|
+
tag.h3(class: "fr-alert__title") { title }
|
13
|
+
tag.p { content }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def default_attributes
|
20
|
+
{ class: %w(fr-alert) }
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class DsfrComponent::BackLinkComponent < DsfrComponent::Base
|
2
|
+
attr_reader :text, :href
|
3
|
+
|
4
|
+
def initialize(href:, text: config.default_back_link_text, classes: [], html_attributes: {})
|
5
|
+
@text = text
|
6
|
+
@href = href
|
7
|
+
|
8
|
+
super(classes: classes, html_attributes: html_attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
link_to(link_content, href, **html_attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def link_content
|
18
|
+
content || text || fail(ArgumentError, "no text or content")
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_attributes
|
22
|
+
{ class: %w(govuk-back-link) }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class DsfrComponent::Base < ViewComponent::Base
|
2
|
+
using HTMLAttributesUtils
|
3
|
+
|
4
|
+
attr_reader :html_attributes
|
5
|
+
|
6
|
+
delegate :config, to: Dsfr::Components
|
7
|
+
|
8
|
+
def initialize(classes:, html_attributes:)
|
9
|
+
if classes.nil?
|
10
|
+
Rails.logger.warn("classes is nil, if no custom classes are needed omit the param")
|
11
|
+
|
12
|
+
classes = []
|
13
|
+
end
|
14
|
+
# FIXME: remove first merge when we deprecate classes
|
15
|
+
#
|
16
|
+
# This step only needs to be here while we still accept classes:, now
|
17
|
+
# we're using html_attributes_utils we can start to move towards
|
18
|
+
# supporting html_attributes: { class: 'xyz' } over taking them
|
19
|
+
# separately
|
20
|
+
|
21
|
+
@html_attributes = default_attributes
|
22
|
+
.deep_merge_html_attributes({ class: classes })
|
23
|
+
.deep_merge_html_attributes(html_attributes)
|
24
|
+
.deep_tidy_html_attributes
|
25
|
+
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class DsfrComponent::BreadcrumbsComponent < DsfrComponent::Base
|
2
|
+
attr_reader :breadcrumbs, :hide_in_print, :collapse_on_mobile
|
3
|
+
|
4
|
+
def initialize(breadcrumbs:,
|
5
|
+
hide_in_print: config.default_breadcrumbs_hide_in_print,
|
6
|
+
collapse_on_mobile: config.default_breadcrumbs_collapse_on_mobile,
|
7
|
+
classes: [],
|
8
|
+
html_attributes: {})
|
9
|
+
|
10
|
+
@breadcrumbs = build_list(breadcrumbs)
|
11
|
+
@hide_in_print = hide_in_print
|
12
|
+
@collapse_on_mobile = collapse_on_mobile
|
13
|
+
|
14
|
+
super(classes: classes, html_attributes: html_attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def default_attributes
|
20
|
+
{
|
21
|
+
class: class_names(
|
22
|
+
"govuk-breadcrumbs",
|
23
|
+
"govuk-!-display-none-print" => hide_in_print,
|
24
|
+
"govuk-breadcrumbs--collapse-on-mobile" => collapse_on_mobile
|
25
|
+
).split
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_list(breadcrumbs)
|
30
|
+
case breadcrumbs
|
31
|
+
when Array
|
32
|
+
breadcrumbs.map { |item| build_list_item(item) }
|
33
|
+
when Hash
|
34
|
+
breadcrumbs.map { |text, link| build_list_item(text, link) }
|
35
|
+
else
|
36
|
+
fail(ArgumentError, "breadcrumbs must be an array or hash")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_list_item(text, link = nil)
|
41
|
+
if link.present?
|
42
|
+
list_item { link_to(text, link, class: "govuk-breadcrumbs__link") }
|
43
|
+
else
|
44
|
+
list_item(aria: { current: "page" }) { text.to_s }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def list_item(html_attributes = {}, &block)
|
49
|
+
tag.li(class: "govuk-breadcrumbs__list-item", **html_attributes, &block)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class DsfrComponent::CookieBannerComponent::MessageComponent < DsfrComponent::Base
|
2
|
+
attr_reader :heading_text, :text, :hidden, :role
|
3
|
+
|
4
|
+
renders_many :actions
|
5
|
+
renders_one :heading_html
|
6
|
+
|
7
|
+
def initialize(heading_text: nil, text: nil, hidden: false, role: nil, classes: [], html_attributes: {})
|
8
|
+
@heading_text = heading_text
|
9
|
+
@text = text
|
10
|
+
@hidden = hidden
|
11
|
+
@role = role
|
12
|
+
|
13
|
+
super(classes: classes, html_attributes: html_attributes)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
tag.div(role: role, hidden: hidden, **html_attributes) do
|
18
|
+
safe_join([
|
19
|
+
tag.div(class: "govuk-grid-row") do
|
20
|
+
tag.div(class: "govuk-grid-column-two-thirds") { safe_join([heading_element, message_element]) }
|
21
|
+
end,
|
22
|
+
actions_element
|
23
|
+
])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def default_attributes
|
30
|
+
{ class: %w(govuk-cookie-banner__message govuk-width-container) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def heading_element
|
34
|
+
return if heading_content.blank?
|
35
|
+
|
36
|
+
tag.h2(heading_content, class: %w(govuk-cookie-banner__heading govuk-heading-m))
|
37
|
+
end
|
38
|
+
|
39
|
+
def heading_content
|
40
|
+
heading_html || heading_text
|
41
|
+
end
|
42
|
+
|
43
|
+
def message_element
|
44
|
+
tag.div(message_content, class: "govuk-cookie-banner__content")
|
45
|
+
end
|
46
|
+
|
47
|
+
def message_content
|
48
|
+
content || wrap_in_p(text) || fail(ArgumentError, "no text or content")
|
49
|
+
end
|
50
|
+
|
51
|
+
def wrap_in_p(message_text)
|
52
|
+
return if message_text.blank?
|
53
|
+
|
54
|
+
tag.p(message_text, class: "govuk-body")
|
55
|
+
end
|
56
|
+
|
57
|
+
def actions_element
|
58
|
+
return if actions.none?
|
59
|
+
|
60
|
+
tag.div(class: "fr-btn-group") { safe_join(actions) }
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module DsfrComponent
|
2
|
+
class CookieBannerComponent < DsfrComponent::Base
|
3
|
+
renders_many :messages, "DsfrComponent::CookieBannerComponent::MessageComponent"
|
4
|
+
|
5
|
+
attr_accessor :aria_label, :hidden, :hide_in_print
|
6
|
+
|
7
|
+
def initialize(
|
8
|
+
aria_label: config.default_cookie_banner_aria_label,
|
9
|
+
hidden: false,
|
10
|
+
hide_in_print: config.default_cookie_banner_hide_in_print,
|
11
|
+
classes: [],
|
12
|
+
html_attributes: {}
|
13
|
+
)
|
14
|
+
@aria_label = aria_label
|
15
|
+
@hidden = hidden
|
16
|
+
@hide_in_print = hide_in_print
|
17
|
+
|
18
|
+
super(classes: classes, html_attributes: html_attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
tag.div(role: "region", aria: { label: aria_label }, data: { nosnippet: true }, hidden: hidden, **html_attributes) do
|
23
|
+
safe_join(messages)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def default_attributes
|
30
|
+
{
|
31
|
+
class: class_names("govuk-cookie-banner", "govuk-!-display-none-print" => hide_in_print).split
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class DsfrComponent::DetailsComponent < DsfrComponent::Base
|
2
|
+
attr_reader :summary_text, :text, :id, :open
|
3
|
+
|
4
|
+
renders_one :summary_html
|
5
|
+
|
6
|
+
def initialize(summary_text: nil, text: nil, classes: [], id: nil, open: nil, html_attributes: {})
|
7
|
+
@summary_text = summary_text
|
8
|
+
@text = text
|
9
|
+
@id = id
|
10
|
+
@open = open
|
11
|
+
|
12
|
+
super(classes: classes, html_attributes: html_attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
tag.details(data: { module: "govuk-details" }, id: id, open: open, **html_attributes) do
|
17
|
+
safe_join([summary, description])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def summary
|
24
|
+
tag.summary(class: "govuk-details__summary") do
|
25
|
+
tag.span(summary_content, class: "govuk-details__summary-text")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def summary_content
|
30
|
+
summary_html || summary_text
|
31
|
+
end
|
32
|
+
|
33
|
+
def description
|
34
|
+
tag.div(class: "govuk-details__text") do
|
35
|
+
content.presence || text
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_attributes
|
40
|
+
{ class: %w(govuk-details) }
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<%= tag.footer(role: 'contentinfo', **html_attributes) do %>
|
2
|
+
<%= tag.div(**container_html_attributes) do %>
|
3
|
+
<% if navigation.present? %>
|
4
|
+
<div class="govuk-footer__navigation">
|
5
|
+
<%= navigation %>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<hr class="govuk-footer__section-break">
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= tag.div(class: meta_classes, **meta_html_attributes) do %>
|
12
|
+
<% if meta.present? %>
|
13
|
+
<%= meta %>
|
14
|
+
<% else %>
|
15
|
+
<div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
|
16
|
+
<% if meta_items.any? %>
|
17
|
+
<h2 class="govuk-visually-hidden"><%= meta_items_title %></h2>
|
18
|
+
|
19
|
+
<ul class="govuk-footer__inline-list">
|
20
|
+
<% @meta_items.each do |hyperlink| %>
|
21
|
+
<li class="govuk-footer__inline-list-item">
|
22
|
+
<%= hyperlink %>
|
23
|
+
</li>
|
24
|
+
<% end %>
|
25
|
+
</ul>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<% if meta_licence.nil? %>
|
29
|
+
<svg aria-hidden="true" focusable="false" class="govuk-footer__licence-logo" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 483.2 195.7" height="17" width="41">
|
30
|
+
<path fill="currentColor" d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145" />
|
31
|
+
</svg>
|
32
|
+
|
33
|
+
<%= tag.span(default_licence, class: "govuk-footer__licence-description") %>
|
34
|
+
<% elsif meta_licence.present? %>
|
35
|
+
<%= tag.span(meta_licence, class: "govuk-footer__licence-description") %>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<% if meta_content.present? %>
|
39
|
+
<div class="govuk-footer__meta-custom">
|
40
|
+
<%= meta_content %>
|
41
|
+
</div>
|
42
|
+
<% end %>
|
43
|
+
</div>
|
44
|
+
|
45
|
+
<%= tag.div(copyright, class: "govuk-footer__meta-item") %>
|
46
|
+
<% end %>
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
<% end %>
|