Popover
UI::PopoverFloating content anchored to a trigger.
# VelvetKit
## Popover (`UI::Popover`)
Floating content anchored to a trigger.
Add it: `bin/rails generate velvetkit:add popover`
Also adds: `icon`, `spinner`, `button`
Stimulus: `ui--popover`
Installs: `@floating-ui/dom`
### Arguments
```ruby
UI::Popover.new(class: nil, **html_attrs)
```
Slots: `with_trigger`, `with_popover_content`, `with_content`, `with_title`
### Example: Default
```erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger(variant: :default) { "Open Popover" } %>
<% popover.with_content do |content| %>
<% content.with_title { "Popover Title" } %>
<p>This is a simple popover with a title and some content.</p>
<% end %>
<% end %>
```
### Example: Positions
```erb
<div class="flex flex-wrap gap-8 p-8 items-center justify-center">
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Top" } %>
<% popover.with_content(side: :top) do |content| %>
<% content.with_title { "Top Position" } %>
This popover appears above the trigger.
<% end %>
<% end %>
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Right" } %>
<% popover.with_content(side: :right) do |content| %>
<% content.with_title { "Right Position" } %>
This popover appears to the right.
<% end %>
<% end %>
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Bottom" } %>
<% popover.with_content(side: :bottom) do |content| %>
<% content.with_title { "Bottom Position" } %>
This popover appears below the trigger.
<% end %>
<% end %>
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Left" } %>
<% popover.with_content(side: :left) do |content| %>
<% content.with_title { "Left Position" } %>
This popover appears to the left.
<% end %>
<% end %>
</div>
```
### Example: With Close Button
```erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Open Popover" } %>
<% popover.with_content(show_close: true) do |content| %>
<% content.with_title { "With Close Button" } %>
<p>This popover has a close button in the top-right corner.</p>
<p>You can also close it by clicking outside, pressing Escape, or tabbing away.</p>
<% end %>
<% end %>
```
### Example: With Rich Content
```erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Open Rich Popover" } %>
<% popover.with_content(show_close: true) do |content| %>
<% content.with_title { "User Profile" } %>
<div class="flex items-center gap-3 mb-3">
<%= render(UI::Avatar.new(src: nil, fallback: "JD")) %>
<div>
<p class="font-medium">John Doe</p>
<p class="text-sm text-muted-foreground">john@example.com</p>
</div>
</div>
<div class="flex gap-2">
<%= render(UI::Button.new(size: :sm)) { "View Profile" } %>
<%= render(UI::Button.new(variant: :outline, size: :sm)) { "Settings" } %>
</div>
<% end %>
<% end %>
```
### Example: Without Title
```erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Open Popover" } %>
<% popover.with_content do %>
<p>This popover has no title, just content. Perfect for simple messages or actions.</p>
<div class="mt-2">
<%= render(UI::Button.new(size: :sm)) { "Take Action" } %>
</div>
<% end %>
<% end %>
```
bin/rails generate velvetkit:add popover
- Stimulus
- ui--popover
- Installs
- @floating-ui/dom
Examples
Default
default.html.erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger(variant: :default) { "Open Popover" } %>
<% popover.with_content do |content| %>
<% content.with_title { "Popover Title" } %>
<p>This is a simple popover with a title and some content.</p>
<% end %>
<% end %>
Positions
positions.html.erb
<div class="flex flex-wrap gap-8 p-8 items-center justify-center">
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Top" } %>
<% popover.with_content(side: :top) do |content| %>
<% content.with_title { "Top Position" } %>
This popover appears above the trigger.
<% end %>
<% end %>
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Right" } %>
<% popover.with_content(side: :right) do |content| %>
<% content.with_title { "Right Position" } %>
This popover appears to the right.
<% end %>
<% end %>
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Bottom" } %>
<% popover.with_content(side: :bottom) do |content| %>
<% content.with_title { "Bottom Position" } %>
This popover appears below the trigger.
<% end %>
<% end %>
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Left" } %>
<% popover.with_content(side: :left) do |content| %>
<% content.with_title { "Left Position" } %>
This popover appears to the left.
<% end %>
<% end %>
</div>
With Close Button
with_close_button.html.erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Open Popover" } %>
<% popover.with_content(show_close: true) do |content| %>
<% content.with_title { "With Close Button" } %>
<p>This popover has a close button in the top-right corner.</p>
<p>You can also close it by clicking outside, pressing Escape, or tabbing away.</p>
<% end %>
<% end %>
With Rich Content
with_rich_content.html.erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Open Rich Popover" } %>
<% popover.with_content(show_close: true) do |content| %>
<% content.with_title { "User Profile" } %>
<div class="flex items-center gap-3 mb-3">
<%= render(UI::Avatar.new(src: nil, fallback: "JD")) %>
<div>
<p class="font-medium">John Doe</p>
<p class="text-sm text-muted-foreground">john@example.com</p>
</div>
</div>
<div class="flex gap-2">
<%= render(UI::Button.new(size: :sm)) { "View Profile" } %>
<%= render(UI::Button.new(variant: :outline, size: :sm)) { "Settings" } %>
</div>
<% end %>
<% end %>
Without Title
without_title.html.erb
<%= render(UI::Popover.new) do |popover| %>
<% popover.with_trigger { "Open Popover" } %>
<% popover.with_content do %>
<p>This popover has no title, just content. Perfect for simple messages or actions.</p>
<div class="mt-2">
<%= render(UI::Button.new(size: :sm)) { "Take Action" } %>
</div>
<% end %>
<% end %>
API
Arguments
UI::Popover.new(class: nil, **html_attrs)
Slots:
with_trigger
with_popover_content
with_content
with_title