Class: Primer::Alpha::ActionMenu

Inherits:
Component
  • Object
show all
Defined in:
app/components/primer/alpha/action_menu.rb,
app/components/primer/alpha/action_menu/list.rb,
app/components/primer/alpha/action_menu/menu.rb,
app/components/primer/alpha/action_menu/group.rb,
app/components/primer/alpha/action_menu/heading.rb,
app/components/primer/alpha/action_menu/sub_menu.rb,
app/components/primer/alpha/action_menu/list_wrapper.rb,
app/components/primer/alpha/action_menu/primary_menu.rb,
app/components/primer/alpha/action_menu/sub_menu_item.rb

Overview

ActionMenu is used for actions, navigation, to display secondary options, or single/multi select lists. They appear when users interact with buttons, actions, or other controls.

The only allowed elements for the Item components are: :a, :button, and :clipboard-copy. The default is :button.

### Select variants

While ‘ActionMenu`s default to a list of buttons that can link to other pages, copy text to the clipboard, etc, they also support single and multiple select variants. The single select variant allows a single item to be “selected” (i.e. marked “active”) when clicked, which will cause a check mark to appear to the left of the item text. When the multiple select variant is chosen, multiple items may be selected and check marks will appear next to each selected item.

Use the select_variant: option to control which variant the ActionMenu uses. For more information, see the documentation on supported arguments below.

### Dynamic labels

When using the single select variant, an optional label indicating the selected item can be displayed inside the menu button. Dynamic labels can also be prefixed with custom text.

Pass ‘dynamic_label: true` to enable dynamic label behavior, and pass `dynamic_label_prefix: “<string>”` to set a custom prefix. For more information, see the documentation on supported arguments below.

### ‘ActionMenu`s as form inputs

When using either the single or multiple select variants, ‘ActionMenu`s can be used as form inputs. They behave very similarly to how HTML `<select>` boxes behave, and play nicely with Rails’ built-in form mechanisms. Pass arguments via the form_arguments: argument, including the Rails form builder object and the name of the field:

“‘erb <% form_with(url: update_merge_strategy_path) do |f| %>

<%= render(Primer::Alpha::ActionMenu.new(form_arguments: { builder: f, name: "merge_strategy" })) do |menu| %>
  <% menu.with_item(label: "Fast forward", data: { value: "fast_forward" }) %>
  <% menu.with_item(label: "Recursive", data: { value: "recursive" }) %>
  <% menu.with_item(label: "Ours", data: { value: "ours" }) %>
  <% menu.with_item(label: "Theirs", data: { value: "theirs" }) %>
<% end %>

<% end %> “‘

The value of the ‘data: { value: … }` argument is sent to the server on submit, keyed using the name provided above (eg. `“merge_strategy”`). If no value is provided for an item, the value of that item is the item’s label. Here’s the corresponding MergeStrategyController that might be written to handle the form above:

“‘ruby class MergeStrategyController < ApplicationController

def update
  puts "You chose #{merge_strategy_params[:merge_strategy]}"
end

private

def merge_strategy_params
  params.permit(:merge_strategy)
end

end “‘

### ActionMenu items that submit forms

Whereas ActionMenu items normally permit navigation via ‘<a>` tags which make HTTP get requests, ActionMenu items also permit navigation via POST requests. To enable this behavior, include the href: argument as normal, but also pass the form_arguments: argument to the appropriate item:

“‘erb <%= render(Primer::Alpha::ActionMenu.new) do |menu| %>

<% menu.with_item(
  label: "Repository",
  href: update_repo_grouping_path,
  form_arguments: {
    method: :post,
    name: "group_by",
    value: "repository"
  }
) %>

<% end %> “‘

Make sure to specify ‘method: :post`, as the default is :get. When clicked, the list item will submit a POST request to the URL passed in the href: argument, including a parameter named `“group_by”` with a value of `“repository”`. If no value is given, the name, eg. `“group_by”`, will be used as the value.

It is possible to include multiple fields on submit. Instead of passing the name: and value: arguments, pass an array via the inputs: argument:

“‘erb <%= render(Primer::Alpha::ActionMenu.new) do |menu| %>

<% menu.with_show_button { "Group By" } %>
<% menu.with_item(
  label: "Repository",
  href: update_repo_grouping_path,
  form_arguments: {
    method: :post,
    inputs: [{
      name: "group_by",
      value: "repository"
    }, {
      name: "some_other_field",
      value: "some value",
    }],
  }
) %>

<% end %> “‘

### Form arguments

The following table summarizes the arguments allowed in the form_arguments: hash mentioned above.

|Name |Type |Default|Description| |:—————-|:————-|:——|:———-| |method |Symbol |:get |The HTTP request method to use to submit the form. One of :get, :post, :patch, :put, :delete, or :head| |name |String |nil |The name of the field that will be sent to the server on submit.| |value |String |nil |The value of the field that will be sent to the server on submit.| |input_arguments|Hash |‘{}` |Additional key/value pairs to emit as HTML attributes on the `<input type=“hidden”>` element.| |inputs |`Array<Hash>` |[] |An array of hashes representing HTML `<input type=“hidden”>` elements. Must contain at least name: and value: keys. If additional key/value pairs are provided, they are emitted as HTML attributes on the `<input>` element. This argument supercedes the name:, value:, and :input_arguments arguments listed above.|

The elements of the inputs: array will be emitted as HTML ‘<input type=“hidden”>` elements.

### JavaScript API

‘ActionMenu`s render an `<action-menu>` custom element that exposes behavior to the client.

#### Query methods

  • ‘getItemById(itemId: string): Element`: Returns the item’s HTML ‘<li>` element. The return value can be passed as the item argument to the other methods listed below.

  • ‘isItemChecked(item: Element): boolean`: Returns true if the item is checked, false otherwise.

  • ‘isItemHidden(item: Element): boolean`: Returns true if the item is hidden, false otherwise.

  • ‘isItemDisabled(item: Element): boolean`: Returns true if the item is disabled, false otherwise.

