Skip to content

Commit

Permalink
ActionMenu form input (#2367)
Browse files Browse the repository at this point in the history
  • Loading branch information
camertron authored Nov 20, 2023
1 parent ebfec72 commit b2acc97
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/empty-meals-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/view-components': minor
---

Add an ActionMenu form input
20 changes: 20 additions & 0 deletions app/forms/action_menu_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# :nodoc:
class ActionMenuForm < ApplicationForm
form do |action_menu_form|
action_menu_form.action_menu(name: "city", label: "Favorite city", caption: "Select your favorite!") do |city_list|
city_list.with_item(label: "Lopez Island", data: { value: "lopez_island" }) do |item|
item.with_leading_visual_icon(icon: :log)
end
city_list.with_item(label: "Bellevue", data: { value: "bellevue" }) do |item|
item.with_leading_visual_icon(icon: :paste)
end
city_list.with_item(label: "Seattle", data: { value: "seattle" }) do |item|
item.with_leading_visual_icon(icon: :"device-camera")
end
end

action_menu_form.submit(name: :submit, label: "Submit")
end
end
2 changes: 2 additions & 0 deletions demo/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# frozen_string_literal: true

# :nodoc:
class ApplicationController < ActionController::Base
protect_from_forgery
end
6 changes: 6 additions & 0 deletions lib/primer/forms/action_menu.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<%= render(FormControl.new(input: @input)) do %>
<%= render(Primer::Alpha::ActionMenu.new(**@input.input_arguments)) do |menu| %>
<% menu.with_show_button { "Select..." } %>
<% @input.block.call(menu) if @input.block %>
<% end %>
<% end %>
25 changes: 25 additions & 0 deletions lib/primer/forms/action_menu.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

module Primer
module Forms
# :nodoc:
class ActionMenu < BaseComponent
delegate :builder, :form, to: :@input

def initialize(input:)
@input = input

@input.input_arguments[:form_arguments] = {
name: @input.name,
builder: builder
}

@input.input_arguments[:select_variant] ||= :single

unless @input.input_arguments.include?(:dynamic_label)
@input.input_arguments[:dynamic_label] = true
end
end
end
end
end
36 changes: 36 additions & 0 deletions lib/primer/forms/dsl/action_menu_input.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

module Primer
module Forms
module Dsl
# :nodoc:
class ActionMenuInput < Input
attr_reader :name, :label, :block

def initialize(name:, label:, **system_arguments, &block)
@name = name
@label = label
@block = block

super(**system_arguments)
end

def to_component
ActionMenu.new(input: self)
end

# :nocov:
def type
:action_menu
end
# :nocov:

# :nocov:
def focusable?
true
end
# :nocov:
end
end
end
end
9 changes: 9 additions & 0 deletions lib/primer/forms/dsl/input_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ def select_list(**options, &block)
add_input SelectInput.new(builder: builder, form: form, **options, &block)
end

# Adds an <%= link_to_component(Primer::Alpha::ActionMenu) %> to this form.
#
# @param options [Hash] The options accepted by the <%= link_to_component(Primer::Alpha::ActionMenu) %> component.
# @param block [Proc] The block passed to `#render` when the <%= link_to_component(Primer::Alpha::ActionMenu) %> is rendered. This block is passed an instance of <%= link_to_component(Primer::Alpha::ActionMenu) %>, which can be used to add items, dividers, etc.
def action_menu(**options, &block)
options = decorate_options(**options)
add_input ActionMenuInput.new(builder: builder, form: form, **options, &block)
end

# END select input methods

# START button input methods
Expand Down
4 changes: 4 additions & 0 deletions previews/primer/forms_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def array_check_box_group_form; end

def select_form; end

def action_menu_form(route_format: :html)
render_with_template(locals: { route_format: route_format })
end

def radio_button_with_nested_form; end

def check_box_with_nested_form; end
Expand Down
3 changes: 3 additions & 0 deletions previews/primer/forms_preview/action_menu_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= primer_form_with(url: action_menu_form_action_path(format: route_format)) do |f| %>
<%= render(ActionMenuForm.new(f)) %>
<% end %>
15 changes: 13 additions & 2 deletions test/lib/primer/forms/integration_forms_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ def test_multi_submit
click_on("Submit")

result = JSON.parse(page.text)
assert result["country"], "CA"
assert result["region"], "SK"
assert_equal result["country"], "CA"
assert_equal result["region"], "SK"
end

def test_toggle_switch_form_errors
Expand All @@ -62,6 +62,17 @@ def test_toggle_switch_form_errors
refute_selector("#error-toggle", text: "Bad CSRF token")
end

def test_action_menu_form_input
visit_preview(:action_menu_form, route_format: :json)

click_on("Select...")
click_on("Lopez Island")
click_on("Submit")

result = JSON.parse(page.text)
assert_equal result.dig("other_params", "city"), "lopez_island"
end

private

def wait_for_toggle_switch_spinner
Expand Down

0 comments on commit b2acc97

Please sign in to comment.