dsfr-view-components 2.1.1 → 2.2.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.
- checksums.yaml +4 -4
- data/app/components/dsfr_component/accordion_component/section_component.html.erb +1 -1
- data/app/components/dsfr_component/accordion_component/section_component.rb +3 -2
- data/app/components/dsfr_component/accordion_component.rb +4 -7
- data/app/components/dsfr_component/alert_component.rb +44 -19
- data/app/components/dsfr_component/badge_component.rb +3 -5
- data/app/components/dsfr_component/base.rb +1 -14
- data/app/components/dsfr_component/breadcrumbs_component.rb +0 -4
- data/app/components/dsfr_component/button_component.rb +2 -2
- data/app/components/dsfr_component/callout_component.rb +41 -0
- data/app/components/dsfr_component/header_component/direct_link_component.rb +2 -2
- data/app/components/dsfr_component/header_component/direct_link_dropdown_component.rb +2 -2
- data/app/components/dsfr_component/header_component/operator_image_component.rb +2 -2
- data/app/components/dsfr_component/header_component/tool_link_component.rb +2 -2
- data/app/components/dsfr_component/header_component.rb +2 -2
- data/app/components/dsfr_component/highlight_component.rb +2 -2
- data/app/components/dsfr_component/modal_component.rb +2 -2
- data/app/components/dsfr_component/notice_component.html.erb +14 -0
- data/app/components/dsfr_component/notice_component.rb +99 -0
- data/app/components/dsfr_component/search_component.html.erb +8 -0
- data/app/components/dsfr_component/search_component.rb +50 -0
- data/app/components/dsfr_component/skiplink_component.rb +2 -2
- data/app/components/dsfr_component/stepper_component.html.erb +1 -1
- data/app/components/dsfr_component/stepper_component.rb +2 -2
- data/app/components/dsfr_component/tabs_component/tab_component.rb +2 -2
- data/app/components/dsfr_component/tabs_component.rb +2 -2
- data/app/components/dsfr_component/tag_component.rb +2 -2
- data/app/components/dsfr_component/tile_component.rb +2 -2
- data/app/components/dsfr_component/traits/header_sizeable.rb +25 -0
- data/app/helpers/dsfr_components_helper.rb +3 -0
- data/lib/dsfr/components/version.rb +1 -1
- data/lib/generators/dsfr_component/templates/component.haml.erb +1 -1
- metadata +16 -34
- data/app/helpers/dsfr_skip_link_helper.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3abead9a7b02e13cbbe5cfa9e1d9efa24db78ff92e6560920823e232da2686a
|
4
|
+
data.tar.gz: 1257756ffd30ee9e631a095967f7c430b7902516952b4f328e8ba9f54825c994
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93de62ccadb3a81c1991ff9f85c42e4f52e0dad62513b958656b20eac58b6a376f67b5394ea395def361bb7cc22e08a26a16681783eec5d2c3889ae5bc3128da
|
7
|
+
data.tar.gz: 79b0c4176685a04c0875ccd70a015ba70aeae6ff948fcf907538211e98880cde86dae51097edd14e0a45f69f8f4866c6a2c6cfe7b60aa361b609a463e14aa67a
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%= tag.section(**html_attributes) do %>
|
2
|
-
<%= tag.send(
|
2
|
+
<%= tag.send(starting_header_tag, class: "fr-accordion__title") do %>
|
3
3
|
<button
|
4
4
|
class="fr-accordion__btn"
|
5
5
|
aria-expanded="<%= expanded? ? "true" : "false" %>"
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class DsfrComponent::AccordionComponent::SectionComponent < DsfrComponent::Base
|
2
|
+
include DsfrComponent::Traits::HeaderSizeable
|
3
|
+
|
2
4
|
attr_reader :title, :expanded, :starting_header_level
|
3
5
|
|
4
6
|
alias_method :expanded?, :expanded
|
@@ -11,7 +13,6 @@ class DsfrComponent::AccordionComponent::SectionComponent < DsfrComponent::Base
|
|
11
13
|
starting_header_level:,
|
12
14
|
expanded: false,
|
13
15
|
id: nil,
|
14
|
-
classes: [],
|
15
16
|
html_attributes: {}
|
16
17
|
)
|
17
18
|
@title = title
|
@@ -19,7 +20,7 @@ class DsfrComponent::AccordionComponent::SectionComponent < DsfrComponent::Base
|
|
19
20
|
@id = id
|
20
21
|
@starting_header_level = starting_header_level
|
21
22
|
|
22
|
-
super(
|
23
|
+
super(html_attributes: html_attributes)
|
23
24
|
end
|
24
25
|
|
25
26
|
def id
|
@@ -1,11 +1,8 @@
|
|
1
1
|
class DsfrComponent::AccordionComponent < DsfrComponent::Base
|
2
|
-
|
2
|
+
include DsfrComponent::Traits::HeaderSizeable
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
renders_many :sections, ->(title: nil, expanded: false, id: nil, classes: [], html_attributes: {}, &block) do
|
4
|
+
renders_many :sections, ->(title: nil, expanded: false, id: nil, html_attributes: {}, &block) do
|
7
5
|
DsfrComponent::AccordionComponent::SectionComponent.new(
|
8
|
-
classes: classes,
|
9
6
|
expanded: expanded,
|
10
7
|
html_attributes: html_attributes,
|
11
8
|
title: title,
|
@@ -15,10 +12,10 @@ class DsfrComponent::AccordionComponent < DsfrComponent::Base
|
|
15
12
|
)
|
16
13
|
end
|
17
14
|
|
18
|
-
def initialize(
|
15
|
+
def initialize(html_attributes: {}, starting_header_level: nil)
|
19
16
|
@starting_header_level = starting_header_level
|
20
17
|
|
21
|
-
super(
|
18
|
+
super(html_attributes: html_attributes)
|
22
19
|
end
|
23
20
|
|
24
21
|
private
|
@@ -7,18 +7,19 @@ class DsfrComponent::AlertComponent < DsfrComponent::Base
|
|
7
7
|
# @param size [Symbol] alert size : `:md` (default) or `:sm`
|
8
8
|
# @param close_button [Boolean] display a close button to remove the alert
|
9
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
|
10
|
+
def initialize(type: nil, title: nil, size: :md, close_button: false, icon_name: nil, html_attributes: {})
|
11
11
|
@title = title
|
12
12
|
@type = type
|
13
13
|
@size = size
|
14
14
|
@close_button = close_button
|
15
|
+
@icon_name = icon_name
|
15
16
|
|
16
|
-
super(
|
17
|
+
super(html_attributes: html_attributes)
|
17
18
|
end
|
18
19
|
|
19
20
|
def call
|
20
|
-
|
21
|
-
|
21
|
+
check_main_content!
|
22
|
+
check_icon_allowed!
|
22
23
|
|
23
24
|
tag.div(**html_attributes) do
|
24
25
|
safe_join([title_tag, content_tag, close_button_tag])
|
@@ -27,10 +28,36 @@ class DsfrComponent::AlertComponent < DsfrComponent::Base
|
|
27
28
|
|
28
29
|
private
|
29
30
|
|
30
|
-
attr_reader :title, :type, :size, :close_button
|
31
|
+
attr_reader :title, :type, :size, :close_button, :icon_name
|
31
32
|
|
32
33
|
def default_attributes
|
33
|
-
{ class: %w(fr-alert) + [type_class, size_class].compact }
|
34
|
+
{ class: %w(fr-alert) + [icon_class, type_class, size_class].compact }
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_type?
|
38
|
+
type.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_icon_allowed!
|
42
|
+
raise ArgumentError, "a custom icon can only be used on default alert types" if icon_name && !default_type?
|
43
|
+
end
|
44
|
+
|
45
|
+
def main_content?
|
46
|
+
case size
|
47
|
+
when :sm
|
48
|
+
content.present? && title.blank?
|
49
|
+
when :md
|
50
|
+
content.present? || title.present?
|
51
|
+
else
|
52
|
+
raise ArgumentError, "invalid alert size: '#{size}', supported sizes are #{SIZES.to_sentence}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def check_main_content!
|
57
|
+
raise(
|
58
|
+
ArgumentError,
|
59
|
+
"You must provide a title for medium alerts, but you can't use it for small alerts (use content instead)"
|
60
|
+
) if not main_content?
|
34
61
|
end
|
35
62
|
|
36
63
|
def title_tag
|
@@ -57,33 +84,31 @@ private
|
|
57
84
|
end
|
58
85
|
end
|
59
86
|
|
60
|
-
def
|
61
|
-
|
87
|
+
def icon_class
|
88
|
+
return nil if icon_name.blank?
|
62
89
|
|
63
|
-
"fr-
|
90
|
+
"fr-icon-#{icon_name}"
|
64
91
|
end
|
65
92
|
|
66
93
|
def valid_type?
|
67
94
|
type.in?(TYPES)
|
68
95
|
end
|
69
96
|
|
70
|
-
def
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
def size_class
|
75
|
-
return nil if size == :md
|
97
|
+
def type_class
|
98
|
+
return nil if type.blank?
|
76
99
|
|
77
|
-
|
100
|
+
raise ArgumentError, "invalid alert type #{type}, supported types are #{TYPES.to_sentence}" unless valid_type?
|
78
101
|
|
79
|
-
"fr-alert--#{
|
102
|
+
"fr-alert--#{type}"
|
80
103
|
end
|
81
104
|
|
82
105
|
def valid_size?
|
83
106
|
size.in?(SIZES)
|
84
107
|
end
|
85
108
|
|
86
|
-
def
|
87
|
-
|
109
|
+
def size_class
|
110
|
+
return nil if size == :md
|
111
|
+
|
112
|
+
"fr-alert--#{size}"
|
88
113
|
end
|
89
114
|
end
|
@@ -3,14 +3,12 @@ module DsfrComponent
|
|
3
3
|
STATUSES = %i[success error info warning new].freeze
|
4
4
|
|
5
5
|
# @param status [BadgeComponent::STATUSES]
|
6
|
-
def initialize(status:,
|
6
|
+
def initialize(status:, html_attributes: {})
|
7
7
|
raise(ArgumentError, "`status` should be one of #{STATUSES}") unless STATUSES.include?(status)
|
8
8
|
|
9
9
|
@status = status
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
super(classes: classes, html_attributes: html_attributes)
|
11
|
+
super(html_attributes: html_attributes)
|
14
12
|
end
|
15
13
|
|
16
14
|
def call
|
@@ -24,7 +22,7 @@ module DsfrComponent
|
|
24
22
|
attr_reader :status
|
25
23
|
|
26
24
|
def default_attributes
|
27
|
-
{ class: 'fr-badge' }
|
25
|
+
{ class: ['fr-badge', "fr-badge--#{status}"] }
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
@@ -9,21 +9,8 @@ class DsfrComponent::Base < ViewComponent::Base
|
|
9
9
|
|
10
10
|
SIZES = %i[sm md lg].freeze
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
if classes.nil?
|
14
|
-
Rails.logger.warn("classes is nil, if no custom classes are needed omit the param")
|
15
|
-
|
16
|
-
classes = []
|
17
|
-
end
|
18
|
-
# FIXME: remove first merge when we deprecate classes
|
19
|
-
#
|
20
|
-
# This step only needs to be here while we still accept classes:, now
|
21
|
-
# we're using html_attributes_utils we can start to move towards
|
22
|
-
# supporting html_attributes: { class: 'xyz' } over taking them
|
23
|
-
# separately
|
24
|
-
|
12
|
+
def initialize(html_attributes: {})
|
25
13
|
@html_attributes = default_attributes
|
26
|
-
.deep_merge_html_attributes({ class: classes })
|
27
14
|
.deep_merge_html_attributes(html_attributes)
|
28
15
|
.deep_tidy_html_attributes
|
29
16
|
|
@@ -9,10 +9,6 @@ class DsfrComponent::BreadcrumbsComponent < DsfrComponent::Base
|
|
9
9
|
content_tag(:a, class: 'fr-breadcrumb__link', **attributes) { label }
|
10
10
|
end
|
11
11
|
|
12
|
-
def initialize(classes: [], html_attributes: {})
|
13
|
-
super(classes: classes, html_attributes: html_attributes)
|
14
|
-
end
|
15
|
-
|
16
12
|
private
|
17
13
|
|
18
14
|
def default_attributes
|
@@ -10,7 +10,7 @@ module DsfrComponent
|
|
10
10
|
# @param title [String] Le titre du bouton permettant d’afficher une infobulle (optionnel)
|
11
11
|
# @param level [String] Le niveau du bouton : :primary (défaut), :secondary ou :tertiary (optionnel)
|
12
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,
|
13
|
+
def initialize(label: nil, title: nil, icon: nil, icon_position: :left, level: nil, size: nil, html_attributes: {})
|
14
14
|
@label = label
|
15
15
|
@title = title
|
16
16
|
@icon = icon
|
@@ -24,7 +24,7 @@ module DsfrComponent
|
|
24
24
|
validate_level
|
25
25
|
validate_label
|
26
26
|
|
27
|
-
super(
|
27
|
+
super(html_attributes: html_attributes)
|
28
28
|
end
|
29
29
|
|
30
30
|
def call
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DsfrComponent
|
4
|
+
class CalloutComponent < DsfrComponent::Base
|
5
|
+
include DsfrComponent::Traits::HeaderSizeable
|
6
|
+
|
7
|
+
renders_one :action_zone
|
8
|
+
|
9
|
+
# @param title [String] Le titre de la mise en avant
|
10
|
+
# @param icon_name [String] Le nom de l’icône à afficher (exemple `arrow-right-line`) (optionnel)
|
11
|
+
# @param starting_header_level [Integer] Le niveau de titre (optionnel)
|
12
|
+
def initialize(
|
13
|
+
title:,
|
14
|
+
icon_name: "information-line",
|
15
|
+
starting_header_level: nil,
|
16
|
+
html_attributes: {}
|
17
|
+
)
|
18
|
+
@title = title
|
19
|
+
@icon_name = icon_name
|
20
|
+
@starting_header_level = starting_header_level
|
21
|
+
|
22
|
+
super(html_attributes: html_attributes)
|
23
|
+
end
|
24
|
+
|
25
|
+
def call
|
26
|
+
tag.div(**html_attributes) do
|
27
|
+
concat content_tag(starting_header_tag, @title, class: 'fr-callout__title')
|
28
|
+
|
29
|
+
concat content_tag(:p, content, class: 'fr-callout__text')
|
30
|
+
|
31
|
+
concat action_zone if action_zone?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def default_attributes
|
38
|
+
{ class: "fr-callout fr-icon-#{@icon_name}" }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
class DsfrComponent::HeaderComponent::DirectLinkComponent < DsfrComponent::Base
|
2
|
-
def initialize(title:, path:, active: false,
|
2
|
+
def initialize(title:, path:, active: false, html_attributes: {})
|
3
3
|
@title = title
|
4
4
|
@path = path
|
5
5
|
@active = active
|
6
6
|
|
7
|
-
super(
|
7
|
+
super(html_attributes: html_attributes)
|
8
8
|
end
|
9
9
|
|
10
10
|
def call
|
@@ -1,11 +1,11 @@
|
|
1
1
|
class DsfrComponent::HeaderComponent::DirectLinkDropdownComponent < DsfrComponent::Base
|
2
2
|
renders_many :links, DsfrComponent::HeaderComponent::DirectLinkComponent
|
3
3
|
|
4
|
-
def initialize(title:, active: false,
|
4
|
+
def initialize(title:, active: false, html_attributes: {})
|
5
5
|
@title = title
|
6
6
|
@active = active
|
7
7
|
|
8
|
-
super(
|
8
|
+
super(html_attributes: html_attributes)
|
9
9
|
end
|
10
10
|
|
11
11
|
def call
|
@@ -2,12 +2,12 @@ class DsfrComponent::HeaderComponent::OperatorImageComponent < DsfrComponent::Ba
|
|
2
2
|
# @param title [String] Le title du lien vers la page d'accueil du site
|
3
3
|
# @param src [String] L'attribut src qui sera passé au tag img
|
4
4
|
# @param alt [String] Le texte alternatif qui sera passé au tag img. Il doit impérativement contenir le texte présent dans l’image.
|
5
|
-
def initialize(title:, src:, alt:,
|
5
|
+
def initialize(title:, src:, alt:, html_attributes: {})
|
6
6
|
@title = title
|
7
7
|
@src = src
|
8
8
|
@alt = alt
|
9
9
|
|
10
|
-
super(
|
10
|
+
super(html_attributes: html_attributes)
|
11
11
|
end
|
12
12
|
|
13
13
|
def call
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class DsfrComponent::HeaderComponent::ToolLinkComponent < DsfrComponent::Base
|
2
|
-
def initialize(title:, path:,
|
2
|
+
def initialize(title:, path:, html_attributes: {})
|
3
3
|
@title = title
|
4
4
|
@path = path
|
5
5
|
|
6
|
-
super(
|
6
|
+
super(html_attributes: html_attributes)
|
7
7
|
end
|
8
8
|
|
9
9
|
def call
|
@@ -10,12 +10,12 @@ class DsfrComponent::HeaderComponent < DsfrComponent::Base
|
|
10
10
|
# @param logo_text [String] Ce texte obligatoire sera affiché en dessous de la Marianne et au dessus de la devise française. C’est généralement un nom de ministère ou d’administration.
|
11
11
|
# @param title [String] Le nom du service numérique, titre principal du site.
|
12
12
|
# @param tagline [String] La description du service numérique, sous-titre du site (optionnelle).
|
13
|
-
def initialize(logo_text:, title: nil, tagline: nil,
|
13
|
+
def initialize(logo_text:, title: nil, tagline: nil, html_attributes: {})
|
14
14
|
@logo_text = logo_text
|
15
15
|
@title = title
|
16
16
|
@tagline = tagline
|
17
17
|
|
18
|
-
super(
|
18
|
+
super(html_attributes: html_attributes)
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -2,13 +2,13 @@ module DsfrComponent
|
|
2
2
|
class HighlightComponent < DsfrComponent::Base
|
3
3
|
# @param text [String] Le contenu textuel du composant
|
4
4
|
# @param size [Symbol] La taille de la mise en exergue
|
5
|
-
def initialize(text:, size: :md,
|
5
|
+
def initialize(text:, size: :md, html_attributes: {})
|
6
6
|
@text = text
|
7
7
|
@size = size
|
8
8
|
|
9
9
|
raise ArgumentError if not SIZES.include?(size)
|
10
10
|
|
11
|
-
super(
|
11
|
+
super(html_attributes: html_attributes)
|
12
12
|
end
|
13
13
|
|
14
14
|
def call
|
@@ -5,12 +5,12 @@ module DsfrComponent
|
|
5
5
|
|
6
6
|
# @param title [String] Titre de la modale
|
7
7
|
# @param opened [Boolean] Ouvre la modale dès le chargement de la page
|
8
|
-
def initialize(title:, opened: false,
|
8
|
+
def initialize(title:, opened: false, html_attributes: {})
|
9
9
|
@title = title
|
10
10
|
@opened = opened
|
11
11
|
|
12
12
|
@id = html_attributes[:id]
|
13
|
-
super(
|
13
|
+
super(html_attributes: html_attributes)
|
14
14
|
end
|
15
15
|
|
16
16
|
private
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<%= tag.div(**html_attributes) do %>
|
2
|
+
<div class="fr-container">
|
3
|
+
<div class="fr-notice__body">
|
4
|
+
<%= tag.send(description_tag) do %>
|
5
|
+
<span class="fr-notice__title <%= icon_class %>"><%= title %></span>
|
6
|
+
<span class="fr-notice__desc"><%= description %></span>
|
7
|
+
<%= link_tag %>
|
8
|
+
<% end %>
|
9
|
+
<% if dismissible %>
|
10
|
+
<button onclick="const notice = this.parentNode.parentNode.parentNode; notice.parentNode.removeChild(notice)" title="<%= @dismiss_label %>" type="button" class="fr-btn--close fr-btn"><%= @dismiss_label %></button>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module DsfrComponent
|
2
|
+
class NoticeComponent < DsfrComponent::Base
|
3
|
+
GENERIC_TYPES = %w[info waring alert].freeze
|
4
|
+
WEATHER_TYPES = %w[weather-orange weather-red weather-purple].freeze
|
5
|
+
ALERT_TYPES = %w[kidnapping cyberattack attack witness].freeze
|
6
|
+
TYPES = GENERIC_TYPES + WEATHER_TYPES + ALERT_TYPES
|
7
|
+
|
8
|
+
WEATHER_ICONS = %w[windy-fill thunderstorms-fill heavy-showers-fill flood-fill temp-cold-fill sun-fill avalanches-fill snowy-fill].freeze
|
9
|
+
|
10
|
+
DESCRIPTION_TAGS = %i[p h1 h2 h3 h4 h5 h6].freeze
|
11
|
+
|
12
|
+
# @param title [String] Titre du bandeau
|
13
|
+
# @param description [String] Description du bandeau pour apporter du contexte (optionnel)
|
14
|
+
# @param type [String] Type de bandeau (info, waring, alert, weather-orange, weather-red, weather-purple, kidnapping, cyberattack, attack, witness)
|
15
|
+
# @param description_tag [Symbol] Balise HTML à utiliser pour la description (p, h1, h2, h3, h4, h5, h6)
|
16
|
+
# @param use_icon [Boolean] Afficher ou non une icône, uniquement pour les bandeaux génériques
|
17
|
+
# @param icon_name [String] Nom de l'icône à afficher
|
18
|
+
# @param use_notice [Boolean] Ajout l’attribut role="notice" (si insertion du bandeau à la volée)
|
19
|
+
# @param dismissible [Boolean] Ajouter un bouton de fermeture
|
20
|
+
# @param dismiss_label [String] Libellé du bouton de fermeture (optionnel)
|
21
|
+
# @param link_label [String] Libellé du lien (optionnel)
|
22
|
+
# @param link_href [String] URL du lien (optionnel)
|
23
|
+
# @param link_title [String] Titre du lien (optionnel)
|
24
|
+
# @param link_blank [Boolean] Ouvrir le lien dans un nouvel onglet (optionnel)
|
25
|
+
def initialize(title:, description:, type: "info", description_tag: :p, use_icon: true, icon_name: nil, use_notice: false, dismissible: false, dismiss_label: "Masquer le message", link_label: nil, link_href: nil, link_title: nil, link_blank: true,
|
26
|
+
html_attributes: {})
|
27
|
+
@title = title
|
28
|
+
@description = description
|
29
|
+
@type = type
|
30
|
+
@description_tag = description_tag
|
31
|
+
@icon_name = icon_name
|
32
|
+
@use_notice = use_notice
|
33
|
+
@dismissible = dismissible
|
34
|
+
@dismiss_label = dismiss_label
|
35
|
+
@link_label = link_label
|
36
|
+
@link_href = link_href
|
37
|
+
@link_title = link_title
|
38
|
+
@link_blank = link_blank
|
39
|
+
|
40
|
+
# D’après les règles du DSFR les types non génériques ont forcément une icône
|
41
|
+
@use_icon = if GENERIC_TYPES.include?(type)
|
42
|
+
use_icon
|
43
|
+
else
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
raise ArgumentError, "Invalid type: #{type}. Valid types: #{TYPES.join(', ')}" unless type_valid?
|
48
|
+
|
49
|
+
raise ArgumentError, "Invalid description tag: #{description_tag}" unless DESCRIPTION_TAGS.include?(description_tag)
|
50
|
+
|
51
|
+
if icon_name
|
52
|
+
raise ArgumentError, "L’icône n’est pas personnalisable sur les bandeaux d’alertes" if ALERT_TYPES.include?(type)
|
53
|
+
raise ArgumentError, "L’icône d’un bandeau de type météo doit être une icône météo (#{WEATHER_ICONS.join(', ')})" if WEATHER_TYPES.include?(type) && WEATHER_ICONS.exclude?(icon_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
super(html_attributes: html_attributes)
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
attr_reader :type, :title, :description, :description_tag, :use_icon, :icon_name, :use_notice, :dismissible, :link_label, :link_href, :link_title, :link_blank
|
62
|
+
|
63
|
+
def notice_class
|
64
|
+
"fr-notice--#{type}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def type_valid?
|
68
|
+
TYPES.include?(type)
|
69
|
+
end
|
70
|
+
|
71
|
+
def link_display?
|
72
|
+
link_label.present? && link_href.present?
|
73
|
+
end
|
74
|
+
|
75
|
+
def link_tag
|
76
|
+
return unless link_display?
|
77
|
+
|
78
|
+
target = @link_blank ? "_blank" : "_self"
|
79
|
+
|
80
|
+
link_to(link_label, link_href, title: link_title, target: target)
|
81
|
+
end
|
82
|
+
|
83
|
+
def icon_class
|
84
|
+
return unless icon_name
|
85
|
+
|
86
|
+
"fr-icon-#{icon_name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def default_attributes
|
90
|
+
class_attr = "fr-notice #{notice_class}"
|
91
|
+
class_attr += " fr-notice--no-icon" unless use_icon
|
92
|
+
|
93
|
+
attr = { class: class_attr }
|
94
|
+
attr[:role] = "notice" if use_notice
|
95
|
+
|
96
|
+
attr
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= form_with(url: url, method: :get, **html_attributes) do |form| %>
|
2
|
+
<% hidden_fields.each do |name, value| %>
|
3
|
+
<%= form.hidden_field(name, value: value) %>
|
4
|
+
<% end %>
|
5
|
+
<%= form.label(name, label_text, for: id, class: 'fr-label') %>
|
6
|
+
<%= form.search_field(name, id: id, placeholder: button_text, value: value, class: 'fr-input') %>
|
7
|
+
<%= form.button(type: :submit, name: nil, class: 'fr-btn') { button_text } %>
|
8
|
+
<% end %>
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module DsfrComponent
|
2
|
+
class SearchComponent < DsfrComponent::Base
|
3
|
+
DEFAULT_LABEL_TEXT = 'Recherche'.freeze
|
4
|
+
DEFAULT_BUTTON_TEXT = 'Rechercher'.freeze
|
5
|
+
|
6
|
+
# @param url [String] form destination
|
7
|
+
# @param name [String|Symbol] input name
|
8
|
+
# @param size [Symbol] component size : `:md` (default) or `:sm`/`:lg`
|
9
|
+
# @param label_text [String] Label text, default: "Recherche"
|
10
|
+
# @param button_text [String] Button and placeholder text, default: "Rechercher"
|
11
|
+
# @param value [String] Current input value (optional, defaults to request.params[name])
|
12
|
+
# @param hidden_fields [Hash] Extra fields (optional)
|
13
|
+
def initialize(url:, name: :search, size: :md, label_text: DEFAULT_LABEL_TEXT, button_text: DEFAULT_BUTTON_TEXT, **html_attributes)
|
14
|
+
@url = url
|
15
|
+
@name = name
|
16
|
+
@label_text = label_text
|
17
|
+
@button_text = button_text
|
18
|
+
@size = size
|
19
|
+
@value = html_attributes.delete(:value)
|
20
|
+
@hidden_fields = html_attributes.delete(:hidden_fields) || {}
|
21
|
+
@html_attributes = html_attributes
|
22
|
+
|
23
|
+
validate_size!
|
24
|
+
|
25
|
+
super(html_attributes: html_attributes)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :url, :size, :name, :label_text, :button_text, :hidden_fields, :html_attributes
|
31
|
+
|
32
|
+
def id
|
33
|
+
"#{name}_#{object_id}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def value
|
37
|
+
@value || (request && request.params[name])
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_attributes
|
41
|
+
classes = ['fr-search-bar']
|
42
|
+
classes << "fr-search-bar--#{size}" unless size == :md
|
43
|
+
{ class: classes }
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate_size!
|
47
|
+
raise(ArgumentError, "`size` should be one of #{SIZES}") if size.present? && SIZES.exclude?(size)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -2,11 +2,11 @@ module DsfrComponent
|
|
2
2
|
class SkiplinkComponent < DsfrComponent::Base
|
3
3
|
# @param label [String] le texte utilisé pour le aria-label de la nav qui affiche les liens d’évitement (par exemple « Accès rapide »)
|
4
4
|
# @param links [Array] liste de liens HTML
|
5
|
-
def initialize(label:, links:,
|
5
|
+
def initialize(label:, links:, html_attributes: {})
|
6
6
|
@label = label
|
7
7
|
@links = links
|
8
8
|
|
9
|
-
super(
|
9
|
+
super(html_attributes: html_attributes)
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
@@ -4,7 +4,7 @@ module DsfrComponent
|
|
4
4
|
# @param value [Integer] Numéro de l’étape en cours (commence à 1)
|
5
5
|
# @param max [Integer] Nombre d’étapes total
|
6
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,
|
7
|
+
def initialize(title:, value:, max:, next_title: nil, html_attributes: {})
|
8
8
|
@title = title
|
9
9
|
@value = value
|
10
10
|
@max = max
|
@@ -12,7 +12,7 @@ module DsfrComponent
|
|
12
12
|
|
13
13
|
raise ArgumentError, "Les étapes doivent aller de 1 jusqu´à 8 au maximum" if @value < 1 || @value > @max || @max > 8
|
14
14
|
|
15
|
-
super(
|
15
|
+
super(html_attributes: html_attributes)
|
16
16
|
end
|
17
17
|
|
18
18
|
private
|
@@ -3,13 +3,13 @@ class DsfrComponent::TabsComponent::TabComponent < DsfrComponent::Base
|
|
3
3
|
# @param active [Boolean] Définit si l’onglet est actif ou non
|
4
4
|
# @param path [String] (optionnel) chemin vers lequel l’onglet pointe, utilisable avec Turbo Drive, transforme le bouton en lien, avec une turbo action `advance`
|
5
5
|
# @param icon [String] (optionnel) icône affichée à gauche du titre de l’onglet (sans le préfixe `fr-icon-`)
|
6
|
-
def initialize(title:, active: false, path: nil, icon: nil,
|
6
|
+
def initialize(title:, active: false, path: nil, icon: nil, html_attributes: {})
|
7
7
|
@title = title
|
8
8
|
@active = active
|
9
9
|
@path = path
|
10
10
|
@icon = icon
|
11
11
|
|
12
|
-
super(
|
12
|
+
super(html_attributes: html_attributes)
|
13
13
|
end
|
14
14
|
|
15
15
|
def nav_id
|
@@ -2,11 +2,11 @@ class DsfrComponent::TabsComponent < DsfrComponent::Base
|
|
2
2
|
renders_many :tabs, "DsfrComponent::TabsComponent::TabComponent"
|
3
3
|
|
4
4
|
# @param label [String] Le nom du système d’onglets, sera uniquement affiché comme aria-label (optionnel)
|
5
|
-
def initialize(label: nil,
|
5
|
+
def initialize(label: nil, html_attributes: {})
|
6
6
|
@label = label
|
7
7
|
@tabs = []
|
8
8
|
|
9
|
-
super(
|
9
|
+
super(html_attributes: html_attributes)
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
@@ -8,7 +8,7 @@ module DsfrComponent
|
|
8
8
|
# @param url [String] for clickable tags only (optional)
|
9
9
|
# @param selected [Boolean] adds a check, useful for filters list, cannot be used with `url` (optional)
|
10
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,
|
11
|
+
def initialize(title:, icon: nil, size: nil, url: nil, selected: nil, dismissable: nil, html_attributes: {})
|
12
12
|
@title = title
|
13
13
|
@icon = icon
|
14
14
|
@size = size
|
@@ -16,7 +16,7 @@ module DsfrComponent
|
|
16
16
|
@selected = selected
|
17
17
|
@dismissable = dismissable
|
18
18
|
|
19
|
-
super(
|
19
|
+
super(html_attributes: html_attributes)
|
20
20
|
end
|
21
21
|
|
22
22
|
def call
|
@@ -7,7 +7,7 @@ module DsfrComponent
|
|
7
7
|
# @param description [String] description (optional)
|
8
8
|
# @param orientation [String] :horizontal or :vertical
|
9
9
|
# @param heading_level [Integer] 1, 2, 3, 4 (default), 5, 6
|
10
|
-
def initialize(title:, url:, image_src: nil, image_alt: "", description: nil, orientation: :vertical, heading_level: 4,
|
10
|
+
def initialize(title:, url:, image_src: nil, image_alt: "", description: nil, orientation: :vertical, heading_level: 4, html_attributes: {})
|
11
11
|
@title = title
|
12
12
|
@url = url
|
13
13
|
@image_src = image_src
|
@@ -18,7 +18,7 @@ module DsfrComponent
|
|
18
18
|
|
19
19
|
raise ArgumentError if HEADING_LEVELS.exclude?(heading_level)
|
20
20
|
|
21
|
-
super(
|
21
|
+
super(html_attributes: html_attributes)
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DsfrComponent
|
4
|
+
module Traits
|
5
|
+
# HeaderSizeable is meant for every component that exhibits a
|
6
|
+
# header, which level can be overriden via the
|
7
|
+
# `default_header_level` method. Make sure you store the attribute
|
8
|
+
# `@starting_header_level` in your component's constructor.
|
9
|
+
module HeaderSizeable
|
10
|
+
DEFAULT_HEADER_LEVEL = 3
|
11
|
+
|
12
|
+
def starting_header_level
|
13
|
+
@starting_header_level || default_header_level
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_header_level
|
17
|
+
DEFAULT_HEADER_LEVEL
|
18
|
+
end
|
19
|
+
|
20
|
+
def starting_header_tag
|
21
|
+
["h", starting_header_level].join
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -18,6 +18,9 @@ module DsfrComponentsHelper
|
|
18
18
|
dsfr_tabs: 'DsfrComponent::TabsComponent',
|
19
19
|
dsfr_highlight: 'DsfrComponent::HighlightComponent',
|
20
20
|
dsfr_skiplink: 'DsfrComponent::SkiplinkComponent',
|
21
|
+
dsfr_callout: 'DsfrComponent::CalloutComponent',
|
22
|
+
dsfr_notice: 'DsfrComponent::NoticeComponent',
|
23
|
+
dsfr_search: 'DsfrComponent::SearchComponent',
|
21
24
|
# DO NOT REMOVE: new component mapping here
|
22
25
|
}.freeze
|
23
26
|
HELPER_NAME_TO_CLASS_NAME.each do |name, klass|
|
@@ -10,4 +10,4 @@ title: <%= name %>
|
|
10
10
|
:markdown
|
11
11
|
Le rendu de base du <%= name %>Component
|
12
12
|
|
13
|
-
= render('/partials/related-info.haml', links:
|
13
|
+
= render('/partials/related-info.haml', links: dsfr_component_doc_links("doc-id", "storybook-id"))
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dsfr-view-components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BetaGouv developers
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-24 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: html-attributes-utils
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
- !ruby/object:Gem::Version
|
67
67
|
version: '0'
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
|
-
name:
|
69
|
+
name: debug
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - ">="
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '0'
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
|
-
name: guard
|
83
|
+
name: guard
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - ">="
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '0'
|
96
96
|
- !ruby/object:Gem::Dependency
|
97
|
-
name:
|
97
|
+
name: guard-rspec
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
99
99
|
requirements:
|
100
100
|
- - ">="
|
@@ -303,34 +303,6 @@ dependencies:
|
|
303
303
|
- - "~>"
|
304
304
|
- !ruby/object:Gem::Version
|
305
305
|
version: 0.7.0
|
306
|
-
- !ruby/object:Gem::Dependency
|
307
|
-
name: slim
|
308
|
-
requirement: !ruby/object:Gem::Requirement
|
309
|
-
requirements:
|
310
|
-
- - "~>"
|
311
|
-
- !ruby/object:Gem::Version
|
312
|
-
version: 4.1.0
|
313
|
-
type: :development
|
314
|
-
prerelease: false
|
315
|
-
version_requirements: !ruby/object:Gem::Requirement
|
316
|
-
requirements:
|
317
|
-
- - "~>"
|
318
|
-
- !ruby/object:Gem::Version
|
319
|
-
version: 4.1.0
|
320
|
-
- !ruby/object:Gem::Dependency
|
321
|
-
name: slim_lint
|
322
|
-
requirement: !ruby/object:Gem::Requirement
|
323
|
-
requirements:
|
324
|
-
- - "~>"
|
325
|
-
- !ruby/object:Gem::Version
|
326
|
-
version: 0.22.0
|
327
|
-
type: :development
|
328
|
-
prerelease: false
|
329
|
-
version_requirements: !ruby/object:Gem::Requirement
|
330
|
-
requirements:
|
331
|
-
- - "~>"
|
332
|
-
- !ruby/object:Gem::Version
|
333
|
-
version: 0.22.0
|
334
306
|
- !ruby/object:Gem::Dependency
|
335
307
|
name: webrick
|
336
308
|
requirement: !ruby/object:Gem::Requirement
|
@@ -368,6 +340,7 @@ files:
|
|
368
340
|
- app/components/dsfr_component/breadcrumbs_component.html.erb
|
369
341
|
- app/components/dsfr_component/breadcrumbs_component.rb
|
370
342
|
- app/components/dsfr_component/button_component.rb
|
343
|
+
- app/components/dsfr_component/callout_component.rb
|
371
344
|
- app/components/dsfr_component/header_component.html.erb
|
372
345
|
- app/components/dsfr_component/header_component.rb
|
373
346
|
- app/components/dsfr_component/header_component/direct_link_component.rb
|
@@ -377,6 +350,10 @@ files:
|
|
377
350
|
- app/components/dsfr_component/highlight_component.rb
|
378
351
|
- app/components/dsfr_component/modal_component.html.erb
|
379
352
|
- app/components/dsfr_component/modal_component.rb
|
353
|
+
- app/components/dsfr_component/notice_component.html.erb
|
354
|
+
- app/components/dsfr_component/notice_component.rb
|
355
|
+
- app/components/dsfr_component/search_component.html.erb
|
356
|
+
- app/components/dsfr_component/search_component.rb
|
380
357
|
- app/components/dsfr_component/skiplink_component.html.erb
|
381
358
|
- app/components/dsfr_component/skiplink_component.rb
|
382
359
|
- app/components/dsfr_component/stepper_component.html.erb
|
@@ -389,10 +366,10 @@ files:
|
|
389
366
|
- app/components/dsfr_component/tile_component.rb
|
390
367
|
- app/components/dsfr_component/traits.rb
|
391
368
|
- app/components/dsfr_component/traits/custom_html_attributes.rb
|
369
|
+
- app/components/dsfr_component/traits/header_sizeable.rb
|
392
370
|
- app/helpers/dsfr_back_to_top_link_helper.rb
|
393
371
|
- app/helpers/dsfr_components_helper.rb
|
394
372
|
- app/helpers/dsfr_link_helper.rb
|
395
|
-
- app/helpers/dsfr_skip_link_helper.rb
|
396
373
|
- config/routes.rb
|
397
374
|
- lib/dsfr/components.rb
|
398
375
|
- lib/dsfr/components/engine.rb
|
@@ -409,6 +386,11 @@ homepage: https://github.com/betagouv/dsfr-view-components
|
|
409
386
|
licenses:
|
410
387
|
- MIT
|
411
388
|
metadata:
|
389
|
+
bug_tracker_uri: https://github.com/betagouv/dsfr-view-components/issues
|
390
|
+
changelog_uri: https://github.com/betagouv/dsfr-view-components/releases
|
391
|
+
documentation_uri: https://www.rubydoc.info/gems/dsfr-view-components/
|
392
|
+
homepage_uri: https://github.com/betagouv/dsfr-view-components
|
393
|
+
source_code_uri: https://github.com/betagouv/dsfr-view-components
|
412
394
|
rubygems_mfa_required: 'true'
|
413
395
|
rdoc_options: []
|
414
396
|
require_paths:
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module DsfrSkipLinkHelper
|
2
|
-
def dsfr_skip_link(text: 'Skip to main content', href: '#main-content', classes: [], **html_attributes, &block)
|
3
|
-
link_classes = Array.wrap(classes).append('govuk-skip-link')
|
4
|
-
|
5
|
-
html_attributes_with_data_module = { data: { module: "govuk-skip-link" } }.deep_merge(html_attributes)
|
6
|
-
|
7
|
-
return link_to(href, class: link_classes, **html_attributes_with_data_module, &block) if block_given?
|
8
|
-
|
9
|
-
link_to(text, href, class: link_classes, **html_attributes_with_data_module)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
ActiveSupport.on_load(:action_view) { include DsfrSkipLinkHelper }
|