ruby_ui 1.4.0 → 1.6.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/ruby_ui/dependencies.yml +12 -2
  3. data/lib/generators/ruby_ui/javascript_utils.rb +0 -13
  4. data/lib/ruby_ui/accordion/accordion_controller.js +16 -9
  5. data/lib/ruby_ui/bubble/bubble.rb +37 -0
  6. data/lib/ruby_ui/bubble/bubble_content.rb +23 -0
  7. data/lib/ruby_ui/bubble/bubble_docs.rb +167 -0
  8. data/lib/ruby_ui/bubble/bubble_group.rb +18 -0
  9. data/lib/ruby_ui/bubble/bubble_reactions.rb +38 -0
  10. data/lib/ruby_ui/combobox/combobox.rb +3 -1
  11. data/lib/ruby_ui/combobox/combobox_checkbox.rb +8 -1
  12. data/lib/ruby_ui/combobox/combobox_controller.js +3 -2
  13. data/lib/ruby_ui/combobox/combobox_trigger.rb +1 -4
  14. data/lib/ruby_ui/context_menu/context_menu_content.rb +5 -6
  15. data/lib/ruby_ui/context_menu/context_menu_controller.js +87 -75
  16. data/lib/ruby_ui/data_table/data_table_column_toggle.rb +8 -4
  17. data/lib/ruby_ui/data_table/data_table_column_visibility_controller.js +12 -2
  18. data/lib/ruby_ui/dialog/dialog_content.rb +1 -1
  19. data/lib/ruby_ui/dropdown_menu/dropdown_menu.rb +0 -1
  20. data/lib/ruby_ui/dropdown_menu/dropdown_menu_controller.js +5 -1
  21. data/lib/ruby_ui/dropdown_menu/dropdown_menu_docs.rb +1 -1
  22. data/lib/ruby_ui/empty/empty.rb +18 -0
  23. data/lib/ruby_ui/empty/empty_content.rb +18 -0
  24. data/lib/ruby_ui/empty/empty_description.rb +18 -0
  25. data/lib/ruby_ui/empty/empty_docs.rb +69 -0
  26. data/lib/ruby_ui/empty/empty_header.rb +18 -0
  27. data/lib/ruby_ui/empty/empty_media.rb +31 -0
  28. data/lib/ruby_ui/empty/empty_title.rb +18 -0
  29. data/lib/ruby_ui/hover_card/hover_card_content.rb +5 -6
  30. data/lib/ruby_ui/hover_card/hover_card_controller.js +113 -76
  31. data/lib/ruby_ui/input_otp/input_otp.rb +42 -0
  32. data/lib/ruby_ui/input_otp/input_otp_controller.js +128 -0
  33. data/lib/ruby_ui/input_otp/input_otp_docs.rb +213 -0
  34. data/lib/ruby_ui/input_otp/input_otp_group.rb +15 -0
  35. data/lib/ruby_ui/input_otp/input_otp_separator.rb +39 -0
  36. data/lib/ruby_ui/input_otp/input_otp_slot.rb +33 -0
  37. data/lib/ruby_ui/message/message.rb +23 -0
  38. data/lib/ruby_ui/message/message_avatar.rb +18 -0
  39. data/lib/ruby_ui/message/message_content.rb +18 -0
  40. data/lib/ruby_ui/message/message_docs.rb +173 -0
  41. data/lib/ruby_ui/message/message_footer.rb +18 -0
  42. data/lib/ruby_ui/message/message_group.rb +18 -0
  43. data/lib/ruby_ui/message/message_header.rb +18 -0
  44. data/lib/ruby_ui/message_scroller/message_scroller.rb +18 -0
  45. data/lib/ruby_ui/message_scroller/message_scroller_button.rb +56 -0
  46. data/lib/ruby_ui/message_scroller/message_scroller_content.rb +23 -0
  47. data/lib/ruby_ui/message_scroller/message_scroller_controller.js +335 -0
  48. data/lib/ruby_ui/message_scroller/message_scroller_docs.rb +208 -0
  49. data/lib/ruby_ui/message_scroller/message_scroller_item.rb +28 -0
  50. data/lib/ruby_ui/message_scroller/message_scroller_provider.rb +34 -0
  51. data/lib/ruby_ui/message_scroller/message_scroller_viewport.rb +22 -0
  52. data/lib/ruby_ui/native_select/native_select_icon.rb +1 -1
  53. data/lib/ruby_ui/popover/popover_content.rb +2 -1
  54. data/lib/ruby_ui/popover/popover_controller.js +95 -32
  55. data/lib/ruby_ui/toast/toaster_controller.js +24 -8
  56. data/lib/ruby_ui.rb +1 -1
  57. metadata +34 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8dd00d73934f8ff9e2ac4e92994de33c910192f92df634def1e1726bde86393
