Crocoblock / suggestions

The suggestions for CrocoBlock project
191 stars 78 forks source link

JetFormBuilder - Ultimate checklist for improving basic features and accessibility #7503

Open edgb0lw opened 2 months ago

edgb0lw commented 2 months ago

YOU CAN IGNORE THIS REQUEST AS I HAVE MADE IT BEFORE, BUT IT WAS ACCIDENTALLY DELETED SOMEHOW


This report may seem dull, but it's crucial. I've been using Jet Forms for a while now and I'm impressed. So many features! However, there are still many must-have features missing or they haven't been implemented well. I urge you to take the following points seriously and prioritize them. Please work on these before adding new features to your Form Builder, as they are critical for loading times, user-friendliness, form operation, and form effectiveness (and many of them are easy to implement).

Small errors

Redundant wrapper div

If the attributes data-is-block and data-jet-inited are somehow important, they can be applied to the wrapper div tag above and remove the div.

unnecessary-wrapper-div

Redundant (duplicated) referrer in the hidden fields

There are two fields for essentially the same value, so one is redundant. I would remove the field _jet_engine_refer and leave _wp_http_referer intact.

hidden-fields-referrer-duplicate

Redundant hidden fields

Some hidden fields, which can all be present, appear regardless of the form, even though they are rarely needed. Please only add them when needed and add checkboxes to the respective form settings to determine which hidden fields should be loaded (the default should be none).

_wp_http_referer: Currently only displayed if "Validation" > "Enable form safety" (WP nonce) is enabled in the form settings (which is currently the case, great, so leave it as is). Since I mentioned earlier that the hidden field _wp_http_referer is redundant, it should be loaded under the following conditions:

hidden-fields-list

Honeypot improvements

Here are the improvements I would make:

  1. The hidden field name is currently _jfb_email_hp_. This is not ideal as it sounds quite generic. It's better to use the well-known standard name email. This increases the chances of a bot filling out this field.
  2. Add a regular text field above the email field for "Name" with the field name name. Having redundancy is a good practice.
  3. The inputs in the honeypot have an incorrect autocomplete attribute. The value should be off instead of nope.
  4. You're currently using inline styles to visually hide the honeypot. Please use a class for this purpose, such as jfb-visually-hidden (avoid using the word "honeypot" in any way, as some bots might check for this).
  5. Add the tabindex="-1" attribute to the honeypot HTML wrapper to ensure that the element cannot be focus via keyboard accidentally
.jfb-visually-hidden {
    position: absolute;
    width: 100%;
    overflow: clip;
    clip-path: inset(50%);
    user-select: none;
    -webkit-user-select: none;
}
  1. The HTML for the honeypot should be rendered at the very bottom just before the submit button instead of at the beginning of the form. If the form is within a dialog HTML element, the first focusable element would typically be focused. However, if this is an input that has been hidden via CSS, it won't work.

Since I mentioned in point 1 that the IDs should be simple to catch bots, you should add a note below the honeypot option stating that this will block the IDs name and email and they cannot be used anymore, to avoid confusing users about why they can't use these IDs for their fields. As an example, you can mention that if you add a "Name" or "Email" field, you should set the field names to something like _name and _email.

honeypot-improvements

Label HTML tag

Please remove the option Fields label HTML tag! It only confuses inexperienced users, and your default value is simply wrong and not accessibility-friendly. Provide labels with the HTML tag label by default.

Important features

Hidden select field placeholder

The only option is that you can disable the placeholder (disabled attribute). What's missing is the ability to hide it (hidden attribute) for better user-friendliness.

Without hidden attribute

https://github.com/Crocoblock/suggestions/assets/154816849/8f1e753b-21fc-47b7-a1a9-d6737431c10f

With hidden attribute

https://github.com/Crocoblock/suggestions/assets/154816849/674f5843-953a-43f4-b371-4bc36c0ea664

Missing input attributes

Each input should have options in the field settings tab where you can manage all important attributes:

Issue with mandatory field hint

