When designing a form, start with an explicit saving pattern. Avoid mixing explicit and automatic save patterns on a single page with multiple forms, and never mix save patterns in a single form. For example: if I upload a profile photo in the "Public profile" form, that change should not be saved until I explicitly submit the whole form.
Explicitly saved forms can be saved by clicking a submit button or by pressing Enter while focused on an input.
If there is an error saving the data, the user's data should be preserved in the form and they should be given feedback about the failure.
Separate auto-saving controls from an explicitly saved form
Don't mix auto-saving controls and explicitly saved controls in the same form
If a user tries to navigate away from a page with a form that has unsaved changes, you have the option to warn them that their changes will be lost using the
beforeunload event. Modern browsers prevent developers from customizing the
alert message, so we're limited to a generic message like "Do you want to leave this site? Changes you made may not be saved."
To ensure your forms are accessible, you should use explicit saving (and not automatic saving) in declarative controls. These are:
<select> dropdown menus
Use save and cancel buttons in dropdowns that allow multiple selections
Don't automatically save selections once the dropdown is closed
There are a few issues to bear in mind with autosaving declarative controls.
<select> dropdowns: Similarly to radio button groups, options could be selected when a user focuses the select and uses the arrow keys to read through each option.
When data is not automatically saved after the user makes changes, buttons are used to submit or cancel the changes.
All configuration flows should have calls to action that include an obvious active verb such as "Create", "Save", "Delete", or "Update" (for example, "Create" a new repository, "Add" an SSH key to your profile, "Save" security preferences, "Update" a repository's description, "Delete" an old email address).
When defining these calls to actions, make sure to:
Use descriptive text with an active verb
Don't use vague text
For more guidance on button usage, see the button documentation.
Controls all belong to one form
A form with a button to save and a button to cancel
Controls divided into multiple sections
Do not disable or hide a form's save button even if the form is invalid or has not been changed. Disabled buttons cannot be focused using the Tab key, and disabled button styles are typically low-contrast and difficult to read.
Always keep the save button enabled
Don't disable the save button if the form is invalid or unchanged
Place save buttons somewhere intuitive and easily accessible.
Have one save button per form
Don't have one save button per section of a form
If there is a button to submit and a button to cancel, the cancel button should go to the right of the submit button.
Default to placing the submit button at the bottom left of the form. Labels and inputs are left-aligned and run from top-to-bottom, so users would naturally move their eyes down and to the left.
If there is a button to submit and a button to cancel, the button to cancel should go to the left of the submit button.
If the save button is used in a dialog, place the button at the bottom right of the dialog. Right-aligned dialog buttons feel familiar because it's a common pattern across various platforms such as Windows, macOS, and Android.
If the button is used to send a message such as a comment on an issue, right-align the button below the text area. This is where GitHub has traditionally placed the Submit button for issues and pull requests, and it's common practice in other apps to place a Send button to the right.
To simplify the interface, some content may be edited inline without taking the user to a separate flow.
An input used for inline editing should have a save button placed very close to visually connect the input with the button.
If you believe your submit button will not be intuitive or easily accessible using any of the placement options listed here, you may consider alternatives and optionally propose a new Primer pattern.
Automatic saving applies changes as they are made. Automatic saving should be used when the user expects instant feedback from the change they made.
If a form field is saved automatically, it should be obvious whether or not it saved without using text or visual indicators. A visual indicator for whether or not a form field has been saved successfully could be mistaken as a validation status.
To reduce UI and give instant feedback, you should use automatic saving (and not explicit saving) for imperative controls. These are:
<select> dropdowns or part of an explicitly saved form. Single-select dropdowns behave like a radio dial: the station starts playing as soon as you select it.
Semantic menus should only have a list of options to select from and should not have a save button in their dropdown. As soon as additional features (search inputs, filters, tabs, etc) are added, the component should be treated like a dialog with a button to submit and a button to cancel.
If the change is not obvious within the user's viewport, provide feedback to let the user know that the change occurred successfully.
Before submitting a form with potentially destructive consequences (for example, delete a repository), ask the user to confirm they want to submit the form.
For risky changes, provide a way to undo those changes after saving.
After merging a pull request, a button appears to revert the changes
When creating new content like issues, discussions, or even larger entities such as repositories or organizations, you may redirect the user to the entity they just created at the end of the flow.
In some cases, such as forking or using a template, you may need to hold the user at a waiting page while the entity is generated. In these cases, make the user feel confident that something is happening and that their configuration details will not be lost.