4
- data.tar.gz: 50ba081c5c25aa85581620726935ca1469b402751eade75cdb8adbc2042160d5
3
+ metadata.gz: 2d65c0b25a3f006ce2a97107b84779fb313f55fe0937048f033a8a4477ee5bda
4
+ data.tar.gz: fccde45b64530b69c9c1b3330f2203da5d4921a2b89a48dbc25ae2d27f8d36fd
5
5
  SHA512:
6
- metadata.gz: 44150fd27560c0b3a7d5193501abfd755e36a15ae74dc555088b9a30a1b228adc521dd8a82fc705e3c2396a45bb0baf48aed1351840d96aaa87eae6a9c2d545d
7
- data.tar.gz: fc536b32afeabc805ad4815ce9be98090caf2402e6c5cc920011d9166b721690eb35938195b5079bf44b7400c4ec5454642f00ea844df22062ef326e32316bc4
6
+ metadata.gz: ed144e39bf1a8cdf62f5550a9fdf1426cbc609979dbc7049c33c9c0e6fac737adffad32bbe5f21dd21c6de8b974ffe5c61a9ebd24011001411edac378629b416
7
+ data.tar.gz: 158aa2d122d94feadfb41ebd67e6e2078cf3b8ef9675fb94f23d228e0d27fcfb3b206e46a6f8bf47c3f8ede71b8c68e32c18db7ff9a8e3188f5a000138142d4e
@@ -40,7 +40,7 @@ command:
40
40
 
41
41
  context_menu:
42
42
  js_packages:
43
- - "tippy.js"
43
+ - "@floating-ui/dom"
44
44
 
45
45
  date_picker:
46
46
  components:
@@ -64,7 +64,7 @@ dropdown_menu:
64
64
 
65
65
  hover_card:
66
66
  js_packages:
67
- - "tippy.js"
67
+ - "@floating-ui/dom"
68
68
 
69
69
  masked_input:
70
70
  components:
@@ -73,6 +73,16 @@ masked_input:
73
73
  js_packages:
74
74
  - "maska"
75
75
 
76
+ message:
77
+ components:
78
+ - "Avatar"
79
+ - "Bubble"
80
+
81
+ message_scroller:
82
+ components:
83
+ - "Message"
84
+ - "Bubble"
85
+
76
86
  pagination:
77
87
  components:
78
88
  - "Button"
@@ -25,8 +25,6 @@ module RubyUI
25
25
  pin_motion
26
26
  when "tw-animate-css"
27
27
  pin_tw_animate_css
28
- when "tippy.js"
29
- pin_tippy_js
30
28
  else
31
29
  run "bin/importmap pin #{package}"
32
30
  end
@@ -65,17 +63,6 @@ module RubyUI
65
63
  RUBY
66
64
  end
67
65
 
68
- def pin_tippy_js
69
- say <<~TEXT
70
- WARNING: Installing tippy.js from CDN because `bin/importmap pin tippy.js` doesn't download the correct file.
71
- TEXT
72
-
73
- inject_into_file rails_root.join("config/importmap.rb"), <<~RUBY
74
- pin "tippy.js", to: "https://cdn.jsdelivr.net/npm/tippy.js@6.3.7/+esm"
75
- pin "@popperjs/core", to: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/+esm"\n
76
- RUBY
77
- end
78
-
79
66
  def rails_root = Rails.root