Many forms on the web get this wrong... A form typically has more mandatory fields (if you mark everything, you mark nothing in the end) than optional ones, so it makes sense to mark only those that are optional.

Therefore, add another option for labels belonging to optional fields. Do not name the HTML class jet-form-builder__required, but jet-form-builder__label-type-suffix. This element will then display either the value for optional or mandatory fields. ALSO: If nothing is filled in for the "Required mark" or "Optional mark" options, the HTML suffix element should not be rendered anymore.

Current situation

field-label-suffix-current-situation

Suggestion (optional field example)

field-label-suffix-suggestion-type-optional

Suggestion (required field example)

field-label-suffix-suggestion-type-required

Password field switch checkbox

There should be an option for the password field to display a checkbox below the field. When checked, it changes the password field to type="text". This option should be enabled by default as it's a very useful feature.

Regular file input

Provide us with the option to choose whether to render the regular file input (type="file") or the input that displays all the upload features with JavaScript. Sometimes we just want the regular input.

No success message

In many forms I've built so far, I've redirected the user or done something else afterward anyway. It would be great to have an option to completely disable the success message when submitting the form (i.e., not render it in the HTML at all). Because if the user doesn't stay on the page after successfully submitting the data and then briefly sees a message flash, it can be confusing.

Custom messages

Currently, for each form, you have to manually enter all submission messages if you want to use custom text. It would be great to have global options for this, so that in the plugin settings, you can override the defaults for these fields, which will then be used as the default for every form. This saves a lot of time and allows you to globally change messages if you have many forms.

global-general-messages

Furthermore, three message fields are missing:

Custom message if the CSRF token is invalid (currently only "csrf_failed" is displayed).

https://github.com/Crocoblock/suggestions/assets/154816849/9bb38826-560d-4a6f-9eca-58b604289c7a

Custom message if the WP nonce is invalid (currently only "nonce_failed" is displayed).

https://github.com/Crocoblock/suggestions/assets/154816849/780a1a23-4b0d-4270-8099-9e146d01b893

Custom message if the honeypot was filled out (currently only "honeypot" is displayed).

https://github.com/Crocoblock/suggestions/assets/154816849/9d9d147b-d7d9-4eb4-b532-2932c065293a

Incorrect HTML markup

Checkboxes and radio buttons

The HTML structure of custom checkboxes and radio buttons is rather poor. Additionally, the layout breaks if you include HTML a elements in the label text (since the tag for the text is a span), which is sometimes necessary (for privacy policies, terms of service notices, etc.).

checkboxes-and-radio-buttons-html

I have created a CodePen for good custom checkboxes and radio buttons. Please modify yours accordingly...

ALSO: You are using the wrong HTML markup for checkboxes and radio buttons! Each label should have the legend tag, and the HTML wrapper for the entire field should use the fieldset tag.

Without fieldset and legend

checkboxes-and-radio-buttons-without-fieldset-legend

With fieldset and legend

checkboxes-and-radio-buttons-with-fieldset-legend

You should also add a new form Gutenberg block for the fieldset tag with the legend so that users can manually group inputs. I mentioned earlier that you should always use these tags for checkbox and radio inputs, but sometimes you also need a fieldset for regular inputs (e.g., three text inputs for the date that belong together, like "Year", "Month", "Day"). This block should also have the option to add the disabled attribute.

Field hint text

Most sites display the field hint text below the field, but this is a mistake. It causes users to read beyond the input to get all the information. It also means that the content may be cut off by the browser's autofill routine or on-screen keyboard when the input is focused.

Please place it above the input for easy access.

field-hint-text-above-input

Field error text

Placing errors below the input is problematic as they could be cut off by the browser's autofill routine or on-screen keyboard when the input is focused. Therefore, users may need to dismiss the suggestion or close the keyboard to view the error.

Please place it above the input for easy access.

field-error-text-above-input

Please also add an icon to the error message to make it even more noticeable and ensure that users with color blindness can still notice it. The HTML code for this would look as follows:

