rails-active-ui 0.3.8 → 0.4.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/README.md +195 -6
- data/Rakefile +1 -1
- data/app/components/accordion_component.rb +41 -24
- data/app/components/accordion_item_component.rb +40 -0
- data/app/components/ad_component.rb +1 -1
- data/app/components/api_component.rb +1 -1
- data/app/components/breadcrumb_component.rb +1 -1
- data/app/components/button_group_component.rb +36 -0
- data/app/components/button_to_component.rb +1 -1
- data/app/components/calendar_component.rb +24 -20
- data/app/components/card_component.rb +5 -3
- data/app/components/comment_component.rb +5 -3
- data/app/components/comment_group_component.rb +27 -0
- data/app/components/comment_reply_component.rb +47 -0
- data/app/components/comment_reply_group_component.rb +25 -0
- data/app/components/dimmer_component.rb +1 -1
- data/app/components/divider_component.rb +1 -1
- data/app/components/dropdown_component.rb +6 -2
- data/app/components/embed_component.rb +1 -1
- data/app/components/emoji_component.rb +1 -1
- data/app/components/feed_component.rb +16 -4
- data/app/components/feed_item_component.rb +85 -0
- data/app/components/field_component.rb +42 -0
- data/app/components/flag_component.rb +1 -1
- data/app/components/flyout_component.rb +3 -2
- data/app/components/h_stack_component.rb +1 -1
- data/app/components/header_component.rb +2 -2
- data/app/components/image_component.rb +1 -1
- data/app/components/input_component.rb +22 -41
- data/app/components/item_component.rb +3 -2
- data/app/components/item_group_component.rb +1 -1
- data/app/components/list_component.rb +2 -2
- data/app/components/list_content_component.rb +27 -0
- data/app/components/list_description_component.rb +17 -0
- data/app/components/list_header_component.rb +28 -0
- data/app/components/list_item_component.rb +37 -0
- data/app/components/loader_component.rb +1 -1
- data/app/components/menu_component.rb +1 -1
- data/app/components/modal_component.rb +2 -1
- data/app/components/nag_component.rb +1 -1
- data/app/components/overlay_component.rb +1 -1
- data/app/components/placeholder_component.rb +37 -13
- data/app/components/popup_component.rb +1 -1
- data/app/components/progress_component.rb +1 -1
- data/app/components/pusher_component.rb +1 -1
- data/app/components/rail_component.rb +1 -1
- data/app/components/rating_component.rb +1 -1
- data/app/components/reveal_component.rb +3 -2
- data/app/components/row_component.rb +4 -0
- data/app/components/search_component.rb +1 -1
- data/app/components/segment_group_component.rb +1 -1
- data/app/components/shape_component.rb +1 -1
- data/app/components/sidebar_component.rb +1 -1
- data/app/components/site_component.rb +1 -1
- data/app/components/slider_component.rb +1 -1
- data/app/components/state_component.rb +1 -1
- data/app/components/statistic_component.rb +3 -2
- data/app/components/step_component.rb +2 -2
- data/app/components/step_group_component.rb +1 -1
- data/app/components/sticky_component.rb +1 -1
- data/app/components/style_component.rb +1 -1
- data/app/components/sub_accordion_component.rb +25 -0
- data/app/components/sub_header_component.rb +1 -1
- data/app/components/sub_menu_component.rb +1 -1
- data/app/components/table_cell_component.rb +2 -2
- data/app/components/table_component.rb +2 -2
- data/app/components/tag_component.rb +57 -0
- data/app/components/tag_group_component.rb +33 -0
- data/app/components/text_component.rb +1 -1
- data/app/components/toast_component.rb +1 -1
- data/app/components/transition_component.rb +2 -2
- data/app/components/v_stack_component.rb +1 -1
- data/app/components/visibility_component.rb +1 -1
- data/app/helpers/component_helper.rb +23 -6
- data/app/helpers/ui/fomantic_form_builder.rb +155 -201
- data/app/javascript/ui/controllers/fui_calendar_controller.js +18 -8
- data/lib/ui/version.rb +1 -1
- metadata +15 -3
- data/app/components/checkbox_component.rb +0 -41
- data/app/components/label_component.rb +0 -49
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# CommentReplyGroup — nested reply group within a Comment.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# Comment { |c|
|
|
7
|
+
# c.avatar { ... }
|
|
8
|
+
# c.author { text "Elliot" }
|
|
9
|
+
# CommentReplyGroup {
|
|
10
|
+
# CommentReply { |c| ... }
|
|
11
|
+
# }
|
|
12
|
+
# }
|
|
13
|
+
|
|
14
|
+
class CommentReplyGroupComponent < Component
|
|
15
|
+
attribute :collapsed, :boolean, default: false
|
|
16
|
+
|
|
17
|
+
def to_s
|
|
18
|
+
classes = class_names(
|
|
19
|
+
{ "collapsed" => collapsed },
|
|
20
|
+
"comments"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
tag.div(**merge_html_options(class: classes)) { @content }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -25,6 +25,6 @@ class DimmerComponent < Component
|
|
|
25
25
|
|
|
26
26
|
content_el = @content.present? ? tag.div(class: "content") { @content } : nil
|
|
27
27
|
|
|
28
|
-
tag.div(class: classes, data: { controller: "fui-dimmer" }) { content_el }
|
|
28
|
+
tag.div(**merge_html_options(class: classes, data: { controller: "fui-dimmer" })) { content_el }
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -28,6 +28,8 @@ class DropdownComponent < Component
|
|
|
28
28
|
attribute :disabled, :boolean, default: false
|
|
29
29
|
attribute :action, :string, default: nil
|
|
30
30
|
|
|
31
|
+
slot :trigger
|
|
32
|
+
|
|
31
33
|
def to_s
|
|
32
34
|
classes = class_names(
|
|
33
35
|
"ui",
|
|
@@ -49,17 +51,19 @@ class DropdownComponent < Component
|
|
|
49
51
|
hidden_opts[:name] = name if name
|
|
50
52
|
|
|
51
53
|
search_el = search ? tag.input(class: "search") : nil
|
|
54
|
+
trigger_el = @slots[:trigger]
|
|
52
55
|
text_el = if inline
|
|
53
56
|
tag.div(class: "text") { tag.h2(class: "ui header") { placeholder || "" } }
|
|
54
|
-
|
|
57
|
+
elsif !trigger_el
|
|
55
58
|
tag.div(class: "text") { placeholder || "" }
|
|
56
59
|
end
|
|
57
60
|
menu_el = tag.div(class: "menu") { @content }
|
|
58
61
|
|
|
59
|
-
tag.div(class: classes, data: data) {
|
|
62
|
+
tag.div(**merge_html_options(class: classes, data: data)) {
|
|
60
63
|
safe_join([
|
|
61
64
|
tag.input(**hidden_opts),
|
|
62
65
|
search_el,
|
|
66
|
+
trigger_el,
|
|
63
67
|
text_el,
|
|
64
68
|
tag.i(class: "dropdown icon"),
|
|
65
69
|
menu_el
|
|
@@ -25,7 +25,7 @@ class EmbedComponent < Component
|
|
|
25
25
|
icon_el = tag.i(class: "#{icon} icon")
|
|
26
26
|
placeholder_el = placeholder ? tag.img(class: "placeholder", src: placeholder) : nil
|
|
27
27
|
|
|
28
|
-
tag.div(class: "ui embed", data: data) {
|
|
28
|
+
tag.div(**merge_html_options(class: "ui embed", data: data)) {
|
|
29
29
|
safe_join([ icon_el, placeholder_el, @content ])
|
|
30
30
|
}
|
|
31
31
|
end
|
|
@@ -3,20 +3,32 @@
|
|
|
3
3
|
# Feed — activity/event feed.
|
|
4
4
|
#
|
|
5
5
|
# Usage:
|
|
6
|
-
# Feed(size:
|
|
7
|
-
#
|
|
6
|
+
# Feed(size: "small") {
|
|
7
|
+
# FeedEvent { |e| ... }
|
|
8
8
|
# }
|
|
9
9
|
|
|
10
10
|
class FeedComponent < Component
|
|
11
|
-
attribute :size,
|
|
11
|
+
attribute :size, :string, default: nil
|
|
12
|
+
attribute :inverted, :boolean, default: false
|
|
13
|
+
attribute :connected, :boolean, default: false
|
|
14
|
+
attribute :ordered, :boolean, default: false
|
|
15
|
+
attribute :divided, :boolean, default: false
|
|
16
|
+
attribute :disabled, :boolean, default: false
|
|
17
|
+
attribute :color, :string, default: nil
|
|
12
18
|
|
|
13
19
|
def to_s
|
|
14
20
|
classes = class_names(
|
|
15
21
|
"ui",
|
|
16
22
|
size,
|
|
23
|
+
color,
|
|
24
|
+
{ "inverted" => inverted },
|
|
25
|
+
{ "connected" => connected },
|
|
26
|
+
{ "ordered" => ordered },
|
|
27
|
+
{ "divided" => divided },
|
|
28
|
+
{ "disabled" => disabled },
|
|
17
29
|
"feed"
|
|
18
30
|
)
|
|
19
31
|
|
|
20
|
-
tag.div(class: classes) { @content }
|
|
32
|
+
tag.div(**merge_html_options(class: classes)) { @content }
|
|
21
33
|
end
|
|
22
34
|
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# FeedItem — a single item/event in a Feed.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# FeedItem { |e|
|
|
7
|
+
# e.label { Image(src: "/images/avatar/small/elliot.jpg") }
|
|
8
|
+
# e.summary {
|
|
9
|
+
# LinkTo(class: "user") { "Elliot Fu" }
|
|
10
|
+
# text " added you as a friend"
|
|
11
|
+
# }
|
|
12
|
+
# e.date { "1 Hour Ago" }
|
|
13
|
+
# e.meta {
|
|
14
|
+
# LinkTo(class: "like") {
|
|
15
|
+
# Icon(name: "like")
|
|
16
|
+
# text " 4 Likes"
|
|
17
|
+
# }
|
|
18
|
+
# }
|
|
19
|
+
# e.extra_text { "Some additional text" }
|
|
20
|
+
# e.extra_images {
|
|
21
|
+
# LinkTo { Image(src: "/images/wireframe/image.png") }
|
|
22
|
+
# }
|
|
23
|
+
# }
|
|
24
|
+
|
|
25
|
+
class FeedItemComponent < Component
|
|
26
|
+
attribute :disabled, :boolean, default: false
|
|
27
|
+
attribute :color, :string, default: nil
|
|
28
|
+
|
|
29
|
+
slot :label
|
|
30
|
+
slot :summary
|
|
31
|
+
slot :date
|
|
32
|
+
slot :date_inline
|
|
33
|
+
slot :meta
|
|
34
|
+
slot :extra_text
|
|
35
|
+
slot :extra_images
|
|
36
|
+
|
|
37
|
+
def to_s
|
|
38
|
+
classes = class_names(
|
|
39
|
+
{ "disabled" => disabled },
|
|
40
|
+
color,
|
|
41
|
+
"event"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
label_el = if @slots[:label]
|
|
45
|
+
tag.div(class: "label") { @slots[:label] }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
content_parts = []
|
|
49
|
+
|
|
50
|
+
# Date can appear at the top of content (outside summary)
|
|
51
|
+
if @slots[:date]
|
|
52
|
+
content_parts << tag.div(class: "date") { @slots[:date] }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Summary with optional inline date
|
|
56
|
+
if @slots[:summary]
|
|
57
|
+
summary_inner = @slots[:summary]
|
|
58
|
+
if @slots[:date_inline]
|
|
59
|
+
summary_inner = safe_join([ summary_inner, tag.div(class: "date") { @slots[:date_inline] } ])
|
|
60
|
+
end
|
|
61
|
+
content_parts << tag.div(class: "summary") { summary_inner }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
if @slots[:extra_text]
|
|
65
|
+
content_parts << tag.div(class: "extra text") { @slots[:extra_text] }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if @slots[:extra_images]
|
|
69
|
+
content_parts << tag.div(class: "extra images") { @slots[:extra_images] }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if @slots[:meta]
|
|
73
|
+
content_parts << tag.div(class: "meta") { @slots[:meta] }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
loose_content = @slots.values.any? ? nil : @content.presence
|
|
77
|
+
content_el = if content_parts.any? || loose_content.present?
|
|
78
|
+
tag.div(class: "content") { safe_join([ *content_parts, loose_content ]) }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
tag.div(**merge_html_options(class: classes)) {
|
|
82
|
+
safe_join([ label_el, content_el ])
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Field — Fomantic UI field wrapper.
|
|
4
|
+
#
|
|
5
|
+
# Renders <div class="... field"> for use inside forms.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
#
|
|
9
|
+
# Field {
|
|
10
|
+
# Input(icon: "user", icon_position: "left") {
|
|
11
|
+
# TextField(:email, placeholder: "E-mail address")
|
|
12
|
+
# }
|
|
13
|
+
# }
|
|
14
|
+
#
|
|
15
|
+
# Field(required: true, label: "Email") {
|
|
16
|
+
# TextField(:email, placeholder: "you@example.com")
|
|
17
|
+
# }
|
|
18
|
+
|
|
19
|
+
class FieldComponent < Component
|
|
20
|
+
attribute :required, :boolean, default: false
|
|
21
|
+
attribute :disabled, :boolean, default: false
|
|
22
|
+
attribute :error, :boolean, default: false
|
|
23
|
+
attribute :warning, :boolean, default: false
|
|
24
|
+
attribute :inline, :boolean, default: false
|
|
25
|
+
attribute :width, :string, default: nil
|
|
26
|
+
attribute :label, :string, default: nil
|
|
27
|
+
|
|
28
|
+
def to_s
|
|
29
|
+
classes = class_names(
|
|
30
|
+
width,
|
|
31
|
+
{ "required" => required, "disabled" => disabled,
|
|
32
|
+
"error" => error, "warning" => warning, "inline" => inline },
|
|
33
|
+
"field"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
label_el = label ? tag.label(label) : nil
|
|
37
|
+
|
|
38
|
+
tag.div(**merge_html_options(class: classes)) {
|
|
39
|
+
safe_join([ label_el, @content ].compact)
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -34,8 +34,9 @@ class FlyoutComponent < Component
|
|
|
34
34
|
content_el = @slots[:content] ? tag.div(class: "content") { @slots[:content] } : nil
|
|
35
35
|
actions_el = @slots[:actions] ? tag.div(class: "actions") { @slots[:actions] } : nil
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
loose_content = @slots.values.any? ? nil : @content.presence
|
|
38
|
+
tag.div(**merge_html_options(class: classes, data: data)) {
|
|
39
|
+
safe_join([ close_el, header_el, content_el, loose_content, actions_el ])
|
|
39
40
|
}
|
|
40
41
|
end
|
|
41
42
|
end
|
|
@@ -45,14 +45,14 @@ class HeaderComponent < Component
|
|
|
45
45
|
|
|
46
46
|
if image && @slots[:header_image]
|
|
47
47
|
# Image header: image outside content div, text + sub header inside content div
|
|
48
|
-
tag.public_send(tag_name, class: classes) {
|
|
48
|
+
tag.public_send(tag_name, **merge_html_options(class: classes)) {
|
|
49
49
|
safe_join([
|
|
50
50
|
@slots[:header_image],
|
|
51
51
|
tag.div(class: "content") { @content }
|
|
52
52
|
])
|
|
53
53
|
}
|
|
54
54
|
else
|
|
55
|
-
tag.public_send(tag_name, class: classes) {
|
|
55
|
+
tag.public_send(tag_name, **merge_html_options(class: classes)) {
|
|
56
56
|
safe_join([ icon_el, @content ])
|
|
57
57
|
}
|
|
58
58
|
end
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Input —
|
|
3
|
+
# Input — Fomantic UI input wrapper.
|
|
4
|
+
#
|
|
5
|
+
# Renders <div class="ui ... input"> with optional icon. The actual <input>
|
|
6
|
+
# element comes from the block (e.g. a form builder TextField) or is
|
|
7
|
+
# auto-generated as a basic <input type="text"> when no block is given.
|
|
4
8
|
#
|
|
5
9
|
# Usage:
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# Input(
|
|
9
|
-
#
|
|
10
|
-
#
|
|
10
|
+
#
|
|
11
|
+
# # Standalone (no form builder) — auto-generates <input>:
|
|
12
|
+
# Input(icon: "search", placeholder: "Search...")
|
|
13
|
+
#
|
|
14
|
+
# # Wrapping a form builder field:
|
|
15
|
+
# Input(icon: "user", icon_position: "left") {
|
|
16
|
+
# TextField(:email, placeholder: "E-mail address")
|
|
17
|
+
# }
|
|
18
|
+
#
|
|
19
|
+
# # Labeled input:
|
|
20
|
+
# Input(labeled: true) { Tag { "http://" } }
|
|
11
21
|
|
|
12
22
|
class InputComponent < Component
|
|
13
23
|
attribute :icon, :string, default: nil
|
|
@@ -22,54 +32,25 @@ class InputComponent < Component
|
|
|
22
32
|
attribute :error, :boolean, default: false
|
|
23
33
|
attribute :inverted, :boolean, default: false
|
|
24
34
|
attribute :placeholder, :string, default: nil
|
|
25
|
-
attribute :input_type, :string, default: "text"
|
|
26
|
-
attribute :name, :string, default: nil
|
|
27
|
-
attribute :value, :string, default: nil
|
|
28
|
-
attribute :label, :string, default: nil
|
|
29
|
-
attribute :id, :string, default: nil
|
|
30
35
|
|
|
31
36
|
def to_s
|
|
32
|
-
input_field = input_element
|
|
33
|
-
|
|
34
|
-
if label
|
|
35
|
-
tag.div(class: "field") {
|
|
36
|
-
safe_join([
|
|
37
|
-
tag.label(label, for: id || name),
|
|
38
|
-
input_field
|
|
39
|
-
])
|
|
40
|
-
}
|
|
41
|
-
else
|
|
42
|
-
input_field
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def input_element
|
|
49
37
|
classes = class_names(
|
|
50
38
|
"ui",
|
|
51
39
|
size,
|
|
52
40
|
{ "left icon" => icon && icon_position == "left",
|
|
53
41
|
"icon" => icon && icon_position != "left",
|
|
54
|
-
"labeled" => labeled, "action" => action,
|
|
55
|
-
"
|
|
42
|
+
"labeled" => labeled, "action" => action,
|
|
43
|
+
"transparent" => transparent, "fluid" => fluid,
|
|
44
|
+
"loading" => loading, "disabled" => disabled,
|
|
56
45
|
"error" => error, "inverted" => inverted },
|
|
57
46
|
"input"
|
|
58
47
|
)
|
|
59
48
|
|
|
60
|
-
input_opts = { type: input_type }
|
|
61
|
-
input_opts[:placeholder] = placeholder if placeholder
|
|
62
|
-
input_opts[:name] = name if name
|
|
63
|
-
input_opts[:value] = value if value
|
|
64
|
-
input_opts[:disabled] = "disabled" if disabled
|
|
65
|
-
input_opts[:id] = id if id
|
|
66
|
-
input_opts[:aria] = @html_options[:aria] if @html_options&.dig(:aria)
|
|
67
|
-
|
|
68
49
|
icon_el = icon ? tag.i(class: "#{icon} icon") : nil
|
|
69
|
-
|
|
50
|
+
content = @content.present? ? @content : tag.input(type: "text", placeholder: placeholder)
|
|
70
51
|
|
|
71
|
-
tag.div(class: classes) {
|
|
72
|
-
safe_join([
|
|
52
|
+
tag.div(**merge_html_options(class: classes)) {
|
|
53
|
+
safe_join([ content, icon_el ].compact)
|
|
73
54
|
}
|
|
74
55
|
end
|
|
75
56
|
end
|
|
@@ -32,8 +32,9 @@ class ItemComponent < Component
|
|
|
32
32
|
|
|
33
33
|
content_el = content_parts.any? ? tag.div(class: "content") { safe_join(content_parts) } : nil
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
loose_content = @slots.values.any? ? nil : @content.presence
|
|
36
|
+
tag.div(**merge_html_options(class: "item")) {
|
|
37
|
+
safe_join([ image_el, content_el, loose_content ])
|
|
37
38
|
}
|
|
38
39
|
end
|
|
39
40
|
end
|
|
@@ -31,9 +31,9 @@ class ListComponent < Component
|
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
if ordered
|
|
34
|
-
tag.ol(class: classes) { @content }
|
|
34
|
+
tag.ol(**merge_html_options(class: classes)) { @content }
|
|
35
35
|
else
|
|
36
|
-
tag.div(class: classes) { @content }
|
|
36
|
+
tag.div(**merge_html_options(class: classes)) { @content }
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ListContent — content wrapper within a ListItem.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ListItem {
|
|
7
|
+
# Image(src: "avatar.png", class: "avatar")
|
|
8
|
+
# ListContent {
|
|
9
|
+
# ListHeader { text "Rachel" }
|
|
10
|
+
# ListDescription { text "Last seen just now." }
|
|
11
|
+
# }
|
|
12
|
+
# }
|
|
13
|
+
|
|
14
|
+
class ListContentComponent < Component
|
|
15
|
+
attribute :aligned, :string, default: nil
|
|
16
|
+
attribute :floated, :string, default: nil
|
|
17
|
+
|
|
18
|
+
def to_s
|
|
19
|
+
classes = class_names(
|
|
20
|
+
floated && "#{floated} floated",
|
|
21
|
+
aligned && "#{aligned} aligned",
|
|
22
|
+
"content"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
tag.div(**merge_html_options(class: classes)) { @content }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ListDescription — description text within a ListItem or ListContent.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ListItem {
|
|
7
|
+
# ListContent {
|
|
8
|
+
# ListHeader { text "Krolewskie Jadlo" }
|
|
9
|
+
# ListDescription { text "An excellent polish restaurant." }
|
|
10
|
+
# }
|
|
11
|
+
# }
|
|
12
|
+
|
|
13
|
+
class ListDescriptionComponent < Component
|
|
14
|
+
def to_s
|
|
15
|
+
tag.div(**merge_html_options(class: "description")) { @content }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ListHeader — header text within a ListItem or ListContent.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ListItem {
|
|
7
|
+
# ListHeader { text "New York City" }
|
|
8
|
+
# text "A lovely city"
|
|
9
|
+
# }
|
|
10
|
+
#
|
|
11
|
+
# ListItem {
|
|
12
|
+
# ListContent {
|
|
13
|
+
# ListHeader(href: "#") { text "Rachel" }
|
|
14
|
+
# ListDescription { text "Last seen just now." }
|
|
15
|
+
# }
|
|
16
|
+
# }
|
|
17
|
+
|
|
18
|
+
class ListHeaderComponent < Component
|
|
19
|
+
attribute :href, :string, default: nil
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
if href
|
|
23
|
+
tag.a(**merge_html_options(class: "header", href: href)) { @content }
|
|
24
|
+
else
|
|
25
|
+
tag.div(**merge_html_options(class: "header")) { @content }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ListItem — individual item within a List.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# List {
|
|
7
|
+
# ListItem { text "Apples" }
|
|
8
|
+
# ListItem(icon: "users") { ListContent { text "Fomantic UI" } }
|
|
9
|
+
# ListItem(href: "#") { text "Link item" }
|
|
10
|
+
# }
|
|
11
|
+
|
|
12
|
+
class ListItemComponent < Component
|
|
13
|
+
attribute :href, :string, default: nil
|
|
14
|
+
attribute :active, :boolean, default: false
|
|
15
|
+
attribute :disabled, :boolean, default: false
|
|
16
|
+
attribute :icon, :string, default: nil
|
|
17
|
+
attribute :value, :string, default: nil
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
classes = class_names(
|
|
21
|
+
{ "active" => active, "disabled" => disabled },
|
|
22
|
+
"item"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
icon_el = icon ? tag.i(class: "#{icon} icon") : nil
|
|
26
|
+
opts = { class: classes }
|
|
27
|
+
opts[:"data-value"] = value if value
|
|
28
|
+
|
|
29
|
+
inner = safe_join([ icon_el, @content ])
|
|
30
|
+
|
|
31
|
+
if href
|
|
32
|
+
tag.a(inner, **merge_html_options(**opts, href: href))
|
|
33
|
+
else
|
|
34
|
+
tag.div(inner, **merge_html_options(**opts))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -74,8 +74,9 @@ class ModalComponent < Component
|
|
|
74
74
|
opts = merge_html_options(class: classes, data: data)
|
|
75
75
|
opts[:id] = id if id
|
|
76
76
|
|
|
77
|
+
loose_content = @slots.values.any? ? nil : @content.presence
|
|
77
78
|
tag.div(**opts) {
|
|
78
|
-
safe_join([ close_el, header_el, content_el,
|
|
79
|
+
safe_join([ close_el, header_el, content_el, loose_content, actions_el ])
|
|
79
80
|
}
|
|
80
81
|
end
|
|
81
82
|
end
|
|
@@ -18,7 +18,7 @@ class NagComponent < Component
|
|
|
18
18
|
|
|
19
19
|
close_el = tag.i(class: "close icon")
|
|
20
20
|
|
|
21
|
-
tag.div(class: classes, data: { controller: "fui-nag" }) {
|
|
21
|
+
tag.div(**merge_html_options(class: classes, data: { controller: "fui-nag" })) {
|
|
22
22
|
safe_join([ close_el, @content ])
|
|
23
23
|
}
|
|
24
24
|
end
|