# frozen_string_literal: true
module Ariadne
# `DropdownComponent` is a lightweight context menu for holding navigation and actions.
class DropdownComponent < Ariadne::Component
DEFAULT_TAG = :div
TAG_OPTIONS = [DEFAULT_TAG].freeze
DEFAULT_CLASSES = ""
# Required trigger for the dropdown. Has the same arguments as <%= link_to_component(Ariadne::ButtonComponent) %>,
# but it is locked as a `summary` tag.
#
# @param size [Symbol] <%= one_of(Ariadne::BaseButton::VALID_SIZES) %>
# @param type [Symbol] <%= one_of(Ariadne::BaseButton::VALID_TYPES) %>
# @param scheme [Symbol] <%= one_of(Ariadne::ButtonComponent::VALID_SCHEMES) %>
# @param classes [String] <%= link_to_classes_docs %>
# @param attributes [Hash] <%= link_to_attributes_docs %>
renders_one :button, lambda { |size: Ariadne::BaseButton::DEFAULT_SIZE, scheme: :none, classes: "", attributes: {}|
@button_classes = classes
@button_attributes = attributes
@button_attributes[:button] = true
Ariadne::ButtonComponent.new(tag: :summary, type: :button, scheme: scheme, dropdown: @with_caret, size: size, classes: classes, attributes: attributes)
}
# Required context menu for the dropdown.
#
# @param as [Symbol] When `as` is `:list`, wraps the menu in a `
` with a `- ` for each item.
# @param direction [Symbol] <%= one_of(Ariadne::Dropdown::MenuComponent::VALID_DIRECTIONS) %>
# @param header [String] Optional string to display as the header
# @param classes [String] <%= link_to_classes_docs %>
# @param attributes [Hash] <%= link_to_attributes_docs %>
renders_one :menu, "Ariadne::Dropdown::MenuComponent"
# TODO: remove *Item suffix from nested classes
# @example Default
# <%= render(Ariadne::DropdownComponent.new) do |c| %>
# <% c.with_button do %>
# Dropdown
# <% end %>
#
# <% c.with_menu do |menu| %>
# <% menu.with_header { "Header" } %>
# <% menu.with_item { "Item 1" } %>
# <% menu.with_item { "Item 2" } %>
# <% menu.with_item { "Item 3" } %>
# <% end %>
# <% end %>
#
# @example With dividers
#
# @description
# Dividers can be used to separate a group of items. They don't have any content.
# @code
# <%= render(Ariadne::DropdownComponent.new) do |c| %>
# <% c.with_button do %>
# Dropdown
# <% end %>
#
# <% c.with_menu do |menu| %>
# <% menu.with_header { "Header" } %>
# <%= menu.with_item { "Item 1" } %>
# <%= menu.with_item { "Item 2" } %>
# <%= menu.with_item(divider: true) %>
# <%= menu.with_item { "Item 3" } %>
# <%= menu.with_item { "Item 4" } %>
# <%= menu.with_item(divider: true) %>
# <%= menu.with_item { "Item 5" } %>
# <%= menu.with_item { "Item 6" } %>
# <% end %>
# <% end %>
#
# @example With direction
# <%= render(Ariadne::DropdownComponent.new) do |c| %>
# <% c.with_button do %>
# Dropdown
# <% end %>
#
# <% c.with_menu(direction: :s) do |menu| %>
# <% menu.header { "Header" } %>
# <%= menu.with_item { "Item 1" } %>
# <%= menu.with_item { "Item 2" } %>
# <%= menu.with_item { "Item 3" } %>
# <%= menu.with_item { "Item 4" } %>
# <% end %>
# <% end %>
#
# @example With caret
# <%= render(Ariadne::DropdownComponent.new(with_caret: true)) do |c| %>
# <% c.with_button do %>
# Dropdown
# <% end %>
#
# <% c.with_menu do |menu| %>
# <% menu.with_header { "Header" } %>
# <%= menu.with_item { "Item 1" } %>
# <%= menu.with_item { "Item 2" } %>
# <%= menu.with_item { "Item 3" } %>
# <%= menu.with_item { "Item 4" } %>
# <% end %>
# <% end %>
#
# @example Customizing the button
# <%= render(Ariadne::DropdownComponent.new) do |c| %>
# <% c.with_button(scheme: :info, size: :sm) do %>
# Dropdown
# <% end %>
#
# <% c.with_menu do |menu| %>
# <% menu.with_header { "Header" } %>
# <%= menu.with_item { "Item 1" } %>
# <%= menu.with_item { "Item 2" } %>
# <%= menu.with_item { "Item 3" } %>
# <%= menu.with_item { "Item 4" } %>
# <% end %>
# <% end %>
#
# @example Menu as list
# <%= render(Ariadne::DropdownComponent.new) do |c| %>
# <% c.with_button do %>
# Dropdown
# <% end %>
#
# <% c.with_menu(as: :list) do |menu| %>
# <% menu.with_header { "Header" } %>
# <% menu.with_item { "Item 1" } %>
# <% menu.with_item { "Item 2" } %>
# <% menu.with_item(divider: true) %>
# <% menu.with_item { "Item 3" } %>
# <% menu.with_item { "Item 4" } %>
# <% end %>
# <% end %>
#
# @example Customizing menu items
# <%= render(Ariadne::DropdownComponent.new) do |c| %>
# <% c.with_button do %>
# Dropdown
# <% end %>
#
# <% c.with_menu do |menu| %>
# <% menu.with_header { "Header" } %>
# <% menu.with_item(tag: :button) { "Item 1" } %>
# <% menu.with_item(classes: "ariadne-text-red-500") { "Item 2" } %>
# <% menu.with_item { "Item 3" } %>
# <% end %>
# <% end %>
#
# @param overlay [Symbol] <%= one_of(Ariadne::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
# @param with_caret [Boolean] Whether or not a caret should be rendered in the button.
# @param classes [String] <%= link_to_classes_docs %>
# @param attributes [Hash] <%= link_to_attributes_docs %>
def initialize(overlay: :default, with_caret: false, classes: "", attributes: {})
@tag = check_incoming_tag(DEFAULT_TAG, tag)
@classes = merge_class_names(
DEFAULT_CLASSES,
classes,
)
@attributes = attributes
@with_caret = with_caret
@overlay = overlay
@attributes[:reset] = true
end
def render?
button.present? && menu.present?
end
end
end