<div class="jet-form-builder__label-error">
    <i class="jet-form-builder__label-error-icon fas fa-circle-exclamation"></i>
    <div>Error message</div>
</div>

Label content

Earlier, I mentioned that the hint end error texts should be displayed above the field. Specifically, they should all be within the label tag. This has the advantage of providing a large clickable area, which is very helpful for mobile users. So, with the changes together, the HTML block for the label area should look like this:

<label class="jet-form-builder__label" for="field-id">
    <div class="jet-form-builder__label-text">
        Field name
        <span class="jet-form-builder__label-type-suffix">(Optional)</span>
    </div>
    <div class="jet-form-builder__label-hint">Hint text</div>
    <div class="jet-form-builder__label-error">
        <i class="jet-form-builder__label-error-icon fas fa-circle-exclamation"></i>
        <div>Error message</div>
    </div>
</label>

Validation

I know it sounds a bit strange at first, but live input validation is not recommended; it only confuses and annoys the user. The best approach is validation that only occurs when the submit button is pressed. Only then the user is truly ready to receive feedback on whether they have filled everything out correctly. I mean, just look at how annoying it is (even built-in HTML5 validation should be avoided; it has the same problem and is also inconsistent across different browsers):

https://github.com/Crocoblock/suggestions/assets/154816849/004bde79-7726-4e99-8f87-3404e936dfe1

Additional validation type

Please add another validation type named "Custom: After Submit" or similar.

additional-validation-type

If this validation type is selected for the form, no fields should be validated on the frontend (i.e., no required attribute anywhere). Instead, the form should only be checked when the submit button is clicked.

When this validation type is selected, you should be able to specify a custom error message for each input or fieldset in the field settings, which will be displayed in the error summary and above the field.

If you set up a custom validation (server-side callback) for a field, it should also be displayed after the submit (when this validation type is selected).

The global error message (e.g., Validation error, Captcha validation failed, etc.) should also be displayed in the error summary.

More on all of this directly below:

Then, when there are errors, the following things should happen:

focus-label-above-input

This is how all the changes should look together:

error-summary

The HTML markup for the summary should look like this:

<div>
    <div role="alert" class="jfb-error-summary">
        <h2 class="jfb-error-summary__heading">There’s a problem</h2>
        <p class="jfb-error-summary__message">Global error message</p>
        <div class="jfb-error-summary__errors">
            <a href="#field-a">Error message for field a</a>
            <a href="#field-b">Error message for field b</a>
        </div>
    </div>
</div>

Why the empty wrapper div?

"In JAWS 2022, this attribute led to a race condition between the role="alert" attribute and the existing JavaScript that shifts focus when the page loads. Moving role="alert" into its own nested div decouples the race condition and allows screen readers to announce the warning while still being in sequential keyboard navigation mode regarding the error summary."

Furthermore, when this validation type is active, you should default to not validating any of the fields. By default, I think you validate email fields and a few others. Please refrain from doing so and give us full control. By default, nothing should be validated so that we can manually configure everything and have full control.

JavaScript

Please set the default submission type of the form to "AJAX" instead of page reload. It's faster and more modern. Also, please establish the connection using the fetch() method instead of still using XHR. fetch() is more flexible, faster, and modern.

In the "Additional validation type" section, I have suggested my desired validation, which actually requires very little JavaScript. So, when this validation is selected, please only load the required JavaScript, which should be tiny since it doesn't need to do much.

Please make the form (when the "Additional Validation Type" is selected) fully available without JavaScript. With my proposed method, JavaScript is not strictly necessary. Therefore, the form should be submitted via AJAX, and if JavaScript is not available, a page reload should occur.

It would also be great if you could use Vanilla JS instead of jQuery. I know, this is far more easier said than done. It has become unnecessary nowadays and has significant page speed issues.


I know that was a lot, but please prioritize these things as new features to implement. I have spent a long time focusing on easy-to-use forms and accessibility, and they are simply the foundation of everything. If all implemented, they would make the plugin infinitely better and provide users with a better experience! :)

Thank you in advance for reading this long report! :) Edgar