From a3507d8883433ef1413cb8614ab4b3cb4d05b1e7 Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Mon, 8 Jun 2026 09:48:09 +0100 Subject: [PATCH] [chore] render filterable tree view in fieldset Fieldset-style inputs never go through the `FormControl` wrapper, so the legend needs the `FormControl-label` class applied by the component. The input does not support validation for the time being. Wrapper arguments stay on the fieldset, while the component-specific and form arguments flow to the inner tree view. --- lib/primer/open_project/forms/_index.sass | 1 + .../forms/dsl/filterable_tree_view_input.rb | 4 +++ .../forms/filterable_tree_view.html.erb | 26 ++++++++++++++----- .../forms/filterable_tree_view.rb | 14 +++++++--- .../forms/filterable_tree_view.sass | 5 ++++ .../wikis/link_existing_wiki_page_form.rb | 1 + modules/wikis/config/locales/en.yml | 1 + .../forms/filterable_tree_view_spec.rb | 22 +++++++++++++++- 8 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 lib/primer/open_project/forms/filterable_tree_view.sass diff --git a/lib/primer/open_project/forms/_index.sass b/lib/primer/open_project/forms/_index.sass index 4eee9f5aee3..939d25ff05f 100644 --- a/lib/primer/open_project/forms/_index.sass +++ b/lib/primer/open_project/forms/_index.sass @@ -1 +1,2 @@ @import "advanced_form_group" +@import "filterable_tree_view" diff --git a/lib/primer/open_project/forms/dsl/filterable_tree_view_input.rb b/lib/primer/open_project/forms/dsl/filterable_tree_view_input.rb index 46334d2685d..0b825f4b6e7 100644 --- a/lib/primer/open_project/forms/dsl/filterable_tree_view_input.rb +++ b/lib/primer/open_project/forms/dsl/filterable_tree_view_input.rb @@ -59,6 +59,10 @@ module Primer true end # :nocov: + + def supports_validation? + false + end end end end diff --git a/lib/primer/open_project/forms/filterable_tree_view.html.erb b/lib/primer/open_project/forms/filterable_tree_view.html.erb index bb222c38920..ddda8b1ba53 100644 --- a/lib/primer/open_project/forms/filterable_tree_view.html.erb +++ b/lib/primer/open_project/forms/filterable_tree_view.html.erb @@ -1,7 +1,19 @@ -<%= - render(FormControl.new(input: @input)) do - render(Primer::OpenProject::FilterableTreeView.new(**@input.input_arguments)) do |tree_view| - @input.block&.call(tree_view) - end - end -%> +
+ <%= content_tag(:fieldset, **@fieldset_arguments) do %> + <% if @input.label %> + <%= content_tag(:legend, **@input.label_arguments) do %> + <%= @input.label %> + <% end %> + <% end %> +
+ <%= render(Caption.new(input: @input)) %> +
+ <%= render(SpacingWrapper.new) do %> + <%= + render(Primer::OpenProject::FilterableTreeView.new(**@tree_view_arguments)) do |tree_view| + @input.block&.call(tree_view) + end + %> + <% end %> + <% end %> +
diff --git a/lib/primer/open_project/forms/filterable_tree_view.rb b/lib/primer/open_project/forms/filterable_tree_view.rb index c6b43a0cbb9..d86bd22780c 100644 --- a/lib/primer/open_project/forms/filterable_tree_view.rb +++ b/lib/primer/open_project/forms/filterable_tree_view.rb @@ -39,10 +39,18 @@ module Primer super() @input = input + @input.add_label_classes("FormControl-label") - @input.input_arguments[:form_arguments] = { - name: @input.name, - builder: builder + @fieldset_arguments = @input.input_arguments.extract!(:hidden, :class, :classes) + Primer::Forms::Utils.classify(@fieldset_arguments) + @fieldset_arguments.delete(:class) if @fieldset_arguments[:class].blank? + + @tree_view_arguments = { + **@input.input_arguments, + form_arguments: { + name: @input.name, + builder: builder + } } end end diff --git a/lib/primer/open_project/forms/filterable_tree_view.sass b/lib/primer/open_project/forms/filterable_tree_view.sass new file mode 100644 index 00000000000..b7fa534e956 --- /dev/null +++ b/lib/primer/open_project/forms/filterable_tree_view.sass @@ -0,0 +1,5 @@ +.FormControl-filterable-tree-view-wrap + & fieldset + padding: 0 + margin: 0 + border: 0 diff --git a/modules/wikis/app/forms/wikis/link_existing_wiki_page_form.rb b/modules/wikis/app/forms/wikis/link_existing_wiki_page_form.rb index cd39eca96a4..93711b53e80 100644 --- a/modules/wikis/app/forms/wikis/link_existing_wiki_page_form.rb +++ b/modules/wikis/app/forms/wikis/link_existing_wiki_page_form.rb @@ -37,6 +37,7 @@ module Wikis f.filterable_tree_view( name: "wiki_page_selection", + label: I18n.t("wikis.link_existing_wiki_page_form.label"), src: helpers.search_wiki_pages_path(provider_id: model.provider_id, name: "wiki_page_selection"), filter_mode_control_arguments: { hidden: true }, filter_input_arguments: { diff --git a/modules/wikis/config/locales/en.yml b/modules/wikis/config/locales/en.yml index b67984ec956..2693679c401 100644 --- a/modules/wikis/config/locales/en.yml +++ b/modules/wikis/config/locales/en.yml @@ -151,6 +151,7 @@ en: link_existing_wiki_page_dialog: title: Add existing wiki page link_existing_wiki_page_form: + label: Wiki page no_results: No wiki pages found placeholder: Search for a wiki page oauth_login_component: diff --git a/spec/lib/primer/open_project/forms/filterable_tree_view_spec.rb b/spec/lib/primer/open_project/forms/filterable_tree_view_spec.rb index 45ba32e4f2a..aeeac813a99 100644 --- a/spec/lib/primer/open_project/forms/filterable_tree_view_spec.rb +++ b/spec/lib/primer/open_project/forms/filterable_tree_view_spec.rb @@ -41,7 +41,7 @@ RSpec.describe Primer::OpenProject::Forms::FilterableTreeView, type: :forms do render_in_view_context(model, params) do |model, params| primer_form_with(url: "/foo", model:) do |f| render_inline_form(f) do |form| - form.filterable_tree_view(name: :ingredients, **params) do |tree| + form.filterable_tree_view(name: :ingredients, label: "Ingredients", **params) do |tree| tree.with_leaf(select_variant: :multiple, label: "flour") tree.with_leaf(select_variant: :multiple, label: "sugar") tree.with_leaf(select_variant: :multiple, label: "eggs") @@ -60,10 +60,30 @@ RSpec.describe Primer::OpenProject::Forms::FilterableTreeView, type: :forms do expect(rendered_form).to have_element :"filterable-tree-view" end + it "renders the fieldset" do + expect(rendered_form).to have_selector :fieldset, "Ingredients" + end + + it "renders the label as the fieldset legend" do + expect(rendered_form).to have_element :legend, class: "FormControl-label", text: "Ingredients" + end + it "renders the leafs", :aggregate_failures do expect(rendered_form).to have_element(:li, class: "TreeViewItem", role: "none", text: "flour") expect(rendered_form).to have_element(:li, class: "TreeViewItem", role: "none", text: "sugar") expect(rendered_form).to have_element(:li, class: "TreeViewItem", role: "none", text: "eggs") end + + it "wires the tree view up for form submission" do + expect(rendered_form).to have_element :input, type: "hidden", name: "comment[ingredients][]", visible: :all + end + + context "when hidden" do + let(:params) { { hidden: true } } + + it "hides the whole fieldset" do + expect(rendered_form).to have_selector :fieldset, visible: :hidden + end + end end end