80
67
  end
81
68
  end
@@ -79,7 +79,11 @@ export default class extends Controller {
79
79
  duration: this.animationDurationValue,
80
80
  easing: this.animationEasingValue,
81
81
  },
82
- );
82
+ )
83
+ .finished.then(() => {
84
+ if (content.dataset.state === "open") content.style.height = "auto";
85
+ })
86
+ .catch(() => {});
83
87
  }
84
88
 
85
89
  // Hide the accordion content with animation
@@ -87,20 +91,23 @@ export default class extends Controller {
87
91
  const content = this.contentTarget;
88
92
  content.dataset.state = "closed";
89
93
 
94
+ const currentHeight = content.getBoundingClientRect().height;
90
95
  animate(
91
96
  content,
92
- { height: 0 },
97
+ { height: [`${currentHeight}px`, "0px"] },
93
98
  {
94
99
  duration: this.animationDurationValue,
95
100
  easing: this.animationEasingValue,
96
101
  },
97
- ).finished.then(() => {
98
- // After animation completes, truly hide the element so it is removed
99
- // from layout and form focus prevents trapped validation errors
100
- if (content.dataset.state === "closed") {
101
- content.setAttribute("hidden", "");
102
- }
103
- });
102
+ )
103
+ .finished.then(() => {
104
+ // After animation completes, truly hide the element so it is removed
105
+ // from layout and form focus — prevents trapped validation errors
106
+ if (content.dataset.state === "closed") {
107
+ content.setAttribute("hidden", "");
108
+ }
109
+ })
110
+ .catch(() => {});
104
111
  }
105
112
 
