Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added documentation concerning forms #16566

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions lookbook/docs/patterns/02-forms.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
A form is a series of components that require user input that will then be submitted. Forms are notably common in settings pages but are also present elsewhere like in individual modals (edit project attribute section, edit meeting details) and the filter panel.

## Form elements

A form may be composed of these elements:

- Text input
- Text area
- Select
- Toggle switch
- Checkbox
- Checkbox group
- Radio button
- Radio groups

Additional elements like Banners might also be used.

## Grouping and hierarchy

Form elements that are related need to be grouped together. For this, use a [form group](https://primer-lookbook.github.com/view-components/lookbook/pages/forms/groups_layouts).

If a form is particularly long, split it into different form groups and use a [`Subhead`](https://primer-lookbook.github.com/view-components/lookbook/inspect/primer/beta/subhead/default) at the start of each to give it a title. When using Subheads, we recommend implementing individual Save buttons for each section (using the <em>Secondary</em> style). If a section only contains `Toggle switch` elements, a separate Save button is not necessarily (since the Toggle sends its own server request on interaction).

If a form does not use Subhead sections, then there should be a single 'Save' (using the <em>Primary</em> style) button at the end.

## Form width

In Primer, form elements automatically take the width of the container. In certain cases (especially Settings pages), full-width input fields will look strange. In this case, form inputs will need to have a smaller width. A good rule of thumb is to fit the size of the fields to the expected length of the user input. Date fields can for example be rather small, as they are limited in length. The name of an object on the other hand can be quite long, so the field is expected to be larger.

In OpenProject, each form element has its own container. It is thus possible to define the container width for each input. This width will define both the visual width of the field but also the max width of the caption field (where the line breaks).

The options are:

- <strong>:auto</strong> => width: auto
- <strong>:small</strong> => max-width: min(256px, 100vw - 2rem)
- <strong>:medium</strong> => max-width: min(320px, 100vw - 2rem)
- <strong>:large</strong> => max-width: min(480px, 100vw - 2rem)
- <strong>:xlarge</strong> => max-width: min(640px, 100vw - 2rem)
- <strong>:xxlarge</strong> => max-width: min(960px, 100vw - 2rem)
Comment on lines +34 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A screenshot would be worth a thousand words.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also knowing that multiple width are available does not help making a choice. If there is a rule, here would be a good place to make it explicit.



<%= embed Patterns::FormsPreview, :default, panels: %i[] %>

## Vertical spacing

By default, form elements do not have proper vertical spacing in Primer. We recommend a 16px (`stack/gap/normal`) vertical separate between individual elements. There is an [open issue in Primer's GitHub](https://github.com/primer/view_components/issues/3042) to fix this.

Until this is fixed at a component level, please do not manually apply form padding.

An alternative approach is to wrap individual form elements using `Form group`. Please only use this sparingly and only when it is absolutely necessarily.
1 change: 1 addition & 0 deletions lookbook/docs/patterns/16-settings-pages.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
When working on Settings pages, please refer to the Forms pattern for information on how to implement form elements.
11 changes: 11 additions & 0 deletions lookbook/previews/patterns/forms_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module Patterns
# @hidden
class FormsPreview < ViewComponent::Preview
# @display min_height 500px
def default
render_with_template
end
end
end
60 changes: 60 additions & 0 deletions lookbook/previews/patterns/forms_preview/default.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<%
custom_width_form = Class.new(ApplicationForm) do
form do |f|
f.text_field(
name: :ultimate_answer,
label: "Auto",
caption: "Takes container width",
required: true,
input_width: :auto
)

f.text_field(
name: :ultimate_answer,
label: "Small",
required: true,
input_width: :small
)

f.text_field(
name: :lots_of_text,
label: "Medium",
required: true,
input_width: :medium
)

f.select_list(
name: "cities",
label: "Large",
caption: "All widths also work on Select fields",
include_blank: true,
required: true,
input_width: :large
) do |city_list|
city_list.option(label: "Lopez Island", value: "lopez_island")
city_list.option(label: "Bellevue", value: "bellevue")
city_list.option(label: "Seattle", value: "seattle")
end


f.text_field(
name: :lots_of_text,
label: "XLarge",
required: true,
input_width: :xlarge
)


f.text_field(
name: :lots_of_text,
label: "XXLarge",
required: true,
input_width: :xxlarge
)
end
end
%>

<%= primer_form_with(url: "/foo") do |f| %>
<%= render(custom_width_form.new(f)) %>
<% end %>
Loading