From 42797bdd3f9802e7eaee4c6ffb717cc37064f208 Mon Sep 17 00:00:00 2001 From: Mike Perrotti Date: Fri, 5 Aug 2022 11:09:45 -0400 Subject: [PATCH] Interface guidelines for forms (#261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP * WIP * adds interface guidelines for forms * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Inayaili León * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * Update content/ui-patterns/forms.mdx Co-authored-by: Cameron Dutro * addresses feedback from design infrastructure teammates * removes unnecessary heading * updates action menu example image * updates focus styles in supporting graphics * Update content/ui-patterns/forms.mdx * updates guidance about placeholder text * adds guidance on error summaries, removes checkbox group validation example * addresses feedback about unclear guidelines * Update content/ui-patterns/forms.mdx Co-authored-by: Vinicius Depizzol * adds guidance about form control sizing * shortens intro paragraph, removes guidance about hiding labels * updates example images * renders gifs as HTML video elements * adds custom video player * adds aria labels to icon buttons * addresses feedback about formcontrol anatomy diagrams Co-authored-by: Inayaili León Co-authored-by: Cameron Dutro Co-authored-by: Vinicius Depizzol --- content/components/textInputField.mdx | 4 + content/ui-patterns/forms.mdx | 581 ++++++++++++++++++ content/ui-patterns/index.mdx | 9 + package.json | 2 +- .../gatsby-theme-doctocat/mdx-components.js | 3 + src/@primer/gatsby-theme-doctocat/nav.yml | 2 + src/CustomVideoPlayer.tsx | 55 ++ yarn.lock | 10 +- 8 files changed, 660 insertions(+), 6 deletions(-) create mode 100644 content/components/textInputField.mdx create mode 100644 content/ui-patterns/forms.mdx create mode 100644 src/@primer/gatsby-theme-doctocat/mdx-components.js create mode 100644 src/CustomVideoPlayer.tsx diff --git a/content/components/textInputField.mdx b/content/components/textInputField.mdx new file mode 100644 index 000000000..b399347fe --- /dev/null +++ b/content/components/textInputField.mdx @@ -0,0 +1,4 @@ +--- +title: TextInputField +status: Alpha +--- diff --git a/content/ui-patterns/forms.mdx b/content/ui-patterns/forms.mdx new file mode 100644 index 000000000..31c5181e0 --- /dev/null +++ b/content/ui-patterns/forms.mdx @@ -0,0 +1,581 @@ +--- +title: Forms +--- + +import {Box, Heading, Link} from '@primer/components' + + + Primer's form design guidelines aim to minimize the effort and cognitive load required to complete a task that + requires data input from the user. For example: creating a new repo, configuring settings, and logging in. + + +## Form control anatomy + +![diagrams labeling the anatomy of a text field and a checkbox field](https://user-images.githubusercontent.com/2313998/171692166-43d45c4b-509a-4f68-9e8b-1577658b493e.png) + +### Label (required) + +Labels should be descriptive and concise: aim for no more than 3 words. Write labels in sentence case. Examples: "Repository name", "Payment method". + +If you're having trouble keeping label text short, consider using a [caption](#caption) to provide more context. + +Placeholder text is never an acceptable substitute for a label because: + +- The placeholder text disappears as soon as the input has a value +- Placeholder text colors are typically too light to meet the minimum color contrast ratio required for accessibility +- Screen readers do not read placeholder text as a label + +### Required field indicator + +When a field is required to have a value, it should be visibly marked as required. An individual checkbox or radio button cannot be marked as required. + +For more information, see the [required fields](#required-fields) section. + +### Input (required) + +The input is what the user interacts with to set the value of the form control. You may pre-fill inputs with smart default values, but be careful about making too many assumptions about what a user wants or needs. + +### Caption + +A caption may be used to provide additional context about the field to help users fill in the correct data or explain how the data will be used. Caption text should be as short as possible. + +Caption text may be displayed alongside a validation message, or it may be hidden if it only provides redundant information. + +Caption text may be used to augment the [label](#label), but should not be redundant with the label or any other parts of the form control. If the caption feels redundant, try removing it. + + + + + Use caption text that shows new information and provides helpful context + + + + Don’t use caption text that is redundant + + + +### Validation message + +A single validation message may be displayed to provide helpful information for a user to complete their task. For example: explain why a value is invalid so they can correct it and submit the form. + +An individual checkbox or radio should not have its own validation message or style. + + + + + Show a validation message for the group of inputs + + + + Don’t show a validation message for each input + + + +Information from the caption should not be repeated in the error message. Show the validation message and remove the caption. A validation message makes the field easier to spot when a user is scanning for invalid fields. + + + + + Hide a caption that is redundant with the validation message + + + + Don’t show a repetitive validation message + + + +For more information about form validation, see the [validation guidelines](#invalid-input). + +## Input methods + +### Open-ended text + +![Text input, open-ended autocomplete text input, plain text input, textarea](https://user-images.githubusercontent.com/2313998/170069913-325a987b-9a75-4e83-826a-bb7ae73d6831.png) + +Use an open-ended text field when the field does not have a list of possible values. If the input is able to suggest values, use [autocomplete](#autocomplete) to allow users to pick a value or enter their own. + +### A set of selectable options + +![Action menu, autocomplete input with limited options, checkbox group, radio group, select](https://user-images.githubusercontent.com/2313998/170069915-657a6291-2729-4e3e-abbc-b7611f8051dc.png) + +Show a set of selectable options when there is a finite number of possible values. + +## Structure + +Forms should have a structure that makes it easy for users to scan. Forms that flow vertically are easier for sighted users to scan visually. + + + + + Default to vertically stacked form controls + + + + Don’t lay out forms that flow into columns just to reduce the vertical space used by the form + + + +### Order of form controls + +Form fields should be in a predictable order that flows intuitively. + +To achieve an intuitive flow: + +- Order fields by their relative level of importance +- Keep related fields near each other +- When possible, keep inputs that require keyboard input near each other so that users who use a mouse don't have to switch back and forth between clicking and typing + +### Sizing form controls + +#### Hint at the expected length of the value + + + + + + Form controls should be sized to fit their value. Start with the browser default width, and adjust as needed. + + +
  • + Single-line text inputs get a default width set by the browser, but their width can be changed to fit the + approximate length of their text. +
      +
    • + If the text length could fall into a wide range, then either keep the browser-default length, or fill the + width of its parent. +
    • +
    +
  • +
  • + Multi-line text inputs (a [Textarea](#textarea)) get a default width and height set by the browser, but its + dimensions can be changed to fit longer blocks of text. +
  • +
  • + Select dropdown widths are set by the browser to be as wide as the text of it's longest option. We shouldn't + override this width unless it's to make the dropdown fill the width of its parent. +
  • +
  • Checkbox and radio inputs have static dimensions
  • +
    +
    +
    + +#### Maintain page hierarchy + +Input components ship with size variants that adjust font size and padding to maintain consistent hierarchy with adjacent elements. + +### Grouping form controls + + + visually grouped of related inputs + + When there is a collection of closely related fields, they should be labeled and visually grouped together. For + example: putting form controls closer together. + + + +### Progressively disclosed form controls + + + form section where controls are hidden until the feature is enabled + + To keep forms concise, you may choose to hide or show form controls based on selections the user has made. + + + +#### Nested form controls + +Sometimes, progressively disclosed form controls can be visually nested under a parent form control. A common pattern is to use a checkbox or radio “checked” state to decide whether to show a related form control. + + + Primary discipline radio buttons, selected 'Other' option reveals a text input + + If the parent form control provides sufficient visual context, you may visually hide the label. However, you must + specify text for a visually hidden label that is accessible to screen readers. + + + + + + Checkbox that progressively discloses a dropdown with an internal label + Checkbox that progressively discloses a labeled select input + + + If the parent form control does not provide sufficient context, a visible label should be shown. Make sure the label + of the nested form control doesn’t clash with the label of its parent form control. + + + +See [progressive disclosure](/ui-patterns/progressive-disclosure) for more information. + +## Validation + +Use Primer instead of browser-native validation UI. Browser-native validation messages are not accessible to screen readers, and they visually clash with Primer styles. + +### Validation statuses + + + + input with forbidden characters + Error messages: An invalid field should always have a message explaining why the value does not pass validation. The message should explain why the value is invalid, and unblock users from completing their task by guiding them to a valid value. + + + + valid repo name success + Success messages: A success message may be used when a user might need extra assurance that the field's value is valid. For example: when creating a repository name, it’s nice to be assured that the name is available and valid. + + + +### Validation on submit + +The default behavior of the web is to perform validation when the user attempts to submit the form. This lets the user flow quickly through the form without interruption. + +When the form fails validation, guide the user to the invalid inputs: + +- If the form has 3 or more errors, you may show an [interactive summary of errors](#interactive-summary-of-errors) +- If an interactive summary of errors is not shown, the first invalid input should be focused and scrolled into the viewport + +After a form has been submitted and failed validation, you may switch to inline validation to provide quicker feedback. + +#### Interactive summary of errors + + + a form for biographical information that has three invalid inputs +
    + + In a flash alert at the top of the form, list the invalid inputs + as anchor links. When the link is activated, place focus in it's corresponding input. + + + When the flash alert appears, it should be focused. + +
    +
    + +### Inline validation + + + Inline validation offers immediate feedback, but be sure to consider the following drawbacks. + +
      +
    • There is a negative impact on perceived performance when validating server-side.
    • +
    • When a screen reader user moves focus from the invalid input to the next form control, they will be interrupted by the validation message of the previous form control.
    • +
    +
    + + + + + If the form control is in a valid state, validation should be performed until after the user has made a change to + the input and has removed focus from the input. + + + + + + + Don't attempt to validate an input before the user is done with it. Validation may be performed as the user is + typing or making their selection, but only after the first time the input has been validated and + the input is in an invalid state. This gives the user early positive feedback by removing the error + if the user makes a change that fixes it. + + + + + + + If the form control’s validation is likely to take more than 1 second, show a loading indicator. + + + +## Submission + +Forms should follow consistent patterns for [submitting and saving data](/ui-patterns/saving). + +## Related components + + + +
    + Action menu with selection +

    + If the parent form control provides sufficient visual context, you may visually hide the label. However, you must + specify text for a visually hidden label that is accessible to screen readers. +

    + Primer React implementation +
    +
    + + + +
    + Autocomplete +

    + An autocomplete input renders a text input that allows a user to quickly filter through a list of options to pick + one or more values. +

    + Primer React implementation +
    +
    + + + +
    + Checkbox group +

    A set of checkboxes to let users make one or more selections from a short list of options

    + Primer React implementation +
    +
    + + + +
    + Form control +

    A form control renders a labelled input and, optionally, associated validation text and/or hint text.

    + Primer React implementation +
    +
    + + + +
    + Radio group +

    A set of radio inputs to let users make a single selection from a short list of options

    + Primer React implementation +
    +
    + + + +
    + Select dropdown +

    A select input may be used when a user needs to select one option from a long list

    + Primer React implementation +
    +
    + + + +
    + + Textarea + +

    A text area is used to put multiple lines of text in an input

    + Primer React implementation +
    +
    + + + +
    + Text input +

    + A text input is used to set a value that is a single line of text. See the list of{' '} + types in the MDN docs. +

    + Primer React implementation +
    +
    diff --git a/content/ui-patterns/index.mdx b/content/ui-patterns/index.mdx index 93f9a6842..797cf23cb 100644 --- a/content/ui-patterns/index.mdx +++ b/content/ui-patterns/index.mdx @@ -32,6 +32,15 @@ import {Grid, Flex, Box, Link, Text, Label} from '@primer/components' Feature onboarding Onboarding is a virtual unboxing experience that helps users get started with a feature. This is a guide for designing onboarding for the product and does not include what to do for marketing pages, email announcements, social media, etc. + {/*
    + + + +
    */} +
    + Forms + Forms are used to complete tasks that require data input from the user. These guidelines aim to minimize the effort and cognitive load required to complete a task that involves a form. +
    {/*
    diff --git a/package.json b/package.json index 07fd6ffd4..5df79c7af 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@primer/gatsby-theme-doctocat": "^3.1.1", - "@primer/octicons-react": "^11.0.0", + "@primer/octicons-react": "^17.2.0", "eslint": "5.8.0", "eslint-plugin-github": "1.6.0", "gatsby": "^2.32.13", diff --git a/src/@primer/gatsby-theme-doctocat/mdx-components.js b/src/@primer/gatsby-theme-doctocat/mdx-components.js new file mode 100644 index 000000000..f62d5f739 --- /dev/null +++ b/src/@primer/gatsby-theme-doctocat/mdx-components.js @@ -0,0 +1,3 @@ +import CustomVideoPlayer from '../../CustomVideoPlayer' + +export default {CustomVideoPlayer} diff --git a/src/@primer/gatsby-theme-doctocat/nav.yml b/src/@primer/gatsby-theme-doctocat/nav.yml index 014521368..c1b321e94 100644 --- a/src/@primer/gatsby-theme-doctocat/nav.yml +++ b/src/@primer/gatsby-theme-doctocat/nav.yml @@ -43,6 +43,8 @@ url: /ui-patterns/empty-states - title: Feature onboarding url: /ui-patterns/feature-onboarding + - title: Forms + url: /ui-patterns/forms - title: Messaging url: /ui-patterns/messaging - title: Progressive disclosure diff --git a/src/CustomVideoPlayer.tsx b/src/CustomVideoPlayer.tsx new file mode 100644 index 000000000..52e53b33f --- /dev/null +++ b/src/CustomVideoPlayer.tsx @@ -0,0 +1,55 @@ +import React from 'react' +import {Box} from '@primer/components' +import {ColumnsIcon, PlayIcon} from '@primer/octicons-react' + +const CustomVideoPlayer = (props: React.HTMLProps) => { + const videoElement = React.useRef(null) + const [isPlaying, setIsPlaying] = React.useState(props.autoPlay) + + const playVideo = () => { + videoElement.current.play() + setIsPlaying(true) + } + + const pauseVideo = () => { + videoElement.current.pause() + setIsPlaying(false) + } + + return ( + + {/* component users would be able to pass their own children */} + {/* eslint-disable-next-line jsx-a11y/media-has-caption */} + + ) +} + +export default CustomVideoPlayer diff --git a/yarn.lock b/yarn.lock index 9db7ffef2..9f05df897 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1689,11 +1689,6 @@ styled-system "^5.0.18" worker-loader "^3.0.2" -"@primer/octicons-react@^11.0.0": - version "11.3.0" - resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-11.3.0.tgz#794641d95ff5749a9438a2e0c201956b2a377b60" - integrity sha512-4sVhkrBKuj3h+PFw69yOyO/l3nQB/mm95V+Kz7LRSlIrbZr6hZarZD5Ft4ewdONPROkIHQM/6KSK90+OAimxsQ== - "@primer/octicons-react@^13.0.0": version "13.0.0" resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-13.0.0.tgz#a7f2288fd9cf9cabc1e75553a0dd9f00d74b68c1" @@ -1704,6 +1699,11 @@ resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-16.2.0.tgz#702f59169dd763dc03e613b0e881aa715da37a5c" integrity sha512-943t5kkVRt+/hxVnKS27xweUp4lXFxwJaTrsit1C1xBB4kqdjzmYGpU84zwKsNyyV2Ch7may3umKjbI/mFBPPQ== +"@primer/octicons-react@^17.2.0": + version "17.2.0" + resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-17.2.0.tgz#c08ab5cba5164638899f40fa842e6745160f0c19" + integrity sha512-1yYKU6jOtKJlbMKjXYWXeMcI1Y0R70hmS01DSQ3G7+pY9MQDEZss9tgwFaKj7tgw+L3eFojivzo4oqVNfriKmw== + "@primer/primitives@4.8.1": version "4.8.1" resolved "https://registry.yarnpkg.com/@primer/primitives/-/primitives-4.8.1.tgz#05f76e47f67018514fd54b35ca615b9d27ef2a46"