106
113
  // Rotate the accordion icon 180deg using animate function
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class Bubble < Base
5
+ VARIANTS = {
6
+ default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
7
+ secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
8
+ muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
9
+ tinted: "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
10
+ outline: "*:data-[slot=bubble-content]:bg-background *:data-[slot=bubble-content]:border-border [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
11
+ ghost: "*:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50 border-none",
12
+ destructive: "*:data-[slot=bubble-content]:bg-destructive/10 dark:*:data-[slot=bubble-content]:bg-destructive/20 *:data-[slot=bubble-content]:text-destructive [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
13
+ }
14
+
15
+ def initialize(variant: :default, align: :start, **attrs)
16
+ @variant = variant
17
+ @align = align
18
+ super(**attrs)
19
+ end
20
+
21
+ def view_template(&)
22
+ div(**attrs, &)
23
+ end
24
+
25
+ private
26
+
27
+ def default_attrs
28
+ {
29
+ data: {slot: "bubble", variant: @variant, align: @align},
30
+ class: [
31
+ "group/bubble relative flex w-fit min-w-0 flex-col gap-1 max-w-[80%] data-[align=end]:self-end data-[variant=ghost]:max-w-full",
32
+ VARIANTS[@variant]
33
+ ]
34
+ }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class BubbleContent < Base
5
+ def initialize(as: :div, **attrs)
6
+ @as = as
7
+ super(**attrs)
8
+ end
9
+
10
+ def view_template(&)
11
+ send(@as, **attrs, &)
12
+ end
13
+
14
+ private
15
+
16
+ def default_attrs
17
+ {
18
+ data: {slot: "bubble-content"},
19
+ class: "w-fit max-w-full min-w-0 overflow-hidden wrap-break-word rounded-3xl border border-transparent px-3 py-2.5 text-sm leading-relaxed group-data-[align=end]/bubble:self-end [&:is(button,a)]:text-left [&:is(button,a)]:outline-none [&:is(button,a)]:transition-colors [&:is(button,a):focus-visible]:border-ring [&:is(button,a):focus-visible]:ring-3 [&:is(button,a):focus-visible]:ring-ring/30"
20
+ }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Views::Docs::Bubble < Views::Base
4
+ def view_template
5
+ component = "Bubble"
6
+
7
+ div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do
8
+ render Docs::Header.new(title: "Bubble", description: "A chat bubble surface for displaying conversational content, with variants, alignment, grouping, and reactions.")
9
+
10
+ Heading(level: 2) { "Usage" }
11
+
12
+ render Docs::VisualCodeExample.new(title: "Default", context: self) do
13
+ <<~RUBY
14
+ Bubble(align: :end) do
15
+ BubbleContent { "Hey there! what's up?" }
16
+ end
17
+ RUBY
18
+ end
19
+
20
+ render Docs::VisualCodeExample.new(title: "Conversation", context: self) do
21
+ <<~RUBY
22
+ div(class: "flex flex-col gap-8") do
23
+ Bubble(align: :end) do
24
+ BubbleContent { "Hey there! what's up?" }
25
+ end
26
+ BubbleGroup do
27
+ Bubble(variant: :muted) do
28
+ BubbleContent { "Hey! Want to see chat bubbles?" }
29
+ end
30
+ Bubble(variant: :muted) do
31
+ BubbleContent { "I can group messages, switch sides, and keep the whole thread easy to scan." }
32
+ BubbleReactions(role: "img", aria_label: "Reaction: thumbs up") do
33
+ span { "👍" }
34
+ end
35
+ end
36
+ end
37
+ Bubble(align: :end) do
38
+ BubbleContent { "Sure. Hit me with your best demo." }
39
+ end
40
+ end
41
+ RUBY
42
+ end
43
+
44
+ Heading(level: 2) { "Variants" }
45
+
46
+ render Docs::VisualCodeExample.new(title: "Variants", context: self) do
47
+ <<~RUBY
48
+ div(class: "flex flex-col gap-4 w-full") do
49
+ Bubble(variant: :default) { BubbleContent { "Default" } }
50
+ Bubble(variant: :secondary) { BubbleContent { "Secondary" } }
51
+ Bubble(variant: :muted) { BubbleContent { "Muted" } }
52
+ Bubble(variant: :tinted) { BubbleContent { "Tinted" } }
53
+ Bubble(variant: :outline) { BubbleContent { "Outline" } }
54
+ Bubble(variant: :ghost) { BubbleContent { "Ghost — unframed, full width for assistant text or markdown." } }
55
+ Bubble(variant: :destructive) { BubbleContent { "Destructive — something went wrong." } }
56
+ end
57
+ RUBY
58
+ end
59
+
60
+ Heading(level: 2) { "Alignment" }
61
+
62
+ render Docs::VisualCodeExample.new(title: "Start and end", context: self) do
63
+ <<~RUBY
64
+ div(class: "flex flex-col gap-4 w-full") do
65
+ Bubble(align: :start, variant: :muted) do
66
+ BubbleContent { "Aligned to the start (receiver)." }
67
+ end
68
+ Bubble(align: :end) do
69
+ BubbleContent { "Aligned to the end (sender)." }
70
+ end
71
+ end
72
+ RUBY
73
+ end
74
+
75
+ Heading(level: 2) { "Reactions" }
76
+
77
+ render Docs::VisualCodeExample.new(title: "Reactions", context: self) do
78
+ <<~RUBY
79
+ div(class: "flex flex-col gap-10 w-full py-6") do
80
+ Bubble(variant: :muted) do
81
+ BubbleContent { "Reactions anchor to the bubble edge." }
82
+ BubbleReactions(role: "img", aria_label: "Reactions: thumbs up, fire, eyes, and 2 more") do
83
+ span { "👍" }
84
+ span { "🔥" }
85
+ span { "👀" }
86
+ span { "+2" }
87
+ end
88
+ end
89
+ Bubble(align: :end) do
90
+ BubbleContent { "Place them on top and to the start too." }
91
+ BubbleReactions(side: :top, align: :start, role: "img", aria_label: "Reaction: heart") do
92
+ span { "❤️" }
93
+ end
94
+ end
95
+ end
96
+ RUBY
97
+ end
98
+
99
+ Heading(level: 2) { "Group" }
100
+
101
+ render Docs::VisualCodeExample.new(title: "Bubble group", context: self) do
102
+ <<~RUBY
103
+ BubbleGroup do
104
+ Bubble(variant: :muted) { BubbleContent { "First message in the group." } }
105
+ Bubble(variant: :muted) { BubbleContent { "Second one, tighter spacing." } }
106
+ Bubble(variant: :muted) { BubbleContent { "Third, all stacked together." } }
107
+ end
108
+ RUBY
109
+ end
110
+
111
+ Heading(level: 2) { "Link or button bubble" }
112
+
113
+ render Docs::VisualCodeExample.new(title: "Interactive content", context: self) do
114
+ <<~RUBY
115
+ div(class: "flex flex-col gap-4 w-full") do
116
+ Bubble(align: :end) do
117
+ BubbleContent(as: :a, href: "#") { "Tap to open the link →" }
118
+ end
119
+ Bubble(variant: :outline) do
120
+ BubbleContent(as: :button, type: "button") { "Retry sending" }
121
+ end
122
+ end
123
+ RUBY
124
+ end
125
+
126
+ Heading(level: 2) { "With Tooltip" }
127
+
128
+ render Docs::VisualCodeExample.new(title: "Reveal metadata on hover", context: self) do
129
+ <<~RUBY
130
+ Tooltip do
131
+ TooltipTrigger(class: "w-fit") do
132
+ Bubble(variant: :muted, class: "max-w-none") do
133
+ BubbleContent { "Read 9:41 AM" }
134
+ end
135
+ end
136
+ TooltipContent do
137
+ Text { "Delivered and read" }
138
+ end
139
+ end
140
+ RUBY
141
+ end
142
+
143
+ Heading(level: 2) { "With Popover" }
144
+
145
+ render Docs::VisualCodeExample.new(title: "Surface details on demand", context: self) do
146
+ <<~RUBY
147
+ Popover do
148
+ PopoverTrigger do
149
+ Bubble(variant: :destructive, class: "max-w-none") do
150
+ BubbleContent { "Message failed to send" }
151
+ end
152
+ end
153
+ PopoverContent(class: "w-64") do
154
+ Text(weight: :semibold) { "Delivery error" }
155
+ Text(size: :sm, class: "text-muted-foreground") { "The recipient's inbox is full. Try again later." }
156
+ end
157
+ end
158
+ RUBY
159
+ end
160
+
161
+ render Components::ComponentSetup::Tabs.new(component_name: component)
162
+
163
+ # components
164
+ render Docs::ComponentsTable.new(component_files(component))
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class BubbleGroup < Base
5
+ def view_template(&)
6
+ div(**attrs, &)
7
+ end
8
+
9
+ private
10
+
11
+ def default_attrs
12
+ {
13
+ data: {slot: "bubble-group"},
14
+ class: "flex min-w-0 flex-col gap-2"
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyUI
4
+ class BubbleReactions < Base
5
+ SIDES = {
6
+ top: "top-0 -translate-y-3/4",
7
+ bottom: "bottom-0 translate-y-3/4"
8
+ }
9
+
10
+ ALIGNS = {
11
+ start: "left-3",
12
+ end: "right-3"
13
+ }
14
+
15
+ def initialize(side: :bottom, align: :end, **attrs)
16
+ @side = side
17
+ @align = align
18
+ super(**attrs)
19
+ end
20
+
21
+ def view_template(&)
22
+ div(**attrs, &)
23
+ end
24
+
25
+ private
26
+
27
+ def default_attrs
28
+ {
29
+ data: {slot: "bubble-reactions", side: @side, align: @align},
30
+ class: [
31
+ "absolute z-10 flex w-fit items-center justify-center rounded-full ring-3 ring-card bg-muted shrink-0 gap-1 px-1.5 py-0.5 has-[button]:p-0 text-sm",
32
+ SIDES[@side],
33
+ ALIGNS[@align]
34
+ ]
35
+ }
36
+ end
37
+ end
38
+ end
@@ -2,8 +2,9 @@
2
2
 
3
3
  module RubyUI
4
4
  class Combobox < Base
5
- def initialize(term: nil, **)
5
+ def initialize(term: nil, placement: "bottom-start", **)
6
6
  @term = term
7
+ @placement = placement
7
8
  super(**)
8
9
  end
9
10
 
@@ -19,6 +20,7 @@ module RubyUI
19
20
  data: {
20
21
  controller: "ruby-ui--combobox",
21
22
  ruby_ui__combobox_term_value: @term,
23
+ ruby_ui__combobox_placement_value: @placement,
22
24
  action: "turbo:morph@window->ruby-ui--combobox#updateTriggerContent"
23
25
  }
24
26
  }
