anchor_view_components 0.20.1 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/app/assets/builds/anchor-view-components.css +1 -1
- data/app/assets/images/icons/calendar.svg +7 -0
- data/app/assets/images/icons/check.svg +4 -0
- data/app/assets/images/icons/paste-clipboard.svg +5 -0
- data/app/assets/images/icons/search.svg +5 -0
- data/app/assets/stylesheets/components/button.css +1 -1
- data/app/components/anchor/action_menu_component.html.erb +8 -10
- data/app/components/anchor/action_menu_component.rb +15 -6
- data/app/components/anchor/anchor_view_components.ts +2 -0
- data/app/components/anchor/autocomplete_component.html.erb +6 -7
- data/app/components/anchor/autocomplete_component.rb +29 -8
- data/app/components/anchor/badge_component.html.erb +3 -6
- data/app/components/anchor/badge_component.rb +0 -10
- data/app/components/anchor/banner_component.html.erb +1 -7
- data/app/components/anchor/banner_component.rb +0 -10
- data/app/components/anchor/button_component.html.erb +10 -17
- data/app/components/anchor/button_component.rb +14 -21
- data/app/components/anchor/component.rb +22 -5
- data/app/components/anchor/copy_to_clipboard_component.en.yml +2 -0
- data/app/components/anchor/copy_to_clipboard_component.html.erb +21 -0
- data/app/components/anchor/copy_to_clipboard_component.rb +15 -0
- data/app/components/anchor/copy_to_clipboard_controller.ts +34 -0
- data/app/components/anchor/dialog_component.html.erb +3 -4
- data/app/components/anchor/icon_component.html.erb +1 -3
- data/app/components/anchor/icon_component.rb +1 -1
- data/app/components/anchor/loading_indicator_component.html.erb +3 -4
- data/app/components/anchor/logo_component.html.erb +1 -4
- data/app/components/anchor/logo_component.rb +1 -1
- data/app/components/anchor/panel/body_component.html.erb +3 -5
- data/app/components/anchor/panel_component.html.erb +3 -1
- data/app/components/anchor/popover_component.html.erb +3 -7
- data/app/components/anchor/popover_controller.ts +21 -15
- data/app/components/anchor/prose_component.html.erb +5 -4
- data/app/components/anchor/radio_button_collection_component.html.erb +1 -0
- data/app/components/anchor/radio_button_collection_component.rb +35 -0
- data/app/components/anchor/radio_button_component.html.erb +11 -0
- data/app/components/anchor/radio_button_component.rb +105 -0
- data/app/components/anchor/side_nav_component.html.erb +8 -9
- data/app/components/anchor/side_nav_component.rb +4 -1
- data/app/components/anchor/tab_bar/tab_component.html.erb +8 -6
- data/app/components/anchor/tab_bar/tab_component.rb +2 -2
- data/app/components/anchor/tab_bar_component.html.erb +3 -4
- data/app/components/anchor/tab_bar_component.rb +3 -2
- data/app/components/anchor/table_component.rb +1 -1
- data/app/components/anchor/text_component.html.erb +1 -6
- data/app/components/anchor/text_component.rb +5 -14
- data/app/components/anchor/text_field_component.html.erb +19 -1
- data/app/components/anchor/text_field_component.rb +35 -16
- data/app/components/anchor/toast_component.html.erb +5 -8
- data/app/components/anchor/toast_component.rb +8 -12
- data/app/components/anchor/toast_controller.ts +5 -1
- data/app/helpers/anchor/fetch_or_fallback_helper.rb +26 -0
- data/app/helpers/anchor/form_builder.rb +52 -29
- data/app/helpers/anchor/tailwind_constants.rb +0 -37
- data/app/helpers/anchor/view_helper.rb +11 -0
- data/lib/anchor/view_components/engine.rb +0 -1
- data/lib/anchor/view_components/version.rb +1 -1
- data/previews/anchor/copy_to_clipboard_component_preview.rb +7 -0
- data/previews/anchor/forms_preview.rb +45 -0
- data/previews/forms/default.html.erb +6 -4
- data/previews/forms/radio_button_collection.html.erb +51 -0
- data/previews/forms/with_icons.html.erb +10 -0
- metadata +17 -2
@@ -0,0 +1,34 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller<HTMLDivElement> {
|
4
|
+
static targets = [ "initialIcon", "successIcon"];
|
5
|
+
static classes = [ "hidden" ]
|
6
|
+
|
7
|
+
declare readonly initialIconTarget: SVGElement;
|
8
|
+
declare readonly successIconTarget: SVGElement;
|
9
|
+
declare readonly notificationDelayValue: number;
|
10
|
+
declare readonly hiddenClass: string;
|
11
|
+
declare readonly textToCopyValue: string;
|
12
|
+
declare readonly hasTextToCopyValue: boolean;
|
13
|
+
|
14
|
+
static values = {
|
15
|
+
notificationDelay: { type: Number, default: 1500 },
|
16
|
+
textToCopy: String,
|
17
|
+
};
|
18
|
+
|
19
|
+
copy(): void {
|
20
|
+
if (this.hasTextToCopyValue) {
|
21
|
+
navigator.clipboard.writeText(this.textToCopyValue);
|
22
|
+
}
|
23
|
+
this.toggleIcons();
|
24
|
+
|
25
|
+
setTimeout(() => {
|
26
|
+
this.toggleIcons();
|
27
|
+
}, this.notificationDelayValue);
|
28
|
+
}
|
29
|
+
|
30
|
+
toggleIcons(): void {
|
31
|
+
this.initialIconTarget.classList.toggle(this.hiddenClass);
|
32
|
+
this.successIconTarget.classList.toggle(this.hiddenClass);
|
33
|
+
}
|
34
|
+
}
|
@@ -1,14 +1,13 @@
|
|
1
1
|
<%= show_button if show_button? %>
|
2
2
|
|
3
|
-
<%= tag.dialog(
|
3
|
+
<%= tag.dialog(**merge_options(wrapper_options, {
|
4
4
|
aria: { labelledby: title_id },
|
5
|
-
class:
|
5
|
+
class: "w-[36rem] rounded-lg p-0 bg-white shadow-lg backdrop:bg-grey-100/50",
|
6
6
|
data: {
|
7
7
|
controller: "dialog",
|
8
8
|
testid: title_id,
|
9
9
|
},
|
10
|
-
|
11
|
-
) do %>
|
10
|
+
})) do %>
|
12
11
|
<header class="p-6 flex gap-4 justify-between items-center">
|
13
12
|
<%= render Anchor::TextComponent.new(
|
14
13
|
variant: :heading_2xl,
|
@@ -1,7 +1,6 @@
|
|
1
1
|
<%= tag.span t(".label"), class: "sr-only" %>
|
2
2
|
|
3
|
-
<%= anchor_icon(
|
3
|
+
<%= anchor_icon(**merge_options(wrapper_options,
|
4
|
+
class: class_names(wrapper_options[:class], "text-grey-100 animate-spin"),
|
4
5
|
icon: "loading-indicator",
|
5
|
-
|
6
|
-
data: data,
|
7
|
-
) %>
|
6
|
+
)) %>
|
@@ -4,15 +4,11 @@
|
|
4
4
|
) do %>
|
5
5
|
<%= trigger if trigger? %>
|
6
6
|
|
7
|
-
<%= tag.div(
|
8
|
-
class:
|
9
|
-
"absolute -left-full -top-full m-0 bg-white rounded border border-subdued popover-open:block",
|
10
|
-
classes
|
11
|
-
),
|
7
|
+
<%= tag.div(**merge_options(wrapper_options,
|
8
|
+
class: "absolute -left-full -top-full m-0 bg-white rounded border border-subdued popover-open:block",
|
12
9
|
data: { action: "toggle->popover#positionPopover" },
|
13
|
-
id:,
|
14
10
|
popover: "auto",
|
15
|
-
) do %>
|
11
|
+
)) do %>
|
16
12
|
<%= content %>
|
17
13
|
<% end %>
|
18
14
|
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Controller } from "@hotwired/stimulus";
|
2
|
-
import { computePosition, autoPlacement, offset } from "@floating-ui/dom";
|
2
|
+
import { computePosition, autoPlacement, offset, autoUpdate } from "@floating-ui/dom";
|
3
3
|
|
4
4
|
export default class extends Controller<HTMLDivElement> {
|
5
5
|
static targets = ["button"];
|
@@ -7,20 +7,26 @@ export default class extends Controller<HTMLDivElement> {
|
|
7
7
|
declare readonly buttonTarget: HTMLButtonElement;
|
8
8
|
|
9
9
|
positionPopover = (event: { target: HTMLDivElement }): void => {
|
10
|
+
const trigger = this.buttonTarget
|
10
11
|
const popover = event.target;
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
|
13
|
+
const updatePosition = () => {
|
14
|
+
computePosition(trigger, popover, {
|
15
|
+
placement: "bottom-start",
|
16
|
+
middleware: [
|
17
|
+
autoPlacement({
|
18
|
+
allowedPlacements: ["bottom-start", "bottom-end", "top-start", "top-end"],
|
19
|
+
}),
|
20
|
+
offset(4)
|
21
|
+
],
|
22
|
+
}).then(({ x, y }) => {
|
23
|
+
Object.assign(popover.style, {
|
24
|
+
left: `${x}px`,
|
25
|
+
top: `${y}px`,
|
26
|
+
});
|
27
|
+
})
|
28
|
+
};
|
29
|
+
|
30
|
+
autoUpdate(trigger, popover, updatePosition);
|
25
31
|
};
|
26
32
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= tag.div content, class: "flex flex-col space-y-2 text-base" %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Anchor
|
2
|
+
class RadioButtonCollectionComponent < Component
|
3
|
+
attr_reader :attribute, :descriptions, :form_builder
|
4
|
+
|
5
|
+
def initialize(
|
6
|
+
form_builder:,
|
7
|
+
attribute:,
|
8
|
+
collection:,
|
9
|
+
value_method:,
|
10
|
+
text_method:,
|
11
|
+
**options
|
12
|
+
)
|
13
|
+
@form_builder = form_builder
|
14
|
+
@attribute = attribute
|
15
|
+
@collection = collection
|
16
|
+
@value_method = value_method
|
17
|
+
@text_method = text_method
|
18
|
+
@descriptions = options.delete(:descriptions)
|
19
|
+
|
20
|
+
super
|
21
|
+
|
22
|
+
def options
|
23
|
+
{ class: RadioButtonComponent::INPUT_CLASSES }
|
24
|
+
end
|
25
|
+
|
26
|
+
def radio(radio:)
|
27
|
+
RadioButtonComponent.new(
|
28
|
+
radio:,
|
29
|
+
attribute:,
|
30
|
+
form_builder:
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div class="flex gap-1 items-start">
|
2
|
+
<%= radio.radio_button(radio_options) %>
|
3
|
+
<% if description.present? %>
|
4
|
+
<div class="flex flex-col gap-1">
|
5
|
+
<%= radio.label %>
|
6
|
+
<%= description_span %>
|
7
|
+
</div>
|
8
|
+
<% else %>
|
9
|
+
<%= tag.div radio.label, class: "self-center" %>
|
10
|
+
<% end %>
|
11
|
+
</div>
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Anchor
|
2
|
+
class RadioButtonComponent < Anchor::Component
|
3
|
+
INPUT_CLASSES = %w(
|
4
|
+
appearance-none
|
5
|
+
w-[18px]
|
6
|
+
m-[3px]
|
7
|
+
aspect-square
|
8
|
+
rounded-full
|
9
|
+
border-2
|
10
|
+
border-grey-60
|
11
|
+
hover:border-grey-80
|
12
|
+
checked:bg-gradient-radial
|
13
|
+
checked:from-blue-50
|
14
|
+
checked:from-[50%]
|
15
|
+
checked:to-transparent
|
16
|
+
checked:to-[54%]
|
17
|
+
checked:border-blue-50
|
18
|
+
checked:hover:from-blue-60
|
19
|
+
checked:hover:from-[50%]
|
20
|
+
checked:hover:to-transparent
|
21
|
+
checked:hover:to-[54%]
|
22
|
+
checked:hover:border-blue-60
|
23
|
+
disabled:border-grey-40
|
24
|
+
disabled:checked:border-grey-40
|
25
|
+
disabled:checked:from-grey-40
|
26
|
+
disabled:checked:from-[50%]
|
27
|
+
disabled:checked:to-transparent
|
28
|
+
disabled:checked:to-[54%]
|
29
|
+
disabled:checked:border-grey-40
|
30
|
+
aria-readonly:border-grey-40
|
31
|
+
aria-readonly:checked:border-grey-40
|
32
|
+
aria-readonly:checked:from-grey-40
|
33
|
+
aria-readonly:checked:from-[50%]
|
34
|
+
aria-readonly:checked:to-transparent
|
35
|
+
aria-readonly:checked:to-[54%]
|
36
|
+
aria-readonly:checked:border-grey-40
|
37
|
+
).freeze
|
38
|
+
|
39
|
+
DESCRIPTION_CLASSES = %w(
|
40
|
+
text-secondary
|
41
|
+
text-sm
|
42
|
+
).freeze
|
43
|
+
|
44
|
+
def initialize(radio:, attribute:, form_builder:)
|
45
|
+
@radio = radio
|
46
|
+
@attribute = attribute
|
47
|
+
@form_builder = form_builder
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
attr_reader :radio, :attribute, :form_builder
|
55
|
+
|
56
|
+
delegate :value, to: :radio
|
57
|
+
|
58
|
+
def aria_description
|
59
|
+
{ describedby: description_id }
|
60
|
+
end
|
61
|
+
|
62
|
+
def description
|
63
|
+
if radio.object.is_a?(Hash)
|
64
|
+
radio.object[:description]
|
65
|
+
elsif radio.object.respond_to?(:description)
|
66
|
+
radio.object.description
|
67
|
+
elsif I18n.exists?(description_translation_scope)
|
68
|
+
human_attribute_description
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def description_id
|
75
|
+
"#{attribute}-#{value}-description"
|
76
|
+
end
|
77
|
+
|
78
|
+
def description_span
|
79
|
+
tag.span description, id: description_id, class: DESCRIPTION_CLASSES
|
80
|
+
end
|
81
|
+
|
82
|
+
def description_text
|
83
|
+
human_attribute_description
|
84
|
+
end
|
85
|
+
|
86
|
+
def description_translation_scope
|
87
|
+
["activerecord.values", i18n_model_key, description_id.gsub("-", ".")]
|
88
|
+
end
|
89
|
+
|
90
|
+
def human_attribute_description
|
91
|
+
I18n.t description_translation_scope.join(".")
|
92
|
+
end
|
93
|
+
|
94
|
+
def i18n_model_key
|
95
|
+
form_builder.object.class.model_name.i18n_key
|
96
|
+
end
|
97
|
+
|
98
|
+
def radio_options
|
99
|
+
{
|
100
|
+
aria: description.present? && aria_description,
|
101
|
+
data: { testid: "radio-#{attribute}-#{radio.value}".dasherize },
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,20 +1,19 @@
|
|
1
|
-
<%= tag.div(
|
2
|
-
|
1
|
+
<%= tag.div(**merge_options(wrapper_options, {
|
2
|
+
class: "flex min-h-[100dvh] max-h-[100dvh] overflow-hidden",
|
3
3
|
data: {
|
4
4
|
controller: "toggle",
|
5
5
|
toggle_toggle_class: "side-nav-open",
|
6
6
|
toggle_initial_label_value: t(".hide_nav"),
|
7
7
|
toggle_intermediate_label_value: t(".show_nav"),
|
8
|
-
}
|
9
|
-
) do %>
|
10
|
-
<%= tag.header(
|
8
|
+
}
|
9
|
+
})) do %>
|
10
|
+
<%= tag.header(**merge_options(sidebar_options, {
|
11
11
|
class: class_names(
|
12
12
|
"flex flex-shrink-0 w-[15rem] relative",
|
13
13
|
"[.side-nav-open_&]:w-[3.5rem] transition-[width] duration-500",
|
14
|
-
classes
|
15
14
|
),
|
16
|
-
data: { testid: "side-nav" }
|
17
|
-
) do %>
|
15
|
+
data: { testid: "side-nav" },
|
16
|
+
})) do %>
|
18
17
|
<%= tag.div(
|
19
18
|
class: class_names(
|
20
19
|
"bg-teal text-white w-[15rem] flex flex-col divide-y divide-solid divide-white/10 duration-500",
|
@@ -58,7 +57,7 @@
|
|
58
57
|
),
|
59
58
|
data: { toggle_target: "inertify" },
|
60
59
|
) do %>
|
61
|
-
|
60
|
+
<%= render Anchor::ActionMenuComponent.new(classes: "py-4", menu_options: { class: "ml-4 w-[198px]" }) do |c| %>
|
62
61
|
<% c.with_show_button(
|
63
62
|
classes: "text-lg text-white w-full hover:text-white hover:bg-white/[.05] px-6 justify-between rounded-none",
|
64
63
|
full_width: true,
|
@@ -8,18 +8,21 @@ module Anchor
|
|
8
8
|
apps_button_text:,
|
9
9
|
nav_items:,
|
10
10
|
employee:,
|
11
|
+
sidebar_options: {},
|
11
12
|
**kwargs
|
12
13
|
)
|
13
14
|
@apps = apps
|
14
15
|
@apps_button_text = apps_button_text
|
15
16
|
@nav_items = nav_items
|
16
17
|
@employee = employee
|
18
|
+
@sidebar_options = sidebar_options
|
17
19
|
|
18
20
|
super
|
19
21
|
end
|
20
22
|
|
21
23
|
private
|
22
24
|
|
23
|
-
attr_reader :apps, :apps_button_text, :employee, :nav_items
|
25
|
+
attr_reader :apps, :apps_button_text, :employee, :nav_items,
|
26
|
+
:sidebar_options
|
24
27
|
end
|
25
28
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
<%= link_to(
|
2
2
|
content,
|
3
3
|
href,
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
**merge_options(wrapper_options,
|
5
|
+
aria: {
|
6
|
+
current: { page: active }
|
7
|
+
},
|
8
|
+
class: class_names(
|
9
|
+
"inline-block px-5 py-4 text-sm font-semibold relative text-gray-600 hover:text-gray-900",
|
10
|
+
"text-gray-900 after:block after:bg-blue-500 after:h-1 after:absolute after:-bottom-1 after:inset-x-0" => active,
|
11
|
+
)
|
10
12
|
)
|
11
13
|
) %>
|
@@ -1,7 +1,6 @@
|
|
1
|
-
<%= tag.nav(
|
2
|
-
|
3
|
-
|
4
|
-
) do %>
|
1
|
+
<%= tag.nav(**merge_options(wrapper_options,
|
2
|
+
class: "shadow-[inset_0_-1px] shadow-gray-400 pb-1",
|
3
|
+
)) do %>
|
5
4
|
<ul class="flex">
|
6
5
|
<% tabs.each do |tab| %>
|
7
6
|
<%= tag.li tab %>
|
@@ -3,7 +3,7 @@ module Anchor
|
|
3
3
|
TAG_DEFAULT = :p
|
4
4
|
|
5
5
|
VARIANT_DEFAULT = :body_base
|
6
|
-
|
6
|
+
VARIANT_MAPPINGS = {
|
7
7
|
body_lg: "text-lg",
|
8
8
|
body_base: "text-base",
|
9
9
|
body_sm: "text-sm",
|
@@ -16,25 +16,16 @@ module Anchor
|
|
16
16
|
subheading_sm: "text-sm font-bold leading-4 uppercase",
|
17
17
|
subheading_xs: "text-xs font-bold leading-4 uppercase",
|
18
18
|
}.freeze
|
19
|
-
VARIANT_OPTIONS =
|
19
|
+
VARIANT_OPTIONS = VARIANT_MAPPINGS.keys
|
20
20
|
|
21
|
-
def initialize(
|
22
|
-
variant: VARIANT_DEFAULT,
|
23
|
-
tag: TAG_DEFAULT,
|
24
|
-
**kwargs
|
25
|
-
)
|
26
|
-
@variant = VARIANT_MAPPING[
|
27
|
-
fetch_or_fallback(VARIANT_OPTIONS, variant, VARIANT_DEFAULT)
|
28
|
-
]
|
21
|
+
def initialize(tag: TAG_DEFAULT, **kwargs)
|
29
22
|
@tag = tag
|
30
|
-
|
31
|
-
|
32
|
-
super
|
23
|
+
super(**kwargs)
|
33
24
|
end
|
34
25
|
|
35
26
|
private
|
36
27
|
|
37
|
-
attr_reader :
|
28
|
+
attr_reader :tag
|
38
29
|
|
39
30
|
def render?
|
40
31
|
content.present?
|
@@ -1 +1,19 @@
|
|
1
|
-
|
1
|
+
<% if starting_icon? || ending_icon? %>
|
2
|
+
<%= tag.div class: "relative" do %>
|
3
|
+
<%= content %>
|
4
|
+
<% if starting_icon? %>
|
5
|
+
<%= anchor_icon(
|
6
|
+
icon: starting_icon,
|
7
|
+
classes: class_names(ICON_CLASSES, "left-4")
|
8
|
+
) %>
|
9
|
+
<% end %>
|
10
|
+
<% if ending_icon? %>
|
11
|
+
<%= anchor_icon(
|
12
|
+
icon: ending_icon,
|
13
|
+
classes: class_names(ICON_CLASSES, "right-4")
|
14
|
+
) %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
<% else %>
|
18
|
+
<%= content %>
|
19
|
+
<% end %>
|
@@ -1,30 +1,49 @@
|
|
1
1
|
module Anchor
|
2
2
|
class TextFieldComponent < Component
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
text-base
|
12
|
-
w-full
|
13
|
-
[&[readonly]]:bg-grey-10
|
14
|
-
[&[readonly]]:border-grey-40
|
15
|
-
[&[readonly]]:shadow-none
|
3
|
+
ICON_CLASSES = %w(
|
4
|
+
absolute
|
5
|
+
h-5
|
6
|
+
w-5
|
7
|
+
top-1/2
|
8
|
+
-translate-y-1/2
|
9
|
+
text-secondary
|
10
|
+
pointer-events-none
|
16
11
|
).freeze
|
17
12
|
|
18
|
-
def initialize(
|
13
|
+
def initialize(
|
14
|
+
form_builder:,
|
15
|
+
attribute:,
|
16
|
+
starting_icon: nil,
|
17
|
+
ending_icon: nil
|
18
|
+
)
|
19
19
|
@form_builder = form_builder
|
20
20
|
@attribute = attribute
|
21
|
-
@
|
21
|
+
@starting_icon = starting_icon
|
22
|
+
@ending_icon = ending_icon
|
22
23
|
|
23
24
|
super
|
24
25
|
end
|
25
26
|
|
27
|
+
attr_reader :starting_icon, :ending_icon
|
28
|
+
|
26
29
|
def options
|
27
|
-
{
|
30
|
+
{
|
31
|
+
class: class_names(
|
32
|
+
TailwindConstants::INPUT,
|
33
|
+
"pl-11" => starting_icon?,
|
34
|
+
"pr-11" => ending_icon?
|
35
|
+
),
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def starting_icon?
|
42
|
+
starting_icon.present?
|
43
|
+
end
|
44
|
+
|
45
|
+
def ending_icon?
|
46
|
+
ending_icon.present?
|
28
47
|
end
|
29
48
|
end
|
30
49
|
end
|
@@ -1,12 +1,9 @@
|
|
1
1
|
<%= tag.div(
|
2
|
-
|
3
|
-
"toast",
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
id: id,
|
8
|
-
popover: "manual",
|
9
|
-
role:,
|
2
|
+
**merge_options(wrapper_options, {
|
3
|
+
class: "toast",
|
4
|
+
data: { controller: "toast", testid: test_id },
|
5
|
+
popover: "manual",
|
6
|
+
})
|
10
7
|
) do %>
|
11
8
|
<% if icon? %>
|
12
9
|
<%= icon %>
|