├── .DS_Store ├── .devcontainer ├── devcontainer.json └── post-create-command.sh ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .rubocop.yml ├── .vscode └── rails-forms-workspace.code-workspace ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bin └── test ├── lib └── primer │ ├── form_components.rb │ ├── rails_forms.rb │ └── rails_forms │ ├── .DS_Store │ ├── acts_as_component.rb │ ├── base.html.erb │ ├── base.rb │ ├── base_component.rb │ ├── buffer_rewriter.rb │ ├── caption.html.erb │ ├── caption.rb │ ├── check_box.html.erb │ ├── check_box.rb │ ├── check_box_group.html.erb │ ├── check_box_group.rb │ ├── dsl │ ├── check_box_group_input.rb │ ├── check_box_input.rb │ ├── form_object.rb │ ├── form_reference_input.rb │ ├── hidden_input.rb │ ├── input.rb │ ├── input_group.rb │ ├── input_methods.rb │ ├── multi_input.rb │ ├── radio_button_group_input.rb │ ├── radio_button_input.rb │ ├── select_list_input.rb │ ├── submit_button_input.rb │ ├── text_area_input.rb │ └── text_field_input.rb │ ├── engine.rb │ ├── form_control.html.erb │ ├── form_control.rb │ ├── form_list.html.erb │ ├── form_list.rb │ ├── form_reference.html.erb │ ├── form_reference.rb │ ├── group.html.erb │ ├── group.rb │ ├── hidden_field.html.erb │ ├── hidden_field.rb │ ├── multi.html.erb │ ├── multi.rb │ ├── radio_button.html.erb │ ├── radio_button.rb │ ├── radio_button_group.html.erb │ ├── radio_button_group.rb │ ├── select_list.html.erb │ ├── select_list.rb │ ├── separator.html.erb │ ├── separator.rb │ ├── spacing_wrapper.html.erb │ ├── spacing_wrapper.rb │ ├── submit_button.html.erb │ ├── submit_button.rb │ ├── text_area.html.erb │ ├── text_area.rb │ ├── text_field.html.erb │ ├── text_field.rb │ └── version.rb ├── lookbook ├── .gitattributes ├── .gitignore ├── .ruby-version ├── Gemfile ├── Gemfile.lock ├── Procfile.dev ├── Rakefile ├── app │ ├── assets │ │ ├── builds │ │ │ └── .keep │ │ ├── config │ │ │ └── manifest.js │ │ └── images │ │ │ └── .keep │ ├── channels │ │ └── application_cable │ │ │ ├── channel.rb │ │ │ └── connection.rb │ ├── controllers │ │ ├── application_controller.rb │ │ └── concerns │ │ │ └── .keep │ ├── helpers │ │ └── application_helper.rb │ ├── javascript │ │ ├── application.js │ │ └── controllers │ │ │ ├── application.js │ │ │ ├── hello_controller.js │ │ │ └── index.js │ ├── jobs │ │ └── application_job.rb │ ├── mailers │ │ └── application_mailer.rb │ ├── models │ │ ├── application_record.rb │ │ └── concerns │ │ │ └── .keep │ └── views │ │ └── layouts │ │ ├── application.html.erb │ │ ├── mailer.html.erb │ │ └── mailer.text.erb ├── bin │ ├── bundle │ ├── dev │ ├── importmap │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── cable.yml │ ├── credentials.yml.enc │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── importmap.rb │ ├── initializers │ │ ├── assets.rb │ │ ├── content_security_policy.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ └── permissions_policy.rb │ ├── locales │ │ └── en.yml │ ├── puma.rb │ ├── routes.rb │ └── storage.yml ├── db │ └── seeds.rb ├── lib │ ├── assets │ │ └── .keep │ └── tasks │ │ └── .keep ├── log │ └── .keep ├── package.json ├── public │ ├── 404.html │ ├── 422.html │ ├── 500.html │ ├── apple-touch-icon-precomposed.png │ ├── apple-touch-icon.png │ ├── favicon.ico │ └── robots.txt ├── script │ ├── css-compile.sh │ └── css.sh ├── storage │ └── .keep ├── test │ ├── application_system_test_case.rb │ ├── channels │ │ └── application_cable │ │ │ └── connection_test.rb │ ├── controllers │ │ └── .keep │ ├── fixtures │ │ └── files │ │ │ └── .keep │ ├── helpers │ │ └── .keep │ ├── integration │ │ └── .keep │ ├── mailers │ │ └── .keep │ ├── models │ │ └── .keep │ ├── system │ │ └── .keep │ └── test_helper.rb ├── tmp │ ├── .keep │ ├── pids │ │ └── .keep │ └── storage │ │ └── .keep ├── vendor │ ├── .keep │ └── javascript │ │ └── .keep └── yarn.lock ├── primer_rails_forms.gemspec ├── test ├── .gitignore ├── app │ ├── components │ │ ├── form_component.html.erb │ │ └── form_component.rb │ ├── controllers │ │ └── application_controller.rb │ └── forms │ │ ├── after_content_form.rb │ │ ├── after_content_form │ │ └── after_content.html.erb │ │ ├── application_form.rb │ │ ├── both_types_of_caption_form.rb │ │ ├── both_types_of_caption_form │ │ └── first_name_caption.html.erb │ │ ├── caption_template_form.rb │ │ ├── caption_template_form │ │ ├── age_middle_aged_caption.html.erb │ │ ├── age_young_caption.html.erb │ │ ├── cool_caption.html.erb │ │ └── first_name_caption.html.erb │ │ ├── check_box_group_form.rb │ │ ├── composed_form.rb │ │ ├── first_name_form.rb │ │ ├── horizontal_form.rb │ │ ├── invalid_form.rb │ │ ├── last_name_form.rb │ │ ├── multi_text_field_form.rb │ │ ├── radio_button_group_form.rb │ │ ├── radio_button_with_nested_form.rb │ │ ├── select_list_form.rb │ │ ├── single_text_field_form.rb │ │ ├── submit_button_form.rb │ │ └── text_field_and_checkbox_form.rb ├── config │ └── application.rb ├── forms_test.rb ├── support │ └── application_form.rb ├── test │ └── components │ │ └── previews │ │ ├── forms_preview.rb │ │ ├── forms_preview │ │ ├── after_content_form.html.erb │ │ ├── caption_template_form.html.erb │ │ ├── check_box_group_form.html.erb │ │ ├── composed_form.html.erb │ │ ├── horizontal_form.html.erb │ │ ├── invalid_form.html.erb │ │ ├── multi_text_field_form.html.erb │ │ ├── radio_button_group_form.html.erb │ │ ├── radio_button_with_nested_form.html.erb │ │ ├── select_list_form.html.erb │ │ ├── single_text_field_form.html.erb │ │ ├── submit_button_form.html.erb │ │ └── text_field_and_checkbox_form.html.erb │ │ └── text_field_preview.rb ├── test_helper.rb └── text_field_test.rb └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/primer/rails_forms/cd98888a4df1a5c8d107b5eb94f1ef4ff2eb67d9/.DS_Store -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: 2 | // https://github.com/microsoft/vscode-dev-containers/tree/v0.177.0/containers/ruby 3 | { 4 | "name": "Ruby", 5 | "build": { 6 | "args": { 7 | // Update 'VARIANT' to pick a Ruby version: 3, 3.0, 2, 2.7, 2.6 8 | "VARIANT": "3", 9 | // Options 10 | "INSTALL_NODE": "true", 11 | "NODE_VERSION": "lts/*" 12 | } 13 | }, 14 | "postCreateCommand": ".devcontainer/post-create-command.sh", 15 | "forwardPorts": [ 16 | 3000 17 | ], 18 | "appPort": [ 19 | 3000 20 | ], 21 | "portsAttributes": { 22 | "3000": { 23 | "label": "lookbook" 24 | } 25 | }, 26 | "customizations": { 27 | "codespaces": { 28 | "repositories": { 29 | "primer/css": { 30 | "permissions": "write-all" 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /.devcontainer/post-create-command.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | script_folder="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)" 4 | workspaces_folder="$(cd "${script_folder}/../.." && pwd)" 5 | 6 | cd "${workspaces_folder}" 7 | 8 | echo "##### Cloning @primer/css" 9 | if [[ ! -d "@primer/css" ]]; then 10 | git clone "https://github.com/primer/css" @primer/css 11 | echo "##### Installing JavaScript dependencies in @primer/css" 12 | cd @primer/css 13 | yarn install 14 | fi 15 | 16 | cd "${workspaces_folder}/rails_forms" 17 | 18 | echo "##### Installing ruby dependencies in rails_forms" 19 | bundle install --jobs 3 --retry 4 20 | 21 | echo "##### Installing JavaScript dependencies in rails_forms" 22 | yarn install 23 | 24 | cd lookbook 25 | 26 | echo "##### Installing ruby dependencies in rails_forms/lookbook" 27 | bundle install --jobs 3 --retry 4 28 | 29 | echo "##### Installing JavaScript dependencies in rails_forms/lookbook" 30 | yarn install 31 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - '*' 7 | push: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@master 16 | - name: Setup Ruby 17 | uses: actions/setup-ruby@v1 18 | with: 19 | ruby-version: 3.0.x 20 | - name: Generate lockfile 21 | run: | 22 | gem update --system 3.2.3 23 | gem install bundler 24 | bundle lock 25 | - uses: actions/cache@v2 26 | with: 27 | path: vendor/bundle 28 | key: gems-build-rails-main-ruby-3.0.x-${{ hashFiles('Gemfile.lock') }} 29 | - name: Lint with Rubocop 30 | run: | 31 | bundle config path vendor/bundle 32 | bundle install --jobs 4 --retry 3 33 | bundle update rails 34 | bundle exec rubocop 35 | test: 36 | runs-on: ubuntu-latest 37 | strategy: 38 | matrix: 39 | rails_version: [7.0.3, main] 40 | ruby_version: [2.7.x, 3.0.x, 3.1.x] 41 | steps: 42 | - uses: actions/checkout@master 43 | - name: Setup Ruby 44 | uses: actions/setup-ruby@v1 45 | with: 46 | ruby-version: ${{ matrix.ruby_version }} 47 | - name: Generate lockfile 48 | run: | 49 | gem update --system 3.3.3 50 | gem install bundler 51 | bundle lock 52 | env: 53 | RAILS_VERSION: ${{ matrix.rails_version }} 54 | - uses: actions/cache@v2 55 | with: 56 | path: vendor/bundle 57 | key: gems-build-rails-${{ matrix.rails_version }}-ruby-${{ matrix.ruby_version }}-${{ hashFiles('Gemfile.lock') }} 58 | - name: Test 59 | run: | 60 | bundle config path vendor/bundle 61 | bundle install --jobs 4 --retry 3 62 | bundle update rails 63 | bin/test 64 | env: 65 | RAILS_VERSION: ${{ matrix.rails_version }} 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | pkg/ 3 | .bundle 4 | node_modules -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_gem: 2 | rubocop-github: 3 | - config/default_edge.yml 4 | - config/rails_edge.yml 5 | 6 | AllCops: 7 | NewCops: enable 8 | Exclude: 9 | - "test/tmp/**/*" 10 | - "lookbook/**/*" 11 | - "vendor/bundle/**/*" 12 | TargetRubyVersion: 2.5 13 | SuggestExtensions: false 14 | 15 | Style/ClassAndModuleChildren: 16 | Enabled: true 17 | Exclude: 18 | - "test/**/*" 19 | 20 | Style/Documentation: 21 | Enabled: false 22 | 23 | Naming/MethodParameterName: 24 | Enabled: true 25 | MinNameLength: 2 26 | 27 | Rails/RefuteMethods: 28 | Enabled: false 29 | 30 | Rails/RakeEnvironment: 31 | Enabled: false 32 | 33 | Style/SymbolArray: 34 | Enabled: false 35 | 36 | Style/AsciiComments: 37 | Enabled: false 38 | 39 | Lint/MissingSuper: 40 | Enabled: false 41 | 42 | Naming/VariableNumber: 43 | Enabled: false 44 | -------------------------------------------------------------------------------- /.vscode/rails-forms-workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "name": "rails_forms", 5 | "path": ".." 6 | }, 7 | { 8 | "name": "@primer/css", 9 | "path": "../../@primer/css" 10 | } 11 | ], 12 | "settings": {} 13 | } 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | gemspec 6 | 7 | group :development do 8 | gem "rubocop", "= 1.13.0" 9 | gem "rubocop-github", "~> 0.16.0" 10 | gem "rubocop-performance", "~> 1.7" 11 | end 12 | 13 | group :development, :test do 14 | gem "pry-byebug" 15 | end 16 | 17 | group :test do 18 | gem "capybara" 19 | gem "minitest" 20 | 21 | rails_version = (ENV["RAILS_VERSION"] || "7.0.3").to_s 22 | 23 | # rubocop:disable Bundler/DuplicatedGem 24 | if rails_version == "main" 25 | git "https://github.com/rails/rails", ref: "main" do 26 | gem "rails" 27 | end 28 | else 29 | gem "rails", rails_version 30 | end 31 | # rubocop:enable Bundler/DuplicatedGem 32 | 33 | gem "view_component", "~> 2.57" 34 | end 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 GitHub 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # primer_rails_forms 2 | 3 | Easily create Rails forms in a declarative manner. 4 | 5 | ## What is this thing? 6 | 7 | This repo contains the library code for the Rails forms framework as well as an app containing a [Lookbook](https://github.com/allmarkedup/lookbook) for demonstrating forms functionality. 8 | 9 | Our goal with this project is to make forms accessible by default. In service of this goal, customization options are limited. If you've run into a use-case that requires functionality the framework does not yet support, please file an issue or reach out to a team member in the #primer-rails Slack channel. 10 | 11 | ## Usage 12 | 13 | For the impatient, here's an example form that showcases much of the framework's functionality. 14 | 15 | ```ruby 16 | class SignUpForm < ApplicationForm 17 | form do |sign_up_form| 18 | sign_up_form.group(layout: :horizontal) do |name_group| 19 | name_group.text_field( 20 | name: :first_name, 21 | label: "First name", 22 | required: true, 23 | caption: "What your friends call you.", 24 | ) 25 | 26 | name_group.text_field( 27 | name: :last_name, 28 | label: "Last name", 29 | required: true, 30 | caption: "What the principal calls you.", 31 | ) 32 | end 33 | 34 | sign_up_form.text_field( 35 | name: :dietary_restrictions, 36 | label: "Dietary restrictions", 37 | caption: "Any allergies?", 38 | ) 39 | 40 | if @show_notifications_checkbox 41 | sign_up_form.check_box( 42 | name: :email_notifications, 43 | label: "Send me gobs of email!", 44 | caption: "Check this if you enjoy getting spam." 45 | ) 46 | end 47 | 48 | sign_up_form.submit(label: "Submit") 49 | end 50 | 51 | def initialize(show_notifications_checkbox: true) 52 | @show_notifications_checkbox = show_notifications_checkbox 53 | end 54 | end 55 | ``` 56 | 57 | ### Form classes 58 | 59 | A number of the concepts present in primer/rails_forms are borrowed from the [view_component](https://github.com/github/view_component) framework. Like view components, forms are declared inside classes that inherit from a common base class, `Primer::RailsForms::Base`. 60 | 61 | ### Application-specific base class 62 | 63 | It's a good idea to create an `ApplicationForm` base class inside your application as we have done inside GitHub's monolith (dotcom). A separate, application-specific base class allows your team to add shared functionality to all forms without the need to modify `Primer::RailsForms::Base` or make changes to each individual form class. 64 | 65 | Place the following code in app/forms/application_form.rb: 66 | 67 | ```ruby 68 | class ApplicationForm < Primer::RailsForms::Base 69 | end 70 | ``` 71 | 72 | All the examples in this README assume the existence of `ApplicationForm`. 73 | 74 | ### Declaring forms 75 | 76 | Forms are declared inside the block passed to the `form` class method. The method yields an instance of `Primer::RailsForms::Dsl::FormObject` and responds to a number of form input methods which are described below. 77 | 78 | ### Input methods 79 | 80 | 1. `text_field`. A single-line text field. Results in an HTML ``. 81 | 82 | | Arg | Type | Required | Description | 83 | |-|-|-|-| 84 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 85 | | label | String | true | The label to display above the input that describes the input. | 86 | | show_label | Boolean | false | Whether or not to visually show the label text. If `false`, the label will be hidden visually but still announced by screen readers. | 87 | | trailing_label | String | false | If provided, renders a label to the right of the text input. | 88 | | size | Symbol | false | One of: `:small`, `:medium`, or `:large`. Default: `:medium`. | 89 | | show_clear_button | Boolean | false | If `true`, includes a clear button that can be used to clear the contents of the input. Default: `false`. | 90 | | clear_button_id | String | false | The HTML `id` attribute of the clear button. | 91 | | inset | Boolean | false | If `true`, renders in an inset state. Default: `false`. | 92 | | monospace | Boolean | false | If `true`, uses a monospace font for the text input. Default: `false`. | 93 | | leading_visual | Hash | false | Renders a leading visual icon before the text field's cursor. The hash will be passed to Primer's [Octicon component](https://primer.style/view-components/components/octicon). | 94 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 95 | 96 | 1. `text_area`. A multi-line text field. Results in an HTML ``. 97 | 98 | | Arg | Type | Required | Description | 99 | |-|-|-|-| 100 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 101 | | label | String | true | The label to display above the input that describes the input. | 102 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 103 | 104 | 1. `select_list`. A dropdown list. Results in an HTML ``. 105 | | Arg | Type | Required | Description | 106 | |-|-|-|-| 107 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 108 | | label | String | true | The label to display above the input that describes the input. | 109 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 110 | 111 | The `select_list` method accepts a block that yields a `SelectInput` object. This object responds to the `option` method that can be used to add items to the select list. The `option` method accepts the following arguments: 112 | 113 | | Arg | Type | Required | Description | 114 | |-|-|-|-| 115 | | label | String | true | The visible text the user will see. | 116 | | value | String | true | The value submitted to the server when the form is submitted. | 117 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 118 | 119 | Example: 120 | 121 | ```ruby 122 | sign_up_form.select_list(name: "foo", label: "Choose your foo") do |select_list| 123 | select_list.option("Foo 1", "foo-1") 124 | select_list.option("Foo 2", "foo-2") 125 | end 126 | ``` 127 | 128 | 1. `checkbox`. A checkbox. Results in an HTML ``. 129 | | Arg | Type | Required | Description | 130 | |-|-|-|-| 131 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 132 | | label | String | true | The label to display above the input that describes the input. | 133 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 134 | 135 | 1. `radio_button_group`. A set of radio buttons. Results in multiple HTML `` elements. 136 | | Arg | Type | Required | Description | 137 | |-|-|-|-| 138 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 139 | | label | String | true | The label to display above the group of buttons that describes the group as a whole. | 140 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 141 | 142 | The `radio_button_group` method accepts a block that yields a `RadioButtonGroupInput` object. This object responds to the `radio_button` method that can be used to add individual radio buttions to the group. The `radio_button` method accepts the following arguments: 143 | 144 | | Arg | Type | Required | Description | 145 | |-|-|-|-| 146 | | label | String | true | The label to display to the right of the button. | 147 | | value | String | true | The value submitted to the server when the form is submitted. | 148 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 149 | 150 | Example: 151 | 152 | ```ruby 153 | sign_up_form.radio_button_group(name: "channel", label: "How did you hear about us?") do |radio_group| 154 | radio_group.radio_button(value: "online", label: "Online ad") 155 | radio_group.radio_button(value: "radio", label: "Radio ad") 156 | radio_group.radio_button(value: "friend", label: "From a friend") 157 | end 158 | ``` 159 | 160 | Radio buttons can contain nested forms. For example: 161 | 162 | ```ruby 163 | sign_up_form.radio_button_group(name: "channel", label: "How did you hear about us?") do |radio_group| 164 | radio_group.radio_button("friend", label: "From a friend") do |friend_radio| 165 | friend_radio.nested_form(class: "some-class") do |builder| 166 | FriendForm.new(builder) 167 | end 168 | end 169 | end 170 | ``` 171 | 172 | Use the `FormList` class to render multiple nested forms (see below). 173 | 174 | 1. `hidden`. A hidden input. Results in an HTML ``. 175 | | Arg | Type | Required | Description | 176 | |-|-|-|-| 177 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 178 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 179 | 180 | 1. `submit`. A submit button. Results in an HTML ``. 181 | | Arg | Type | Required | Description | 182 | |-|-|-|-| 183 | | name | String | true | The name to associate with this input. Appears in the HTML `name="..."` attribute. | 184 | | label | String | true | The text of the submit button. | 185 | | \*\*system_arguments | Hash | false | [See below.](#system-arguments) | 186 | 187 | Note that the submit input uses Primer's [`ButtonComponent`](https://primer.style/view-components/components/button) under the hood and therefore treats system arguments a bit differently. See [the documentation](https://primer.style/view-components/system-arguments) for more information. 188 | 189 | ### System arguments 190 | 191 | In addition to the input-specific arguments listed above, all inputs also feature the following additional arguments. 192 | 193 | | Arg | Type | Description | 194 | |-|-|-| 195 | | id | String | Overrides the HTML `id` attribute generated by Rails with a custom one. | 196 | | class | Array[String] | A list of CSS classes that will be applied to the input. Combined with the `:classes` argument. | 197 | | classes | Array[String] | A list of CSS classes that will be applied to the input. Combined with the `:class` argument. Exists for compatibility with primer/view_components. | 198 | | caption | String | Caption text to render below the input. | 199 | | disabled | Boolean | If `true`, the text input will not allow keyboard input and renders in a disabled state. Default: `false`. | 200 | | invalid | Boolean | If `true`, renders a red border around the input or otherwise indicates the input is invalid. Default: `false`. Not supported for check boxes, radio buttons, or radio groups. | 201 | | validation_message | String | A validation message to render in red text below the input. If this argument is truthy, `invalid` is implicitly set to `true`. Default: `nil`. Not supported for check boxes, radio buttons, or radio groups. | 202 | | full_width | Boolean | If true, the input will stretch to fill its container. Default: `false`. | 203 | | label_arguments | Hash | System arugments passed to the Rails builder's `#label` method. These arguments will appear as HTML attributes on the `