mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 15:35:22 +02:00
Build menu component
This commit is contained in:
parent
6af50928e6
commit
fdbfa14779
12 changed files with 247 additions and 130 deletions
|
@ -4,16 +4,19 @@ class ButtonComponent < ViewComponent::Base
|
|||
VARIANTS = {
|
||||
primary: {
|
||||
bg: "bg-gray-900 theme-dark:bg-white hover:bg-gray-800 theme-dark:hover:bg-gray-50 disabled:bg-gray-500 theme-dark:disabled:bg-gray-400",
|
||||
fg: "text-white theme-dark:text-gray-900"
|
||||
text: "text-white theme-dark:text-gray-900",
|
||||
icon: "fg-inverse"
|
||||
},
|
||||
secondary: {
|
||||
bg: "bg-gray-50 theme-dark:bg-gray-700 hover:bg-gray-100 theme-dark:hover:bg-gray-600 disabled:bg-gray-200 theme-dark:disabled:bg-gray-600",
|
||||
fg: "text-gray-900 theme-dark:text-white"
|
||||
text: "text-gray-900 theme-dark:text-white",
|
||||
icon: "fg-primary"
|
||||
},
|
||||
outline: {
|
||||
bg: "bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
fg: "text-gray-900 theme-dark:text-white",
|
||||
border: "border border-gray-900 theme-dark:border-white"
|
||||
text: "text-gray-900 theme-dark:text-white",
|
||||
border: "border border-secondary",
|
||||
icon: "fg-gray"
|
||||
},
|
||||
outline_destructive: {
|
||||
bg: "bg-transparent hover:bg-red-100 theme-dark:hover:bg-red-700",
|
||||
|
@ -22,19 +25,23 @@ class ButtonComponent < ViewComponent::Base
|
|||
},
|
||||
ghost: {
|
||||
bg: "bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
fg: "text-gray-900 theme-dark:text-white"
|
||||
text: "text-secondary",
|
||||
icon: "fg-gray"
|
||||
},
|
||||
link_color: {
|
||||
bg: "bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
fg: "text-gray-900 theme-dark:text-white"
|
||||
text: "text-primary",
|
||||
icon: "fg-inverse"
|
||||
},
|
||||
link_gray: {
|
||||
bg: "bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700",
|
||||
fg: "text-gray-900 theme-dark:text-white"
|
||||
text: "text-secondary",
|
||||
icon: "fg-gray"
|
||||
},
|
||||
icon: {
|
||||
bg: "bg-transparent hover:bg-gray-100 theme-dark:hover:bg-gray-700 rounded-lg",
|
||||
fg: "fg-gray"
|
||||
text: "text-secondary",
|
||||
icon: "fg-gray"
|
||||
}
|
||||
}.freeze
|
||||
|
||||
|
@ -46,51 +53,55 @@ class ButtonComponent < ViewComponent::Base
|
|||
icon: "w-4 h-4"
|
||||
},
|
||||
md: {
|
||||
icon_container: "w-10 h-10",
|
||||
icon_container: "w-9 h-9",
|
||||
container: "px-3 py-2 rounded-lg",
|
||||
text: "text-sm",
|
||||
icon: "w-5 h-5"
|
||||
},
|
||||
lg: {
|
||||
icon_container: "w-12 h-12",
|
||||
icon_container: "w-10 h-10",
|
||||
container: "px-4 py-3 rounded-xl",
|
||||
text: "text-base",
|
||||
icon: "w-6 h-6"
|
||||
}
|
||||
}
|
||||
|
||||
def initialize(text:, variant: "primary", size: "md", href: nil, leading_icon: nil, trailing_icon: nil, icon: nil, **options)
|
||||
@text = text
|
||||
@variant = variant.underscore.to_sym
|
||||
@size = size.to_sym
|
||||
@href = href
|
||||
@leading_icon = leading_icon
|
||||
@trailing_icon = trailing_icon
|
||||
@icon = icon
|
||||
def initialize(options = {})
|
||||
@text = options.delete(:text)
|
||||
@variant = (options.delete(:variant) || "primary").underscore.to_sym
|
||||
@size = (options.delete(:size) || :md).to_sym
|
||||
@href = options.delete(:href)
|
||||
@method = options.delete(:method)
|
||||
@leading_icon = options.delete(:leading_icon)
|
||||
@trailing_icon = options.delete(:trailing_icon)
|
||||
@icon = options.delete(:icon)
|
||||
@full_width = options.delete(:full_width)
|
||||
@left_align = options.delete(:left_align)
|
||||
@extra_classes = options.delete(:class)
|
||||
@options = options
|
||||
end
|
||||
|
||||
def wrapper_tag(&block)
|
||||
html_tag = @href ? "a" : "button"
|
||||
|
||||
if @href.present?
|
||||
content_tag(html_tag, class: container_classes, href: @href, **@options, &block)
|
||||
if @href && @method
|
||||
button_to @href, class: container_classes, method: @method, **@options, &block
|
||||
else
|
||||
content_tag(html_tag, class: container_classes, **@options, &block)
|
||||
html_tag = @href ? "a" : "button"
|
||||
content_tag(html_tag, class: container_classes, href: @href, **@options, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def text_classes
|
||||
[
|
||||
"font-medium",
|
||||
size_meta[:text],
|
||||
variant_meta[:fg]
|
||||
variant_meta[:text]
|
||||
].join(" ")
|
||||
end
|
||||
|
||||
def icon_classes
|
||||
[
|
||||
size_meta[:icon],
|
||||
variant_meta[:fg]
|
||||
variant_meta[:icon]
|
||||
].join(" ")
|
||||
end
|
||||
|
||||
|
@ -101,10 +112,14 @@ class ButtonComponent < ViewComponent::Base
|
|||
private
|
||||
def container_classes
|
||||
[
|
||||
"inline-flex items-center justify-center gap-1",
|
||||
"inline-flex items-center gap-1",
|
||||
@full_width ? "w-full" : nil,
|
||||
@left_align ? "justify-start" : "justify-center",
|
||||
@variant == :icon ? size_meta[:icon_container] : size_meta[:container],
|
||||
variant_meta[:bg]
|
||||
].join(" ")
|
||||
variant_meta[:bg],
|
||||
variant_meta.dig(:border),
|
||||
@extra_classes
|
||||
].compact.join(" ")
|
||||
end
|
||||
|
||||
def size_meta
|
||||
|
|
|
@ -11,6 +11,10 @@ class IconComponent < ViewComponent::Base
|
|||
default: {
|
||||
icon: "fg-gray",
|
||||
container: "bg-transparent"
|
||||
},
|
||||
destructive: {
|
||||
icon: "text-destructive",
|
||||
container: "bg-transparent"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,12 +49,16 @@ class IconComponent < ViewComponent::Base
|
|||
def container_classes
|
||||
[
|
||||
"flex justify-center items-center",
|
||||
size_meta[:container],
|
||||
show_padding? ? size_meta[:container] : "",
|
||||
variant_meta[:container]
|
||||
].join(" ")
|
||||
end
|
||||
|
||||
private
|
||||
def show_padding?
|
||||
@variant != :default && @variant != :destructive
|
||||
end
|
||||
|
||||
def variant_meta
|
||||
VARIANTS[@variant]
|
||||
end
|
||||
|
|
13
app/components/menu_component.html.erb
Normal file
13
app/components/menu_component.html.erb
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div data-controller="menu">
|
||||
<% if @variant == :icon %>
|
||||
<%= render ButtonComponent.new(variant: "icon", icon: "more-horizontal", data: { menu_target: "button" }) %>
|
||||
<% elsif @variant == :button %>
|
||||
<%= button %>
|
||||
<% end %>
|
||||
|
||||
<div data-menu-target="content" class="hidden min-w-[200px] p-1 z-50 shadow-border-xs bg-container rounded-lg">
|
||||
<% items.each do |item| %>
|
||||
<%= item %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
19
app/components/menu_component.rb
Normal file
19
app/components/menu_component.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MenuComponent < ViewComponent::Base
|
||||
renders_one :button, ->(**options) do
|
||||
options_with_target = options.merge(data: { menu_target: "button" })
|
||||
ButtonComponent.new(**options_with_target)
|
||||
end
|
||||
|
||||
renders_many :items, MenuItemComponent
|
||||
|
||||
VARIANTS = {
|
||||
icon: {},
|
||||
button: {}
|
||||
}
|
||||
|
||||
def initialize(variant: "icon")
|
||||
@variant = variant.to_sym
|
||||
end
|
||||
end
|
50
app/components/menu_item_component.rb
Normal file
50
app/components/menu_item_component.rb
Normal file
|
@ -0,0 +1,50 @@
|
|||
class MenuItemComponent < ViewComponent::Base
|
||||
erb_template <<~ERB
|
||||
<%= wrapper do %>
|
||||
<%= render IconComponent.new(@icon, variant: destructive? ? "destructive" : "default") %>
|
||||
<%= tag.span(@text, class: text_classes) %>
|
||||
<% end %>
|
||||
ERB
|
||||
|
||||
VARIANTS = {
|
||||
link: {},
|
||||
action: {}
|
||||
}
|
||||
|
||||
def initialize(text:, href:, variant: "link", method: :post, icon: nil, data: {})
|
||||
@text = text
|
||||
@icon = icon
|
||||
@href = href
|
||||
@variant = variant.to_sym
|
||||
@method = method
|
||||
@data = data
|
||||
end
|
||||
|
||||
def wrapper(&block)
|
||||
case @variant
|
||||
when :link
|
||||
link_to @href, data: @data, class: container_classes, &block
|
||||
when :action
|
||||
button_to @href, method: @method, data: @data, class: container_classes, &block
|
||||
end
|
||||
end
|
||||
|
||||
def text_classes
|
||||
[
|
||||
"text-sm",
|
||||
destructive? ? "text-destructive" : "text-primary"
|
||||
].join(" ")
|
||||
end
|
||||
|
||||
def destructive?
|
||||
@method == :delete
|
||||
end
|
||||
|
||||
private
|
||||
def container_classes
|
||||
[
|
||||
"flex items-center gap-2 p-2 rounded-md w-full",
|
||||
destructive? ? "hover:bg-red-tint-5 theme-dark:hover:bg-red-tint-10" : "hover:bg-container-hover"
|
||||
].join(" ")
|
||||
end
|
||||
end
|
|
@ -49,14 +49,14 @@ class StyledFormBuilder < ActionView::Helpers::FormBuilder
|
|||
end
|
||||
|
||||
def submit(value = nil, options = {})
|
||||
default_options = {
|
||||
data: { turbo_submits_with: "Submitting..." },
|
||||
class: "btn btn--primary w-full justify-center"
|
||||
}
|
||||
|
||||
merged_options = default_options.merge(options)
|
||||
# Rails superclass logic to extract the submit text
|
||||
value, options = nil, value if value.is_a?(Hash)
|
||||
super(value, merged_options)
|
||||
value ||= submit_default_value
|
||||
|
||||
opts = options.dup
|
||||
opts[:data] = { turbo_submits_with: "Submitting..." }.merge(opts[:data] || {})
|
||||
|
||||
@template.render(ButtonComponent.new(text: value, **opts))
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -42,12 +42,15 @@
|
|||
</div>
|
||||
|
||||
<div data-tabs-target="tab" id="assets-tab">
|
||||
<%= link_to new_account_path(step: "method_select", classification: "asset"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New asset</span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "New asset",
|
||||
variant: "ghost",
|
||||
full_width: true,
|
||||
left_align: true,
|
||||
href: new_account_path(step: "method_select", classification: "asset"),
|
||||
leading_icon: "plus",
|
||||
data: { turbo_frame: "modal" }
|
||||
) %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<% family.balance_sheet.account_groups("asset").each do |group| %>
|
||||
|
@ -57,12 +60,15 @@
|
|||
</div>
|
||||
|
||||
<div data-tabs-target="tab" id="debts-tab" class="hidden">
|
||||
<%= link_to new_account_path(step: "method_select", classification: "liability"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New debt</span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "New debt",
|
||||
variant: "ghost",
|
||||
full_width: true,
|
||||
left_align: true,
|
||||
href: new_account_path(step: "method_select", classification: "liability"),
|
||||
leading_icon: "plus",
|
||||
data: { turbo_frame: "modal" }
|
||||
) %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<% family.balance_sheet.account_groups("liability").each do |group| %>
|
||||
|
@ -72,12 +78,15 @@
|
|||
</div>
|
||||
|
||||
<div data-tabs-target="tab" id="all-tab" class="hidden">
|
||||
<%= link_to new_account_path(step: "method_select"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New account</span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "New account",
|
||||
variant: "ghost",
|
||||
full_width: true,
|
||||
left_align: true,
|
||||
href: new_account_path(step: "method_select"),
|
||||
leading_icon: "plus",
|
||||
data: { turbo_frame: "modal" }
|
||||
) %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<% family.balance_sheet.account_groups.each do |group| %>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<div class="space-y-1">
|
||||
<% account_group.accounts.each do |account| %>
|
||||
<%= link_to account_path(account), class: "block flex items-center gap-2 btn btn--ghost", title: account.name do %>
|
||||
<%= link_to account_path(account), class: "block flex items-center gap-2 px-3 py-2 hover:bg-surface-hover", title: account.name do %>
|
||||
<%= render "accounts/logo", account: account, size: "sm", color: account_group.color %>
|
||||
|
||||
<div class="min-w-0 grow">
|
||||
|
@ -40,10 +40,13 @@
|
|||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= link_to new_polymorphic_path(account_group.key, step: "method_select"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New <%= account_group.name.downcase.singularize %></span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
href: new_polymorphic_path(account_group.key, step: "method_select"),
|
||||
text: "New #{account_group.name.downcase.singularize}",
|
||||
leading_icon: "plus",
|
||||
left_align: true,
|
||||
full_width: true,
|
||||
variant: "ghost",
|
||||
data: { turbo_frame: "modal" }
|
||||
) %>
|
||||
</details>
|
||||
|
|
|
@ -2,23 +2,22 @@
|
|||
<h1 class="text-xl"><%= t(".accounts") %></h1>
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center gap-2">
|
||||
<%= button_to sync_all_accounts_path,
|
||||
disabled: Current.family.syncing?,
|
||||
class: "md:btn md:btn--outline flex items-center justify-center gap-2 w-9 h-9 md:w-auto md:h-auto rounded-full md:rounded-lg",
|
||||
title: t(".sync") do %>
|
||||
<%= lucide_icon "refresh-cw", class: "w-5 h-5" %>
|
||||
<span class="hidden md:inline"><%= t(".sync") %></span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "Sync all",
|
||||
href: sync_all_accounts_path,
|
||||
method: :post,
|
||||
variant: "outline",
|
||||
disabled: Current.family.syncing?,
|
||||
leading_icon: "refresh-cw"
|
||||
) %>
|
||||
|
||||
<%= link_to new_account_path(return_to: accounts_path),
|
||||
data: { turbo_frame: "modal" },
|
||||
class: "btn btn--primary flex items-center justify-center gap-1 w-9 h-9 md:w-auto md:h-auto rounded-full md:rounded-lg" do %>
|
||||
<div class="flex items-center justify-center w-5 h-5">
|
||||
|
||||
<%= lucide_icon("plus") %>
|
||||
</div>
|
||||
<p class="hidden md:block text-sm font-medium"><%= t(".new_account") %></p>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "New account",
|
||||
href: new_account_path(return_to: accounts_path),
|
||||
variant: "primary",
|
||||
leading_icon: "plus",
|
||||
data: { turbo_frame: "modal" }
|
||||
) %>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -6,21 +6,23 @@
|
|||
<%= tag.h2 t(".title"), class: "font-medium text-lg" %>
|
||||
<% unless @account.plaid_account_id.present? %>
|
||||
<div data-controller="menu" data-testid="activity-menu">
|
||||
<button class="btn btn--secondary flex items-center gap-2" data-menu-target="button">
|
||||
<%= lucide_icon("plus", class: "w-4 h-4") %>
|
||||
<%= tag.span t(".new") %>
|
||||
</button>
|
||||
<%= render ButtonComponent.new(text: "New", variant: "secondary", leading_icon: "plus", data: { menu_target: "button" }) %>
|
||||
|
||||
<div data-menu-target="content" class="z-10 hidden bg-container rounded-lg border border-alpha-black-25 shadow-xs p-1">
|
||||
<%= link_to new_valuation_path(account_id: @account.id), data: { turbo_frame: :modal }, class: "block p-2 rounded-lg hover:bg-gray-50 flex items-center gap-2" do %>
|
||||
<%= lucide_icon("circle-dollar-sign", class: "text-secondary w-5 h-5") %>
|
||||
<%= tag.span t(".new_balance"), class: "text-sm" %>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "New balance",
|
||||
variant: "ghost",
|
||||
full_width: true,
|
||||
left_align: true,
|
||||
leading_icon: "circle-dollar-sign",
|
||||
href: new_valuation_path(account_id: @account.id),
|
||||
data: { turbo_frame: :modal }) %>
|
||||
|
||||
<% unless @account.crypto? %>
|
||||
<%= link_to @account.investment? ? new_trade_path(account_id: @account.id) : new_transaction_path(account_id: @account.id), data: { turbo_frame: :modal }, class: "btn btn--primary flex items-center justify-center gap-2 rounded-full md:rounded-lg w-9 h-9 md:w-auto md:h-auto" do %>
|
||||
<span class="flex items-center justify-center">
|
||||
<%= lucide_icon("credit-card", class: "text-secondary w-5 h-5") %>
|
||||
</span>
|
||||
<span class="flex items-center justify-center">
|
||||
<%= lucide_icon("credit-card", class: "text-secondary w-5 h-5") %>
|
||||
</span>
|
||||
<%= tag.span t(".new_transaction"), class: "text-sm md:block" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,47 +1,27 @@
|
|||
<%# locals: (account:) %>
|
||||
|
||||
<%= contextual_menu do %>
|
||||
<div class="w-48 p-1 text-sm leading-6 text-primary bg-container shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<% if account.plaid_account_id.present? %>
|
||||
<%= link_to accounts_path,
|
||||
data: { turbo_frame: :_top },
|
||||
class: "block w-full py-2 px-3 space-x-2 text-primary hover:bg-gray-50 flex items-center rounded-lg" do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-5 h-5 text-secondary" %>
|
||||
<%= render MenuComponent.new do |menu| %>
|
||||
<% menu.with_item(text: "Edit", href: edit_account_path(account), icon: "pencil-line", data: { turbo_frame: :modal })%>
|
||||
|
||||
<span><%= t(".manage") %></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= link_to edit_account_path(account),
|
||||
data: { turbo_frame: :modal },
|
||||
class: "block w-full py-2 px-3 space-x-2 text-primary hover:bg-gray-50 flex items-center rounded-lg" do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-5 h-5 text-secondary" %>
|
||||
<% unless account.crypto? %>
|
||||
<% menu.with_item(
|
||||
text: "Import transactions",
|
||||
href: imports_path({ import: { type: account.investment? ? "TradeImport" : "TransactionImport", account_id: account.id } }),
|
||||
icon: "download",
|
||||
data: { turbo_frame: :_top }
|
||||
) %>
|
||||
<% end %>
|
||||
|
||||
<span><%= t(".edit") %></span>
|
||||
<% end %>
|
||||
|
||||
<% unless account.crypto? %>
|
||||
<%= button_to imports_path({ import: { type: account.investment? ? "TradeImport" : "TransactionImport", account_id: account.id } }),
|
||||
data: { turbo_frame: :_top },
|
||||
class: "block w-full py-2 px-3 space-x-2 text-primary hover:bg-gray-50 flex items-center rounded-lg" do %>
|
||||
<%= lucide_icon "download", class: "w-5 h-5 text-secondary" %>
|
||||
|
||||
<span><%= t(".import") %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= button_to account_path(account),
|
||||
method: :delete,
|
||||
class: "block w-full py-2 px-3 space-x-2 text-red-600 hover:bg-red-50 flex items-center rounded-lg",
|
||||
data: {
|
||||
turbo_frame: :_top,
|
||||
turbo_confirm: {
|
||||
title: t(".confirm_title"),
|
||||
body: t(".confirm_body_html"),
|
||||
accept: t(".confirm_accept", name: account.name)
|
||||
}
|
||||
} do %>
|
||||
<%= lucide_icon("trash-2", class: "w-5 h-5 mr-2") %> Delete account
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% menu.with_item(
|
||||
text: "Delete account",
|
||||
href: account_path(account),
|
||||
method: :delete,
|
||||
icon: "trash-2",
|
||||
variant: "action",
|
||||
data: { turbo_frame: :_top, turbo_confirm: {
|
||||
title: t(".confirm_title"),
|
||||
body: t(".confirm_body_html"),
|
||||
accept: t(".confirm_accept", name: account.name)
|
||||
}}
|
||||
)%>
|
||||
<% end %>
|
||||
|
|
19
test/components/previews/menu_component_preview.rb
Normal file
19
test/components/previews/menu_component_preview.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
class MenuComponentPreview < ViewComponent::Preview
|
||||
# @param variant select {{ MenuComponent::VARIANTS.keys }}
|
||||
def default(variant: "icon")
|
||||
if variant == "icon"
|
||||
render MenuComponent.new(variant: variant) do |menu|
|
||||
menu.with_item(text: "Menu item 1", href: "#", icon: "plus")
|
||||
menu.with_item(text: "Menu item 2", href: "#", icon: "circle")
|
||||
menu.with_item(text: "Destructive", href: "#", method: :delete, icon: "circle")
|
||||
end
|
||||
else
|
||||
render MenuComponent.new(variant: variant) do |menu|
|
||||
menu.with_button(text: "New", icon: "plus")
|
||||
menu.with_item(text: "Menu item 1", href: "#", icon: "plus")
|
||||
menu.with_item(text: "Menu item 2", href: "#", icon: "circle")
|
||||
menu.with_item(text: "Destructive", href: "#", method: :delete, icon: "circle")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue