fernandes-ui 0.1.2 → 0.1.4
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/assets/javascripts/ui.esm.js +3 -6
- data/app/assets/javascripts/ui.js +3 -6
- data/app/behaviors/ui/command_dialog_behavior.rb +0 -8
- data/app/behaviors/ui/empty_behavior.rb +6 -6
- data/app/behaviors/ui/input_behavior.rb +1 -1
- data/app/behaviors/ui/input_group_behavior.rb +3 -1
- data/app/behaviors/ui/input_group_button_behavior.rb +7 -6
- data/app/behaviors/ui/menubar_checkbox_item_behavior.rb +1 -1
- data/app/behaviors/ui/menubar_radio_item_behavior.rb +1 -1
- data/app/behaviors/ui/popover_behavior.rb +11 -3
- data/app/behaviors/ui/spinner_behavior.rb +1 -1
- data/app/behaviors/ui/switch_behavior.rb +49 -49
- data/app/behaviors/ui/toggle_group_behavior.rb +2 -2
- data/app/behaviors/ui/toggle_group_item_behavior.rb +7 -3
- data/app/behaviors/ui/tooltip_behavior.rb +12 -2
- data/app/components/ui/base.rb +8 -0
- data/app/components/ui/calendar.rb +51 -0
- data/app/components/ui/carousel_next.rb +2 -2
- data/app/components/ui/carousel_previous.rb +2 -2
- data/app/components/ui/date_picker.rb +1 -1
- data/app/components/ui/date_picker_trigger.rb +1 -1
- data/app/components/ui/dropdown_menu_trigger.rb +3 -2
- data/app/components/ui/input_group_button.rb +9 -2
- data/app/components/ui/navigation_menu_content.rb +1 -1
- data/app/components/ui/navigation_menu_item.rb +1 -1
- data/app/components/ui/navigation_menu_link.rb +1 -1
- data/app/components/ui/navigation_menu_list.rb +1 -1
- data/app/components/ui/navigation_menu_trigger.rb +1 -1
- data/app/components/ui/popover.rb +26 -1
- data/app/components/ui/select.rb +14 -2
- data/app/components/ui/sonner_toaster.rb +1 -1
- data/app/components/ui/table.rb +7 -7
- data/app/components/ui/table_body.rb +3 -3
- data/app/components/ui/table_footer.rb +3 -3
- data/app/components/ui/table_header.rb +3 -3
- data/app/components/ui/table_row.rb +2 -2
- data/app/components/ui/toggle_group.rb +8 -2
- data/app/components/ui/toggle_group_item.rb +4 -3
- data/app/components/ui/tooltip.rb +26 -2
- data/app/helpers/ui/popover_behavior.rb +5 -2
- data/app/javascript/ui/controllers/collapsible_controller.js +2 -0
- data/app/javascript/ui/controllers/dropdown_controller.js +8 -14
- data/app/view_components/ui/calendar_component.rb +62 -0
- data/app/view_components/ui/dropdown_menu_trigger_component.rb +14 -30
- data/app/view_components/ui/input_group_button_component.rb +16 -1
- data/app/view_components/ui/navigation_menu_content_component.rb +1 -1
- data/app/view_components/ui/navigation_menu_item_component.rb +1 -1
- data/app/view_components/ui/navigation_menu_link_component.rb +1 -1
- data/app/view_components/ui/navigation_menu_list_component.rb +1 -1
- data/app/view_components/ui/navigation_menu_trigger_component.rb +1 -1
- data/app/view_components/ui/popover_component.rb +25 -4
- data/app/view_components/ui/popover_trigger_component.rb +5 -0
- data/app/view_components/ui/select_component.rb +13 -2
- data/app/view_components/ui/table_body_component.rb +1 -1
- data/app/view_components/ui/table_component.rb +4 -4
- data/app/view_components/ui/table_footer_component.rb +1 -1
- data/app/view_components/ui/table_header_component.rb +1 -1
- data/app/view_components/ui/table_row_component.rb +2 -2
- data/app/view_components/ui/tooltip_component.rb +33 -2
- data/app/view_components/ui/tooltip_trigger_component.rb +24 -4
- data/app/views/ui/_avatar.html.erb +8 -4
- data/app/views/ui/_button.html.erb +16 -0
- data/app/views/ui/_date_picker.html.erb +4 -4
- data/app/views/ui/_popover.html.erb +30 -4
- data/app/views/ui/_select.html.erb +13 -2
- data/app/views/ui/_skeleton.html.erb +1 -1
- data/app/views/ui/_tooltip.html.erb +28 -2
- data/app/views/ui/dropdown_menu/_trigger.html.erb +3 -1
- data/app/views/ui/input_group/_button.html.erb +14 -3
- data/app/views/ui/popover/_trigger.html.erb +22 -2
- data/app/views/ui/tooltip/_trigger.html.erb +16 -21
- data/lib/ui/version.rb +1 -1
- metadata +2 -1
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
# Container for popover trigger and content.
|
|
6
6
|
# Uses PopoverBehavior concern for shared styling logic.
|
|
7
7
|
#
|
|
8
|
+
# Supports asChild pattern for composition without wrapper elements.
|
|
9
|
+
#
|
|
8
10
|
# @example Basic usage
|
|
9
11
|
# <%= render UI::PopoverComponent.new do %>
|
|
10
12
|
# <%= render UI::TriggerComponent.new do %>
|
|
@@ -15,13 +17,19 @@
|
|
|
15
17
|
# <% end %>
|
|
16
18
|
# <% end %>
|
|
17
19
|
#
|
|
18
|
-
# @example With custom
|
|
19
|
-
# <%= render UI::PopoverComponent.new(
|
|
20
|
-
#
|
|
20
|
+
# @example With asChild - pass attributes to custom element
|
|
21
|
+
# <%= render UI::PopoverComponent.new(as_child: true) do |popover| %>
|
|
22
|
+
# <%= render UI::InputGroupAddonComponent.new(**popover.popover_attrs) do %>
|
|
23
|
+
# <%= render UI::PopoverTriggerComponent.new(as_child: true) do |trigger| %>
|
|
24
|
+
# <%= render UI::InputGroupButtonComponent.new(**trigger.trigger_attrs) { "Info" } %>
|
|
25
|
+
# <% end %>
|
|
26
|
+
# <%= render UI::PopoverContentComponent.new { "Content" } %>
|
|
27
|
+
# <% end %>
|
|
21
28
|
# <% end %>
|
|
22
29
|
class UI::PopoverComponent < ViewComponent::Base
|
|
23
30
|
include UI::PopoverBehavior
|
|
24
31
|
|
|
32
|
+
# @param as_child [Boolean] When true, yields self to block for attribute access
|
|
25
33
|
# @param placement [String] Placement of the popover (e.g., "bottom", "top-start")
|
|
26
34
|
# @param offset [Integer] Distance in pixels from the trigger
|
|
27
35
|
# @param trigger [String] Trigger type ("click" or "hover")
|
|
@@ -29,6 +37,7 @@ class UI::PopoverComponent < ViewComponent::Base
|
|
|
29
37
|
# @param classes [String] Additional CSS classes to merge
|
|
30
38
|
# @param attributes [Hash] Additional HTML attributes
|
|
31
39
|
def initialize(
|
|
40
|
+
as_child: false,
|
|
32
41
|
placement: "bottom",
|
|
33
42
|
offset: 4,
|
|
34
43
|
trigger: "click",
|
|
@@ -38,6 +47,7 @@ class UI::PopoverComponent < ViewComponent::Base
|
|
|
38
47
|
side_offset: nil,
|
|
39
48
|
**attributes
|
|
40
49
|
)
|
|
50
|
+
@as_child = as_child
|
|
41
51
|
@placement = placement
|
|
42
52
|
@offset = side_offset || offset
|
|
43
53
|
@trigger = trigger
|
|
@@ -47,9 +57,20 @@ class UI::PopoverComponent < ViewComponent::Base
|
|
|
47
57
|
@attributes = attributes
|
|
48
58
|
end
|
|
49
59
|
|
|
60
|
+
# Returns popover attributes for as_child mode
|
|
61
|
+
def popover_attrs
|
|
62
|
+
popover_html_attributes.deep_merge(@attributes)
|
|
63
|
+
end
|
|
64
|
+
|
|
50
65
|
def call
|
|
51
|
-
|
|
66
|
+
if @as_child
|
|
67
|
+
# asChild mode: yield self to block, child accesses popover_attrs
|
|
52
68
|
content
|
|
69
|
+
else
|
|
70
|
+
# Default: render wrapper div with controller
|
|
71
|
+
content_tag :div, **popover_html_attributes do
|
|
72
|
+
content
|
|
73
|
+
end
|
|
53
74
|
end
|
|
54
75
|
end
|
|
55
76
|
end
|
|
@@ -26,6 +26,11 @@ class UI::PopoverTriggerComponent < ViewComponent::Base
|
|
|
26
26
|
@attributes = attributes
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
# Returns trigger attributes for as_child mode
|
|
30
|
+
def trigger_attrs
|
|
31
|
+
popover_trigger_html_attributes.deep_merge(@attributes)
|
|
32
|
+
end
|
|
33
|
+
|
|
29
34
|
def call
|
|
30
35
|
trigger_attrs = popover_trigger_html_attributes.deep_merge(@attributes)
|
|
31
36
|
|
|
@@ -18,14 +18,25 @@ class UI::SelectComponent < ViewComponent::Base
|
|
|
18
18
|
|
|
19
19
|
# @param value [String] Currently selected value
|
|
20
20
|
# @param classes [String] Additional CSS classes to merge
|
|
21
|
+
# @param as_child [Boolean] If true, renders without wrapper div but preserves controller on inner element
|
|
21
22
|
# @param attributes [Hash] Additional HTML attributes
|
|
22
|
-
def initialize(value: nil, classes: "", **attributes)
|
|
23
|
+
def initialize(value: nil, classes: "", as_child: false, **attributes)
|
|
23
24
|
@value = value
|
|
24
25
|
@classes = classes
|
|
26
|
+
@as_child = as_child
|
|
25
27
|
@attributes = attributes
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
def call
|
|
29
|
-
|
|
31
|
+
attrs = select_html_attributes.deep_merge(@attributes)
|
|
32
|
+
if @as_child
|
|
33
|
+
# When as_child, we still need a wrapper for the Stimulus controller
|
|
34
|
+
# but we use a minimal inline wrapper that doesn't break flex layouts
|
|
35
|
+
# Override class to use 'contents' which makes the element invisible to layout
|
|
36
|
+
attrs[:class] = "contents"
|
|
37
|
+
content_tag :span, content, **attrs
|
|
38
|
+
else
|
|
39
|
+
content_tag :div, content, **attrs
|
|
40
|
+
end
|
|
30
41
|
end
|
|
31
42
|
end
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
class UI::TableComponent < ViewComponent::Base
|
|
4
4
|
include UI::TableBehavior
|
|
5
5
|
|
|
6
|
-
renders_one :table_header,
|
|
7
|
-
renders_one :table_body,
|
|
8
|
-
renders_one :table_footer,
|
|
9
|
-
renders_one :table_caption,
|
|
6
|
+
renders_one :table_header, UI::TableHeaderComponent
|
|
7
|
+
renders_one :table_body, UI::TableBodyComponent
|
|
8
|
+
renders_one :table_footer, UI::TableFooterComponent
|
|
9
|
+
renders_one :table_caption, UI::TableCaptionComponent
|
|
10
10
|
|
|
11
11
|
# Aliases amigáveis
|
|
12
12
|
alias_method :header, :with_table_header
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
class UI::TableRowComponent < ViewComponent::Base
|
|
4
4
|
include UI::TableRowBehavior
|
|
5
5
|
|
|
6
|
-
renders_many :heads,
|
|
7
|
-
renders_many :cells,
|
|
6
|
+
renders_many :heads, UI::TableHeadComponent
|
|
7
|
+
renders_many :cells, UI::TableCellComponent
|
|
8
8
|
|
|
9
9
|
# Aliases amigáveis
|
|
10
10
|
alias_method :head, :with_head
|
|
@@ -3,17 +3,48 @@
|
|
|
3
3
|
# TooltipComponent - ViewComponent implementation
|
|
4
4
|
#
|
|
5
5
|
# Root container for tooltip. Manages tooltip state via Stimulus controller.
|
|
6
|
+
#
|
|
7
|
+
# Supports asChild pattern for composition without wrapper elements.
|
|
8
|
+
#
|
|
9
|
+
# @example Basic usage
|
|
10
|
+
# <%= render UI::TooltipComponent.new do %>
|
|
11
|
+
# <%= render UI::TooltipTriggerComponent.new { "Hover me" } %>
|
|
12
|
+
# <%= render UI::TooltipContentComponent.new { "Tooltip text" } %>
|
|
13
|
+
# <% end %>
|
|
14
|
+
#
|
|
15
|
+
# @example With asChild - pass attributes to custom element
|
|
16
|
+
# <%= render UI::TooltipComponent.new(as_child: true) do |tooltip| %>
|
|
17
|
+
# <%= render UI::InputGroupAddonComponent.new(**tooltip.tooltip_attrs) do %>
|
|
18
|
+
# <%= render UI::TooltipTriggerComponent.new(as_child: true) do |trigger| %>
|
|
19
|
+
# <%= render UI::InputGroupButtonComponent.new(**trigger.trigger_attrs) { "Info" } %>
|
|
20
|
+
# <% end %>
|
|
21
|
+
# <%= render UI::TooltipContentComponent.new { "Content" } %>
|
|
22
|
+
# <% end %>
|
|
23
|
+
# <% end %>
|
|
6
24
|
class UI::TooltipComponent < ViewComponent::Base
|
|
7
25
|
include UI::TooltipBehavior
|
|
8
26
|
|
|
27
|
+
# @param as_child [Boolean] When true, yields self to block for attribute access
|
|
9
28
|
# @param attributes [Hash] Additional HTML attributes
|
|
10
|
-
def initialize(**attributes)
|
|
29
|
+
def initialize(as_child: false, **attributes)
|
|
30
|
+
@as_child = as_child
|
|
11
31
|
@attributes = attributes
|
|
12
32
|
end
|
|
13
33
|
|
|
34
|
+
# Returns tooltip attributes for as_child mode
|
|
35
|
+
def tooltip_attrs
|
|
36
|
+
tooltip_html_attributes.deep_merge(@attributes)
|
|
37
|
+
end
|
|
38
|
+
|
|
14
39
|
def call
|
|
15
|
-
|
|
40
|
+
if @as_child
|
|
41
|
+
# asChild mode: yield self to block, child accesses tooltip_attrs
|
|
16
42
|
content
|
|
43
|
+
else
|
|
44
|
+
# Default: render wrapper div with controller
|
|
45
|
+
content_tag :div, **tooltip_html_attributes.merge(@attributes.except(:data)) do
|
|
46
|
+
content
|
|
47
|
+
end
|
|
17
48
|
end
|
|
18
49
|
end
|
|
19
50
|
end
|
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
#
|
|
5
5
|
# The interactive element that shows/hides the tooltip on hover/focus.
|
|
6
6
|
# Supports asChild pattern for composition with other components.
|
|
7
|
+
#
|
|
8
|
+
# @example Basic usage
|
|
9
|
+
# <%= render UI::TooltipTriggerComponent.new do %>
|
|
10
|
+
# Hover me
|
|
11
|
+
# <% end %>
|
|
12
|
+
#
|
|
13
|
+
# @example As child (yields attributes to block)
|
|
14
|
+
# <%= render UI::TooltipTriggerComponent.new(as_child: true) do |trigger| %>
|
|
15
|
+
# <%= render UI::InputGroupButtonComponent.new(**trigger.trigger_attrs) do %>
|
|
16
|
+
# Info
|
|
17
|
+
# <% end %>
|
|
18
|
+
# <% end %>
|
|
7
19
|
class UI::TooltipTriggerComponent < ViewComponent::Base
|
|
8
20
|
include UI::TooltipTriggerBehavior
|
|
9
21
|
|
|
@@ -14,12 +26,20 @@ class UI::TooltipTriggerComponent < ViewComponent::Base
|
|
|
14
26
|
@attributes = attributes
|
|
15
27
|
end
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
# Returns trigger attributes for as_child mode
|
|
30
|
+
def trigger_attrs
|
|
31
|
+
tooltip_trigger_html_attributes.deep_merge(@attributes)
|
|
32
|
+
end
|
|
19
33
|
|
|
20
|
-
|
|
21
|
-
|
|
34
|
+
def call
|
|
35
|
+
if @as_child
|
|
36
|
+
# asChild mode: yield self so caller can access trigger_attrs
|
|
22
37
|
content
|
|
38
|
+
else
|
|
39
|
+
# Default mode: render as button with proper styling
|
|
40
|
+
content_tag :button, **trigger_attrs do
|
|
41
|
+
content
|
|
42
|
+
end
|
|
23
43
|
end
|
|
24
44
|
end
|
|
25
45
|
end
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
<%
|
|
2
|
-
|
|
2
|
+
# Avatar - ERB Partial
|
|
3
|
+
#
|
|
4
|
+
# Displays an image element with a fallback for representing users.
|
|
5
|
+
#
|
|
6
|
+
# @param classes [String] Additional CSS classes to merge
|
|
7
|
+
|
|
8
|
+
@classes = local_assigns.fetch(:classes, "")
|
|
3
9
|
|
|
4
10
|
# Include behavior module
|
|
5
11
|
extend UI::AvatarBehavior
|
|
6
12
|
|
|
7
13
|
# Get HTML attributes from behavior
|
|
8
14
|
attrs = avatar_html_attributes
|
|
9
|
-
|
|
10
|
-
data_attrs = attrs[:data]
|
|
11
|
-
%><span class="<%= all_classes %>" data-controller="<%= data_attrs[:controller] %>" data-slot="<%= data_attrs[:slot] %>">
|
|
15
|
+
%><span class="<%= attrs[:class] %>" data-controller="<%= attrs[:data][:controller] %>" data-slot="<%= attrs[:data][:slot] %>">
|
|
12
16
|
<%= yield %>
|
|
13
17
|
</span>
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
# @param disabled [Boolean] Whether the button is disabled
|
|
12
12
|
# @param classes [String] Additional CSS classes to merge
|
|
13
13
|
# @param attributes [Hash] Additional HTML attributes
|
|
14
|
+
#
|
|
15
|
+
# Supports splatting attributes from parent components (e.g., **trigger_attrs)
|
|
16
|
+
# When attributes are splatted, data/class/id are merged from local_assigns
|
|
14
17
|
|
|
15
18
|
@variant = local_assigns.fetch(:variant, "default")
|
|
16
19
|
@size = local_assigns.fetch(:size, "default")
|
|
@@ -20,6 +23,19 @@
|
|
|
20
23
|
@attributes = local_assigns.fetch(:attributes, {})
|
|
21
24
|
content_param = local_assigns.fetch(:content, nil)
|
|
22
25
|
|
|
26
|
+
# Support for splatted attributes (e.g., **trigger_attrs)
|
|
27
|
+
# Merge data and class from local_assigns if present (from splatting)
|
|
28
|
+
splatted_data = local_assigns.fetch(:data, {})
|
|
29
|
+
splatted_class = local_assigns.fetch(:class, nil)
|
|
30
|
+
|
|
31
|
+
# Merge splatted attributes into @attributes
|
|
32
|
+
if splatted_data.present?
|
|
33
|
+
@attributes = @attributes.deep_merge(data: splatted_data)
|
|
34
|
+
end
|
|
35
|
+
if splatted_class.present?
|
|
36
|
+
@attributes[:class] = TailwindMerge::Merger.new.merge([@attributes[:class], splatted_class].compact.join(" "))
|
|
37
|
+
end
|
|
38
|
+
|
|
23
39
|
extend UI::ButtonBehavior
|
|
24
40
|
base_attrs = button_html_attributes
|
|
25
41
|
|
|
@@ -61,14 +61,14 @@
|
|
|
61
61
|
-%>
|
|
62
62
|
<%= content_tag :div, all_attributes do %>
|
|
63
63
|
<% if @label %>
|
|
64
|
-
<%= render "ui/label
|
|
64
|
+
<%= render "ui/label", content: @label, for: @label_for, classes: "px-1" %>
|
|
65
65
|
<% end %>
|
|
66
66
|
|
|
67
|
-
<%= render "ui/popover
|
|
67
|
+
<%= render "ui/popover", trigger: "click", placement: "bottom-start", offset: 4 do %>
|
|
68
68
|
<%= yield %>
|
|
69
69
|
|
|
70
|
-
<%= render "ui/popover/
|
|
71
|
-
<%= render "ui/calendar
|
|
70
|
+
<%= render "ui/popover/content", classes: "w-auto overflow-hidden p-0" do %>
|
|
71
|
+
<%= render "ui/calendar",
|
|
72
72
|
mode: @mode,
|
|
73
73
|
selected: @selected,
|
|
74
74
|
locale: @locale,
|
|
@@ -1,19 +1,45 @@
|
|
|
1
1
|
<%# Popover Component - Container for popover trigger and content %>
|
|
2
|
+
<%#
|
|
3
|
+
Supports asChild pattern for composition without wrapper elements.
|
|
4
|
+
|
|
5
|
+
@example Basic usage
|
|
6
|
+
render "ui/popover" do
|
|
7
|
+
render "ui/popover/trigger" { "Open" }
|
|
8
|
+
render "ui/popover/content" { "Content" }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
@example With asChild (no wrapper div)
|
|
12
|
+
render "ui/popover", as_child: true do |popover_attrs|
|
|
13
|
+
render "ui/input_group/addon", attributes: popover_attrs do
|
|
14
|
+
render "ui/popover/trigger", as_child: true do |trigger_attrs|
|
|
15
|
+
...
|
|
16
|
+
end
|
|
17
|
+
render "ui/popover/content" { "Content" }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
%>
|
|
2
21
|
<%
|
|
22
|
+
@as_child = local_assigns.fetch(:as_child, false)
|
|
3
23
|
@trigger = local_assigns.fetch(:trigger, "click")
|
|
4
24
|
@placement = local_assigns.fetch(:placement, "bottom")
|
|
5
|
-
@offset = local_assigns.fetch(:offset,
|
|
25
|
+
@offset = local_assigns.fetch(:offset, 4)
|
|
6
26
|
@hover_delay = local_assigns.fetch(:hover_delay, 0)
|
|
7
27
|
@align = local_assigns.fetch(:align, nil)
|
|
8
28
|
@classes = local_assigns.fetch(:classes, "")
|
|
9
29
|
@attributes = local_assigns.fetch(:attributes, {})
|
|
30
|
+
@data = local_assigns.fetch(:data, {})
|
|
10
31
|
|
|
11
32
|
# Extend behavior for shared logic
|
|
12
33
|
extend UI::PopoverBehavior
|
|
13
34
|
|
|
14
|
-
# Get HTML attributes from behavior
|
|
35
|
+
# Get HTML attributes from behavior and deep merge with passed data and attributes
|
|
15
36
|
all_attributes = popover_html_attributes.deep_merge(@attributes)
|
|
37
|
+
all_attributes[:data] = (all_attributes[:data] || {}).merge(@data) if @data.present?
|
|
16
38
|
-%>
|
|
17
|
-
|
|
18
|
-
<%= yield %>
|
|
39
|
+
<% if @as_child %>
|
|
40
|
+
<%= yield(all_attributes) %>
|
|
41
|
+
<% else %>
|
|
42
|
+
<%= content_tag :div, all_attributes do %>
|
|
43
|
+
<%= yield %>
|
|
44
|
+
<% end %>
|
|
19
45
|
<% end %>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
@attributes = local_assigns.fetch(:attributes, {})
|
|
5
5
|
@value = local_assigns.fetch(:value, nil)
|
|
6
6
|
@id = local_assigns.fetch(:id, nil)
|
|
7
|
+
as_child = local_assigns.fetch(:as_child, false)
|
|
7
8
|
|
|
8
9
|
# Extend behavior for shared logic
|
|
9
10
|
extend ::UI::SelectBehavior
|
|
@@ -12,6 +13,16 @@
|
|
|
12
13
|
all_attributes = select_html_attributes.deep_merge(@attributes)
|
|
13
14
|
all_attributes[:id] = @id if @id.present?
|
|
14
15
|
-%>
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
<% if as_child %>
|
|
17
|
+
<%# When as_child, we still need a wrapper for the Stimulus controller
|
|
18
|
+
but we use a minimal inline wrapper that doesn't break flex layouts
|
|
19
|
+
Override class to use 'contents' which makes the element invisible to layout %>
|
|
20
|
+
<% all_attributes[:class] = "contents" %>
|
|
21
|
+
<%= content_tag :span, all_attributes do %>
|
|
22
|
+
<%= yield %>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% else %>
|
|
25
|
+
<%= content_tag :div, all_attributes do %>
|
|
26
|
+
<%= yield %>
|
|
27
|
+
<% end %>
|
|
17
28
|
<% end %>
|
|
@@ -13,7 +13,7 @@ html_class = local_assigns.fetch(:class, "")
|
|
|
13
13
|
attributes = local_assigns.except(:class)
|
|
14
14
|
|
|
15
15
|
default_classes = "bg-accent animate-pulse rounded-md"
|
|
16
|
-
merged_classes = [default_classes, html_class].compact_blank.join(" ")
|
|
16
|
+
merged_classes = TailwindMerge::Merger.new.merge([default_classes, html_class].compact_blank.join(" "))
|
|
17
17
|
%>
|
|
18
18
|
|
|
19
19
|
<div data-slot="skeleton" class="<%= merged_classes %>" <%= attributes.map { |k, v| "#{k}=\"#{v}\"" }.join(" ").html_safe %>></div>
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
<%# Tooltip Component - Root container for tooltip %>
|
|
2
|
+
<%#
|
|
3
|
+
Supports asChild pattern for composition without wrapper elements.
|
|
4
|
+
|
|
5
|
+
@example Basic usage
|
|
6
|
+
render "ui/tooltip" do
|
|
7
|
+
render "ui/tooltip/trigger" { "Hover me" }
|
|
8
|
+
render "ui/tooltip/content" { "Tooltip text" }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
@example With asChild (no wrapper div)
|
|
12
|
+
render "ui/tooltip", as_child: true do |tooltip_attrs|
|
|
13
|
+
render "ui/input_group/addon", attributes: tooltip_attrs do
|
|
14
|
+
render "ui/tooltip/trigger", as_child: true do |trigger_attrs|
|
|
15
|
+
render "ui/input_group/button", attributes: trigger_attrs do
|
|
16
|
+
"Info"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
render "ui/tooltip/content" { "Content" }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
%>
|
|
2
23
|
<%
|
|
24
|
+
@as_child = local_assigns.fetch(:as_child, false)
|
|
3
25
|
@attributes = local_assigns.fetch(:attributes, {})
|
|
4
26
|
|
|
5
27
|
# Extend behavior for shared logic
|
|
@@ -8,6 +30,10 @@
|
|
|
8
30
|
# Get HTML attributes from behavior
|
|
9
31
|
all_attributes = tooltip_html_attributes.deep_merge(@attributes)
|
|
10
32
|
-%>
|
|
11
|
-
|
|
12
|
-
<%= yield %>
|
|
33
|
+
<% if @as_child %>
|
|
34
|
+
<%= yield(all_attributes) %>
|
|
35
|
+
<% else %>
|
|
36
|
+
<%= content_tag :div, all_attributes do %>
|
|
37
|
+
<%= yield %>
|
|
38
|
+
<% end %>
|
|
13
39
|
<% end %>
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
all_attributes = dropdown_menu_trigger_html_attributes.deep_merge(@attributes)
|
|
13
13
|
-%>
|
|
14
14
|
<% if as_child %>
|
|
15
|
-
|
|
15
|
+
<%# When as_child is true, only pass functional attributes (data, aria, tabindex, role)
|
|
16
|
+
The child component handles its own styling (following shadcn pattern) %>
|
|
17
|
+
<%= yield(all_attributes.except(:class)) %>
|
|
16
18
|
<% else %>
|
|
17
19
|
<%= content_tag :div, all_attributes do %>
|
|
18
20
|
<%= content || yield %>
|
|
@@ -10,9 +10,20 @@
|
|
|
10
10
|
# Extend behavior for shared logic
|
|
11
11
|
extend UI::InputGroupButtonBehavior
|
|
12
12
|
|
|
13
|
-
# Get
|
|
14
|
-
|
|
13
|
+
# Get base attributes from behavior (type, variant, classes)
|
|
14
|
+
base_attrs = input_group_button_attributes
|
|
15
|
+
|
|
16
|
+
# Extract button-specific params that ui/button accepts as direct arguments
|
|
17
|
+
button_params = {
|
|
18
|
+
type: base_attrs[:type],
|
|
19
|
+
variant: base_attrs[:variant],
|
|
20
|
+
classes: base_attrs[:classes]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Merge additional HTML attributes (data, role, aria, tabindex, etc.) into attributes hash
|
|
24
|
+
html_attrs = @attributes.except(:type, :variant, :classes)
|
|
25
|
+
button_params[:attributes] = html_attrs unless html_attrs.empty?
|
|
15
26
|
-%>
|
|
16
|
-
<%= render "ui/button", **
|
|
27
|
+
<%= render "ui/button", **button_params do %>
|
|
17
28
|
<%= content || yield %>
|
|
18
29
|
<% end %>
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
<%# Popover Trigger - Button or element that triggers the popover %>
|
|
2
|
+
<%#
|
|
3
|
+
Supports asChild pattern for composition without wrapper elements.
|
|
4
|
+
|
|
5
|
+
@example Basic usage
|
|
6
|
+
render "ui/popover/trigger" do
|
|
7
|
+
button { "Click me" }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
@example With asChild
|
|
11
|
+
render "ui/popover/trigger", as_child: true do |trigger_attrs|
|
|
12
|
+
render "ui/input_group/button", attributes: trigger_attrs do
|
|
13
|
+
"Info"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
%>
|
|
2
17
|
<%
|
|
3
18
|
content ||= local_assigns.fetch(:content, nil)
|
|
19
|
+
as_child = local_assigns.fetch(:as_child, false)
|
|
4
20
|
@classes = local_assigns.fetch(:classes, "")
|
|
5
21
|
@attributes = local_assigns.fetch(:attributes, {})
|
|
6
22
|
|
|
@@ -10,6 +26,10 @@
|
|
|
10
26
|
# Get HTML attributes from behavior
|
|
11
27
|
all_attributes = popover_trigger_html_attributes.deep_merge(@attributes)
|
|
12
28
|
-%>
|
|
13
|
-
|
|
14
|
-
<%=
|
|
29
|
+
<% if as_child %>
|
|
30
|
+
<%= yield(all_attributes) %>
|
|
31
|
+
<% else %>
|
|
32
|
+
<%= content_tag :div, all_attributes do %>
|
|
33
|
+
<%= content || yield %>
|
|
34
|
+
<% end %>
|
|
15
35
|
<% end %>
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
<%# Tooltip Trigger - Interactive element that shows/hides tooltip %>
|
|
2
|
+
<%#
|
|
3
|
+
Supports asChild pattern for composition without wrapper elements.
|
|
4
|
+
|
|
5
|
+
@example Basic usage
|
|
6
|
+
render "ui/tooltip/trigger" do
|
|
7
|
+
"Hover me"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
@example With asChild
|
|
11
|
+
render "ui/tooltip/trigger", as_child: true do |trigger_attrs|
|
|
12
|
+
render "ui/input_group/button", attributes: trigger_attrs do
|
|
13
|
+
"Info"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
%>
|
|
2
17
|
<%
|
|
3
18
|
@as_child = local_assigns.fetch(:as_child, false)
|
|
4
19
|
@attributes = local_assigns.fetch(:attributes, {})
|
|
@@ -10,27 +25,7 @@
|
|
|
10
25
|
trigger_attrs = tooltip_trigger_html_attributes.deep_merge(@attributes)
|
|
11
26
|
-%>
|
|
12
27
|
<% if @as_child %>
|
|
13
|
-
|
|
14
|
-
<% captured_content = capture { yield } %>
|
|
15
|
-
<%= raw captured_content.sub(/(<[a-z][a-z0-9]*)([\s>])/i) do |match|
|
|
16
|
-
tag_start, tag_end = $1, $2
|
|
17
|
-
|
|
18
|
-
# Build attributes string manually
|
|
19
|
-
attrs_array = trigger_attrs.map do |key, value|
|
|
20
|
-
if key == :data && value.is_a?(Hash)
|
|
21
|
-
# Handle data attributes
|
|
22
|
-
value.map { |k, v| "data-#{k.to_s.dasherize}=\"#{ERB::Util.html_escape(v)}\"" }.join(" ")
|
|
23
|
-
elsif value.is_a?(TrueClass)
|
|
24
|
-
key.to_s.dasherize
|
|
25
|
-
elsif value.is_a?(FalseClass) || value.nil?
|
|
26
|
-
nil
|
|
27
|
-
else
|
|
28
|
-
"#{key.to_s.dasherize}=\"#{ERB::Util.html_escape(value)}\""
|
|
29
|
-
end
|
|
30
|
-
end.compact.join(" ")
|
|
31
|
-
|
|
32
|
-
"#{tag_start} #{attrs_array}#{tag_end}"
|
|
33
|
-
end %>
|
|
28
|
+
<%= yield(trigger_attrs) %>
|
|
34
29
|
<% else %>
|
|
35
30
|
<%# Default mode: render as button %>
|
|
36
31
|
<%= content_tag :button, trigger_attrs do %>
|
data/lib/ui/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fernandes-ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Celso Fernandes
|
|
@@ -379,6 +379,7 @@ files:
|
|
|
379
379
|
- app/components/ui/avatar_fallback.rb
|
|
380
380
|
- app/components/ui/avatar_image.rb
|
|
381
381
|
- app/components/ui/badge.rb
|
|
382
|
+
- app/components/ui/base.rb
|
|
382
383
|
- app/components/ui/blockquote.rb
|
|
383
384
|
- app/components/ui/breadcrumb.rb
|
|
384
385
|
- app/components/ui/breadcrumb_ellipsis.rb
|