From 03de788603c8bf40308d349c56ca7524601fd7da Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Wed, 8 Feb 2023 15:48:52 -0800 Subject: [PATCH 1/8] Standalone form control --- .../primer/alpha/form_control.html.erb | 26 ++++ app/components/primer/alpha/form_control.rb | 111 ++++++++++++++++++ previews/primer/alpha/form_control_preview.rb | 106 +++++++++++++++++ .../form_control_preview/playground.html.erb | 9 ++ test/components/alpha/form_control_test.rb | 47 ++++++++ 5 files changed, 299 insertions(+) create mode 100644 app/components/primer/alpha/form_control.html.erb create mode 100644 app/components/primer/alpha/form_control.rb create mode 100644 previews/primer/alpha/form_control_preview.rb create mode 100644 previews/primer/alpha/form_control_preview/playground.html.erb create mode 100644 test/components/alpha/form_control_test.rb diff --git a/app/components/primer/alpha/form_control.html.erb b/app/components/primer/alpha/form_control.html.erb new file mode 100644 index 0000000000..7784c0648c --- /dev/null +++ b/app/components/primer/alpha/form_control.html.erb @@ -0,0 +1,26 @@ +<%= render(Primer::BaseComponent.new(tag: :div, **@system_arguments)) do %> + <%= render(Primer::BaseComponent.new(tag: :label, **@label_arguments)) do %> + <%= @label %> + <% if required? %> + + <% end %> + <% end %> + <% if @input_block %> + <%= view_context.capture { @input_block.call(@input_arguments) } %> + <% end %> + <% if @validation_message %> + <%= render(Primer::BaseComponent.new(tag: :div, **@validation_arguments)) do %> + <%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %> + <%= @validation_message %> + <% end %> + <% end %> + <% if @init_caption || caption? %> + + <% if caption? %> + <%= caption %> + <% else %> + <%= @init_caption %> + <% end %> + + <% end %> +<% end %> diff --git a/app/components/primer/alpha/form_control.rb b/app/components/primer/alpha/form_control.rb new file mode 100644 index 0000000000..38ec960b22 --- /dev/null +++ b/app/components/primer/alpha/form_control.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +module Primer + module Alpha + # Wraps an input (or arbitrary content) with a label above and a caption and validation message beneath. + # NOTE: This `FormControl` component is designed for wrapping inputs that aren't supported by the Primer + # forms framework. + class FormControl < Primer::Component + # Describes the field and what sorts of input it expects. Displayed below the input. + # Note that this slot takes precedence over the `caption:` argument in the constructor. + renders_one :caption + + # @example Default + # <%= render(Primer::Alpha::FormControl.new(label: "Best character")) do |component| %> + # <% component.with_input do |input_arguments| %> + # <%= render(Primer::Alpha::SegmentedControl.new("aria-label": "Best character", **input_arguments)) do |seg| %> + # <% seg.with_item(label: "Han Solo") %> + # <% seg.with_item(label: "Luke Skywalker") %> + # <% seg.with_item(label: "Leia Organa") %> + # <% end %> + # <% end %> + # <% end %> + # + # @param label [String] Label text displayed above the input. + # @param caption [String] Describes the field and what sort of input it expects. Displayed below the input. Note that the `caption` slot is also available and takes precedence over this argument when provided. + # @param validation_message [String] A string displayed in red between the caption and the input indicating the input's contents are invalid. + # @param required [Boolean] Default `false`. When set to `true`, causes an asterisk (*) to appear next to the field's label indicating it is a required field. Note that this option explicitly does _not_ add a `required` HTML attribute. Doing so would enable native browser validations, which are inaccessible and inconsistent with the Primer design system. + # @param visually_hide_label [Boolean] When set to `true`, hides the label. Although the label will be hidden visually, it will still be visible to screen readers. + # @param full_width [Boolean] When set to `true`, the form control will take up all the horizontal space allowed by its container. + # @param system_arguments [Hash] <%= link_to_system_arguments_docs %> + def initialize(label:, caption: nil, validation_message: nil, required: false, visually_hide_label: false, full_width: false, **system_arguments) + @label = label + @init_caption = caption + @validation_message = validation_message + @required = required + @visually_hide_label = visually_hide_label + @full_width = full_width + @system_arguments = system_arguments + + @system_arguments = { + classes: class_names( + @system_arguments[:classes], + "FormControl", + "FormControl--fullWidth" => full_width? + ) + } + + @label_arguments = { + classes: class_names( + "FormControl-label", + @visually_hide_label ? "sr-only" : nil + ) + } + + base_id = self.class.generate_id + @validation_id = "validation-#{base_id}" + @caption_id = "caption-#{base_id}" + + @validation_arguments = { + classes: "FormControl-inlineValidation", + id: @validation_id + } + end + + # @!parse + # # The input content. Yields a set of <%= link_to_system_arguments_docs %> that should be added to the input. + # # + # renders_one(:input) + + def with_input(&block) + @input_block = block + end + + def required? + @required + end + + def visually_hide_label? + @visually_hide_label + end + + def full_width? + @full_width + end + + private + + def before_render + # make sure to evaluate the component's content block so slots are defined + content + + @input_arguments = { + aria: {} + } + + if required? + @input_arguments[:aria][:required] = true + end + + ids = [].tap do |memo| + memo << @validation_id if @validation_message + memo << @caption_id if @init_caption || caption? + end + + return if ids.empty? + + @input_arguments[:aria][:describedby] = ids.join(" ") + end + end + end +end diff --git a/previews/primer/alpha/form_control_preview.rb b/previews/primer/alpha/form_control_preview.rb new file mode 100644 index 0000000000..b5479523ca --- /dev/null +++ b/previews/primer/alpha/form_control_preview.rb @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +module Primer + module Alpha + # @label FormControl + class FormControlPreview < ViewComponent::Preview + # @label Playground + # + # @param label text + # @param caption text + # @param validation_message text + # @param required toggle + # @param visually_hide_label toggle + # @param full_width toggle + def playground( + label: "Best character", + caption: "May the force be with you", + validation_message: "Something went wrong", + required: false, + visually_hide_label: false, + full_width: false + ) + render_with_template( + locals: { + system_arguments: { + label: label, + caption: caption, + validation_message: validation_message, + required: required, + visually_hide_label: visually_hide_label, + full_width: full_width + } + } + ) + end + + # @label Default + def default + render_with_template( + template: "primer/alpha/form_control_preview/playground", + locals: { + system_arguments: { + label: "Best character" + } + } + ) + end + + # @!group Options + # + # @label With caption + def with_caption + render_with_template( + template: "primer/alpha/form_control_preview/playground", + locals: { + system_arguments: { + label: "Best character", + caption: "May the force be with you" + } + } + ) + end + + # @label With validation message + def with_validation_message + render_with_template( + template: "primer/alpha/form_control_preview/playground", + locals: { + system_arguments: { + label: "Best character", + validation_message: "Something went wrong" + } + } + ) + end + + # @label Required + def required + render_with_template( + template: "primer/alpha/form_control_preview/playground", + locals: { + system_arguments: { + label: "Best character", + required: true + } + } + ) + end + + # @label With visually hidden label + def with_visually_hidden_label + render_with_template( + template: "primer/alpha/form_control_preview/playground", + locals: { + system_arguments: { + label: "Best character", + visually_hide_label: true + } + } + ) + end + # + # @!endgroup + end + end +end diff --git a/previews/primer/alpha/form_control_preview/playground.html.erb b/previews/primer/alpha/form_control_preview/playground.html.erb new file mode 100644 index 0000000000..dbcce2f746 --- /dev/null +++ b/previews/primer/alpha/form_control_preview/playground.html.erb @@ -0,0 +1,9 @@ +<%= render(Primer::Alpha::FormControl.new(**system_arguments)) do |component| %> + <% component.with_input do |input_arguments| %> + <%= render(Primer::Alpha::SegmentedControl.new("aria-label": "Best character", **input_arguments)) do |seg| %> + <% seg.with_item(label: "Han Solo", selected: true) %> + <% seg.with_item(label: "Luke Skywalker") %> + <% seg.with_item(label: "Leia Organa") %> + <% end %> + <% end %> +<% end %> diff --git a/test/components/alpha/form_control_test.rb b/test/components/alpha/form_control_test.rb new file mode 100644 index 0000000000..ff4486c7c8 --- /dev/null +++ b/test/components/alpha/form_control_test.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require "components/test_helper" + +module Primer + module Alpha + class FormControlTest < Minitest::Test + include Primer::ComponentTestHelpers + + def test_basic_structure + render_preview(:playground) + + assert_selector(".FormControl-label", text: "Best character") + assert_selector("segmented-control") + assert_selector(".FormControl-inlineValidation", text: "Something went wrong") do + assert_selector(".octicon-alert-fill") + end + assert_selector(".FormControl-caption", text: "May the force be with you") + end + + def test_described_by_ids + render_preview(:playground) + + caption_id = page.find_css(".FormControl-caption")[0].attributes["id"].value + validation_id = page.find_css(".FormControl-inlineValidation")[0].attributes["id"].value + described_by_ids = page.find_css("segmented-control ul")[0].attributes["aria-describedby"].value.split(" ") + + assert_includes(described_by_ids, caption_id) + assert_includes(described_by_ids, validation_id) + end + + def test_required + render_preview(:required) + + assert_selector(".FormControl-label", text: "Best character") do + assert_selector("[aria-hidden=true]", text: "*") + end + end + + def test_visually_hidden_label + render_preview(:with_visually_hidden_label) + + assert_selector(".FormControl-label.sr-only", text: "Best character") + end + end + end +end From e5f7d98686df6b82dd25b9c594fe5b6168761618 Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Fri, 10 Feb 2023 15:58:56 -0800 Subject: [PATCH 2/8] Add changeset --- .changeset/polite-turkeys-rush.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/polite-turkeys-rush.md diff --git a/.changeset/polite-turkeys-rush.md b/.changeset/polite-turkeys-rush.md new file mode 100644 index 0000000000..b8117876bc --- /dev/null +++ b/.changeset/polite-turkeys-rush.md @@ -0,0 +1,5 @@ +--- +'@primer/view-components': patch +--- + +Add a standalone form control From af63ef00f2d1c5f7353258c7a35416778b3333d8 Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Fri, 10 Feb 2023 15:59:47 -0800 Subject: [PATCH 3/8] Make rubocop happy --- app/components/primer/alpha/form_control.rb | 4 +--- test/components/alpha/form_control_test.rb | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/components/primer/alpha/form_control.rb b/app/components/primer/alpha/form_control.rb index 38ec960b22..804703babc 100644 --- a/app/components/primer/alpha/form_control.rb +++ b/app/components/primer/alpha/form_control.rb @@ -93,9 +93,7 @@ def before_render aria: {} } - if required? - @input_arguments[:aria][:required] = true - end + @input_arguments[:aria][:required] = true if required? ids = [].tap do |memo| memo << @validation_id if @validation_message diff --git a/test/components/alpha/form_control_test.rb b/test/components/alpha/form_control_test.rb index ff4486c7c8..fb89161d36 100644 --- a/test/components/alpha/form_control_test.rb +++ b/test/components/alpha/form_control_test.rb @@ -23,7 +23,7 @@ def test_described_by_ids caption_id = page.find_css(".FormControl-caption")[0].attributes["id"].value validation_id = page.find_css(".FormControl-inlineValidation")[0].attributes["id"].value - described_by_ids = page.find_css("segmented-control ul")[0].attributes["aria-describedby"].value.split(" ") + described_by_ids = page.find_css("segmented-control ul")[0].attributes["aria-describedby"].value.split assert_includes(described_by_ids, caption_id) assert_includes(described_by_ids, validation_id) From bdb6da83493a0d5349d9f2059f334f687ec6b52a Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Fri, 10 Feb 2023 16:06:28 -0800 Subject: [PATCH 4/8] Remove aria-required --- app/components/primer/alpha/form_control.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/components/primer/alpha/form_control.rb b/app/components/primer/alpha/form_control.rb index 804703babc..9077ee751f 100644 --- a/app/components/primer/alpha/form_control.rb +++ b/app/components/primer/alpha/form_control.rb @@ -93,8 +93,6 @@ def before_render aria: {} } - @input_arguments[:aria][:required] = true if required? - ids = [].tap do |memo| memo << @validation_id if @validation_message memo << @caption_id if @init_caption || caption? From d07301129dd97b660323ea4a5be7c51806ee9ba9 Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Fri, 10 Feb 2023 16:08:36 -0800 Subject: [PATCH 5/8] Fix system arguments --- app/components/primer/alpha/form_control.rb | 12 +++++------- test/components/component_test.rb | 3 ++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/components/primer/alpha/form_control.rb b/app/components/primer/alpha/form_control.rb index 9077ee751f..904a70ef48 100644 --- a/app/components/primer/alpha/form_control.rb +++ b/app/components/primer/alpha/form_control.rb @@ -37,13 +37,11 @@ def initialize(label:, caption: nil, validation_message: nil, required: false, v @full_width = full_width @system_arguments = system_arguments - @system_arguments = { - classes: class_names( - @system_arguments[:classes], - "FormControl", - "FormControl--fullWidth" => full_width? - ) - } + @system_arguments[:classes] = class_names( + @system_arguments[:classes], + "FormControl", + "FormControl--fullWidth" => full_width? + ) @label_arguments = { classes: class_names( diff --git a/test/components/component_test.rb b/test/components/component_test.rb index 4e26e612c2..4b346e6913 100644 --- a/test/components/component_test.rb +++ b/test/components/component_test.rb @@ -103,7 +103,8 @@ class PrimerComponentTest < Minitest::Test [Primer::Alpha::UnderlineNav, { label: "aria label" }, proc { |component| component.with_tab(selected: true) { "Foo" } }], [Primer::Alpha::Tooltip, { type: :label, for_id: "some-button", text: "Foo" }], [Primer::Alpha::NavList, { aria: { label: "Nav list" } }], - [Primer::Alpha::Banner, {}] + [Primer::Alpha::Banner, {}], + [Primer::Alpha::FormControl, { label: "Foo" }] ].freeze def test_registered_components From d7f59aa77d2b77bca843ed8c22dbea6987e03b50 Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Fri, 10 Feb 2023 16:11:21 -0800 Subject: [PATCH 6/8] Fix coverage --- app/components/primer/alpha/form_control.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/primer/alpha/form_control.rb b/app/components/primer/alpha/form_control.rb index 904a70ef48..e1491b261b 100644 --- a/app/components/primer/alpha/form_control.rb +++ b/app/components/primer/alpha/form_control.rb @@ -46,7 +46,7 @@ def initialize(label:, caption: nil, validation_message: nil, required: false, v @label_arguments = { classes: class_names( "FormControl-label", - @visually_hide_label ? "sr-only" : nil + visually_hide_label? ? "sr-only" : nil ) } From 4d6436ded7246299474bb6431113bed3e5bd4c67 Mon Sep 17 00:00:00 2001 From: camertron Date: Mon, 13 Feb 2023 18:19:11 +0000 Subject: [PATCH 7/8] Generating component snapshots --- .../primer/alpha/form_control/default.png | Bin 0 -> 7734 bytes .../primer/alpha/form_control/focused.png | Bin 0 -> 7730 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 .playwright/screenshots/snapshots.test.ts-snapshots/primer/alpha/form_control/default.png create mode 100644 .playwright/screenshots/snapshots.test.ts-snapshots/primer/alpha/form_control/focused.png diff --git a/.playwright/screenshots/snapshots.test.ts-snapshots/primer/alpha/form_control/default.png b/.playwright/screenshots/snapshots.test.ts-snapshots/primer/alpha/form_control/default.png new file mode 100644 index 0000000000000000000000000000000000000000..f85b51c08b2a51b934bb954896b019d66a98ef6a GIT binary patch literal 7734 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 hvnYoD$^%L?4j$I*GfHcG?cYbja Date: Mon, 13 Feb 2023 16:24:03 -0800 Subject: [PATCH 8/8] Update .changeset/polite-turkeys-rush.md Co-authored-by: Jon Rohan --- .changeset/polite-turkeys-rush.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/polite-turkeys-rush.md b/.changeset/polite-turkeys-rush.md index b8117876bc..7de2dab692 100644 --- a/.changeset/polite-turkeys-rush.md +++ b/.changeset/polite-turkeys-rush.md @@ -2,4 +2,4 @@ '@primer/view-components': patch --- -Add a standalone form control +Add a standalone FormControl component