@@ -19,7 +19,14 @@ module RubyUI
19
19
  ],
20
20
  data: {
21
21
  ruby_ui__combobox_target: "input",
22
- action: "ruby-ui--combobox#inputChanged"
22
+ ruby_ui__checkbox_group_target: "checkbox",
23
+ ruby_ui__form_field_target: "input",
24
+ action: %w[
25
+ ruby-ui--combobox#inputChanged
26
+ change->ruby-ui--checkbox-group#onChange
27
+ change->ruby-ui--form-field#onInput
28
+ invalid->ruby-ui--form-field#onInvalid
29
+ ]
23
30
  }
24
31
  }
25
32
  end
@@ -5,7 +5,8 @@ import { computePosition, autoUpdate, offset, flip } from "@floating-ui/dom";
5
5
  export default class extends Controller {
6
6
  static values = {
7
7
  term: String,
8
- minPopoverWidth: { type: Number, default: 240 }
8
+ minPopoverWidth: { type: Number, default: 240 },
9
+ placement: { type: String, default: "bottom-start" }
9
10
  }
10
11
 
11
12
  static targets = [
@@ -175,7 +176,7 @@ export default class extends Controller {
175
176
  updatePopoverPosition() {
176
177
  this.cleanup = autoUpdate(this.triggerTarget, this.popoverTarget, () => {
177
178
  computePosition(this.triggerTarget, this.popoverTarget, {
178
- placement: 'bottom-start',
179
+ placement: this.placementValue,
179
180
  middleware: [offset(4), flip()],
180
181
  }).then(({ x, y }) => {
181
182
  Object.assign(this.popoverTarget.style, {
@@ -52,10 +52,7 @@ module RubyUI
52
52
  stroke_linejoin: "round"
53
53
  ) do |s|
54
54
  s.path(
55
- d: "m7 15 5 5 5-5"
56
- )
57
- s.path(
58
- d: "m7 9 5-5 5 5"
55
+ d: "m6 9 6 6 6-6"
59
56
  )
60
57
  end
61
58
  end
@@ -2,10 +2,8 @@
2
2
 
3
3
  module RubyUI
4
4
  class ContextMenuContent < Base
5
- def view_template(&block)
6
- template(data: {ruby_ui__context_menu_target: "content"}) do
7
- div(**attrs, &block)
8
- end
5
+ def view_template(&)
6
+ div(**attrs, &)
9
7
  end
10
8
 
11
9
  private
@@ -14,9 +12,10 @@ module RubyUI
14
12
  {
15
13
  role: "menu",
16
14
  aria_orientation: "vertical",
17
- data_state: "open",
15
+ data_state: "closed",
16
+ data: {ruby_ui__context_menu_target: "content"},
18
17
  class:
19
- "z-50 min-w-[8rem] outline-none pointer-events-auto overflow-hidden rounded-md border bg-background p-1 text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
18
+ "hidden absolute z-50 min-w-[8rem] outline-none pointer-events-auto overflow-hidden rounded-md border bg-background p-1 text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
20
19
  tabindex: "-1",
21
20
  data_orientation: "vertical"
22
21
  }