Skip to content

Instantly share code, notes, and snippets.

@camertron
Created June 28, 2023 23:22
Show Gist options
  • Save camertron/22c0880171226c82392271318f48cda9 to your computer and use it in GitHub Desktop.
Save camertron/22c0880171226c82392271318f48cda9 to your computer and use it in GitHub Desktop.
Hacking on the Primer Forms Framework

Intro

The Primer forms framework is a framework for declaratively defining forms using the Primer design system that are accessible by default.

Inputs and Components

Every input type (text fields, select lists, etc) is defined as an input, i.e. a class that inherits from Primer::Forms::Dsl::Input. These inputs together form the framework's DSL, or Domain Specific Language. Inputs return component instances via their #to_component methods. Components are classes that inherit from Primer::Forms::BaseComponent. Together, inputs and components define the form.

Inputs

Example: The TextFieldInput.

Inputs are essentially the DSL layer. They produce components that can be rendered on the page. As such, they generally don't concern themselves with HTML, CSS, etc. Instead, they are supposed to be an abstraction that collects high-level configuration that can be used to construct a component. In practice, the distinction between an input and a component is somewhat blurry, and we are considering merging the two together to reduce complexity.

Components

Example: The TextField component

Although they are not strictly view components (i.e. they do not inherit from ViewComponent::Base), components are designed to work in a very similar fashion. Templates (i.e. ERB files) are defined in separate files with the same file name as the corresponding component class. For example, the TextField component class lives in text_field.rb and renders the text_field.html.erb class.

Input Methods

Text fields (for example) can be declared by calling the text_field method, which is defined here. All this method does is create a new instance of TextFieldInput and add it to the list of inputs. When rendered, the framework interates over this list of inputs, calls #to_component on each input, and renders the resulting component instance.

Adding Another Input

Adding an input requires these steps:

  1. Create a new input class in Primer::Forms::Dsl.
  2. Create a new component class and associated template in the Primer::Forms namespace. Define the #to_component method on the input class and return an instance of the component class.
  3. Add a method to the InputMethods module that creates a new input instance and passes it to #add_input.
  4. Write previews and tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment