class Primer::Alpha::FormControl
‘aria-describedby` manually on the input element.
input being wrapped is not generated by a Rails form helper, care must be taken to set
and validation message elements, and can be passed directly to Rails’ form helper methods. If the
example above, ‘input_arguments[:describedby]` contains the HTML IDs for both the caption
`aria-describedby` attribute in the hash it yields to the block passed to `#with_input`. In the
validation message elements. The component attempts to mitigate this by including the correct
Similarly, `FormControl` cannot automatically connect the `<input>` element to the caption and
as part of the `label_arguments` passed to the `FormControl` constructor.
Note that the name of the field, `:bar`, is passed to both the Rails `#text_field` method and
“`
<% end %>
<% end %>
<% end %>
<%= f.text_field(:bar, **input_arguments) %>
<% component.with_input do |input_arguments| %>
<%= render(Primer::Alpha::FormControl.new(label_arguments: { for: “bar” })) do |component| %>
<%= form_with(url: “/path/somewhere”) do |f| %>
“`erb
attribute, eg:
Users of the `FormControl` component will need to manually connect the label using the `for:`
use Primer’s pre-made form components like ‘TextField`, etc, ideally via the Primer forms framework.
the input and its associated label. For this and other reasons, consumers are highly encouraged to
Because `FormControl` does not manage the actual `<input>` element, it cannot semantically connect
@accessibility
forms framework.
NOTE: This `FormControl` component is designed for wrapping inputs that aren’t supported by the Primer
Wraps an input (or arbitrary content) with a label above and a caption and validation message beneath.
def before_render
def before_render # make sure to evaluate the component's content block so slots are defined content @input_arguments = { aria: {} } ids = [].tap do |memo| memo << @validation_id if @validation_message memo << @caption_id if @init_caption || caption? end @input_arguments[:aria][:required] = "true" if required? return if ids.empty? @input_arguments[:aria][:describedby] = ids.join(" ") end
def full_width?
Whether or not the form control should take up all the horizontal space allowed by its container.
def full_width? @full_width end
def initialize(label:, caption: nil, validation_message: nil, required: false, visually_hide_label: false, full_width: false, label_arguments: {}, **system_arguments)
-
system_arguments
(Hash
) -- <%= link_to_system_arguments_docs %> -
label_arguments
(Hash
) -- HTML attributes to attach to the ` -
full_width
(Boolean
) -- When set to `true`, the form control will take up all the horizontal space allowed by its container. -
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. -
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. -
validation_message
(String
) -- A string displayed in red between the caption and the input indicating the input's contents are invalid. -
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. -
label
(String
) -- Label text displayed above the input.
def initialize(label:, caption: nil, validation_message: nil, required: false, visually_hide_label: false, full_width: false, label_arguments: {}, **system_arguments) @label = label @init_caption = caption @validation_message = validation_message @required = required @visually_hide_label = visually_hide_label @full_width = full_width @label_arguments = label_arguments @system_arguments = system_arguments @system_arguments[:classes] = class_names( @system_arguments[:classes], "FormControl", "FormControl--fullWidth" => full_width? ) @label_arguments[:classes] = class_names( @label_arguments.delete(:classes), "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
def required?
Whether or not this input is marked as required.
def required? @required end
def visually_hide_label?
Whether or not to hide the label visually. The label will still be visible to screen readers.
def visually_hide_label? @visually_hide_label end
def with_input(&block)
def with_input(&block) @input_block = block end