NOTE: Item IDs are special values provided by the user that are attached to ActionMenu items as the data-item-id HTML attribute. Item IDs can be provided by passing an item_id: attribute when adding items to the list, eg:

“‘erb <%= render(Primer::Alpha::ActionMenu.new) do |menu| %>

<% menu.with_item(item_id: "my-id") %>

<% end %> “‘

#### State methods

  • ‘showItem(item: Element)`: Shows the item, i.e. makes it visible.

  • ‘hideItem(item: Element)`: Hides the item, i.e. makes it invisible.

  • ‘enableItem(item: Element)`: Enables the item, i.e. makes it clickable by the mouse and keyboard.

  • ‘disableItem(item: Element)`: Disables the item, i.e. makes it unclickable by the mouse and keyboard.

  • ‘checkItem(item: Element)`: Checks the item. Only has an effect in single- and multi-select modes.

  • ‘uncheckItem(item: Element)`: Unchecks the item. Only has an effect in multi-select mode, since items cannot be unchecked in single-select mode.

#### Events

The ‘<action-menu>` element fires an itemActivated event whenever an item is activated (eg. clicked) via the mouse or keyboard.

“‘typescript document.querySelector(“action-menu”).addEventListener(“itemActivated”, (event: CustomEvent<ItemActivatedEvent>) =>

event.detail.item     // Element: the <li> item that was activated
event.detail.checked  // boolean: whether or not the result of the activation checked the item

) “‘

Defined Under Namespace

Classes: Group, Heading, List, ListWrapper, Menu, PrimaryMenu, SubMenu, SubMenuItem

Constant Summary

Constants inherited from Component

Component::INVALID_ARIA_LABEL_TAGS

Constants included from Status::Dsl

Status::Dsl::STATUSES

Constants included from ViewHelper

ViewHelper::HELPERS

Constants included from TestSelectorHelper

TestSelectorHelper::TEST_SELECTOR_TAG

Constants included from FetchOrFallbackHelper

FetchOrFallbackHelper::InvalidValueError

Constants included from Primer::AttributesHelper

Primer::AttributesHelper::PLURAL_ARIA_ATTRIBUTES, Primer::AttributesHelper::PLURAL_DATA_ATTRIBUTES

Instance Method Summary collapse

Methods inherited from Component

deprecated?, generate_id

Methods included from JoinStyleArgumentsHelper

#join_style_arguments

Methods included from TestSelectorHelper

#add_test_selector

Methods included from FetchOrFallbackHelper

#fetch_or_fallback, #fetch_or_fallback_boolean, #silence_deprecations?

Methods included from ClassNameHelper

#class_names

Methods included from Primer::AttributesHelper

#aria, #data, #extract_data, #merge_aria, #merge_data, #merge_prefixed_attribute_hashes

Methods included from ExperimentalSlotHelpers

included

Methods included from ExperimentalRenderHelpers

included

Constructor Details

#initialize(**system_arguments) ⇒ ActionMenu

Returns a new instance of ActionMenu.

Parameters:

  • system_arguments (Hash)

    The arguments accepted by <%= link_to_component(Primer::Alpha::ActionMenu::PrimaryMenu) %>.



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'app/components/primer/alpha/action_menu.rb', line 209

def initialize(**system_arguments)
  @primary_menu = PrimaryMenu.allocate
  @system_arguments = @primary_menu.send(:initialize, **system_arguments)

  @system_arguments[:tag] = :"action-menu"
  @system_arguments[:preload] = true if @primary_menu.preload?

  @system_arguments[:data] = merge_data(
    @system_arguments, {
      data: { "select-variant": @primary_menu.select_variant }
    }
  )

  @system_arguments[:"data-dynamic-label"] = "" if @primary_menu.dynamic_label

  if @primary_menu.dynamic_label_prefix.present?
    @system_arguments[:"data-dynamic-label-prefix"] = @primary_menu.dynamic_label_prefix
  end
end

Instance Method Details

#itemsArray<ViewComponent::Slot>

Gets the list of configured menu items, which includes regular items, avatar items, groups, and dividers.

Returns:

  • (Array<ViewComponent::Slot>)


28
29
# File 'app/components/primer/alpha/action_menu.rb', line 28

def items
end

#with_avatar_item(**system_arguments) ⇒ Object

Adds an avatar item to the menu.

Parameters:

  • system_arguments (Hash)

    The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList) %>‘s item slot.



10
11
# File 'app/components/primer/alpha/action_menu.rb', line 10

def with_avatar_item(**system_arguments)
end

#with_divider(**system_arguments) ⇒ Object

Adds a divider to the list. Dividers visually separate items.

Parameters:

  • system_arguments (Hash)

    The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList::Divider) %>.



16
17
# File 'app/components/primer/alpha/action_menu.rb', line 16

def with_divider(**system_arguments)
end

#with_group(**system_arguments) ⇒ Object

Adds a group to the menu. Groups are a logical set of items with a header.

Parameters:

  • system_arguments (Hash)

    The arguments accepted by <%= link_to_component(Primer::Alpha::ActionMenu::Group) %>.



22
23
# File 'app/components/primer/alpha/action_menu.rb', line 22

def with_group(**system_arguments)
end

#with_item(**system_arguments) ⇒ Object

Adds an item to the menu.

Parameters:

  • system_arguments (Hash)

    The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList) %>‘s item slot.



4
5
# File 'app/components/primer/alpha/action_menu.rb', line 4

def with_item(**system_arguments)
end