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

Comments Form blocks #38107

Open
SantosGuillamot opened this issue Jan 20, 2022 · 5 comments
Open

Comments Form blocks #38107

SantosGuillamot opened this issue Jan 20, 2022 · 5 comments
Labels
[Block] Post Comments Form Affects the Comments Form Block New Block Suggestion for a new block [Type] Tracking Issue Tactical breakdown of efforts across the codebase and/or tied to Overview issues.

Comments

@SantosGuillamot
Copy link
Contributor

SantosGuillamot commented Jan 20, 2022

1. Goal of the project

The purpose of this project is to make the Comments Form customizable through blocks. In the same way that you can change the footer or the header with blocks and without code, it would be nice to do the same with this form.

Right now, in order to use the Comment Form in a FSE site, there is a Post Comments Form block which is just a wrapper around the comment_form function (explained later), but it doesn’t allow users to edit it through blocks.

Apart from that, it could be interesting to analyze if it makes sense to make some of these blocks (like the textarea, submit button…) reusable in other forms.

2. Out of scope

New functionalities to the Comments Form wouldn’t be covered in this project. It would consist of replicating the current form but making everything customizable from the editor.

3. Existing solution

Before diving into how the comment form blocks could be implemented, it’s interesting to understand the current workflow to post a new comment.

Excalidraw link
ux-workflow

As we can see, depending on the global settings and if the user is logged in or not, the interface will be different.

In classic WordPress themes, the common way to display the comment form is to use the comment_form() function, which returns the proper HTML depending on the args. It is usually added in the themes comments.php file. For example, the twentytwenty-one theme adds it this way:

comment_form(
        array(
            'logged_in_as'       => null,
            'title_reply'        => esc_html__( 'Leave a comment', 'twentytwentyone' ),
            'title_reply_before' => '<h2 id="reply-title" class="comment-reply-title">',
            'title_reply_after'  => '</h2>',
        )
    );

You can check all the args in the comment_form documentation. This way, developers are able to modify the HTML returned by the function.

Apart from that, it includes a bunch of actions and filters that allow plugin/theme developers to interact/modify it. Probably, many current plugins are already using them, so this has to be taken into account for backward compatibility. These old hooks should be included, whenever possible, inside the new block implementations.

Once the form is filled and submitted, the data is sent to /wp-comments.php , which processes it. At this point, it checks if the form is valid and, depending on the result, it returns an error or redirects the user to the new comment.

  • If there is an error, it returns it message without any redirection. There are numerous errors it could return. For example if the name and email are required, if the content is empty, if the comment is duplicated…
    screen-shot-2021-11-17-at-14 22 34

  • If the submission is correct, but the comment requires approval (based on the global settings), it redirects the user to the post with a hash, so only the user can see the unapproved comment, and it could include a message saying the comment is awaiting moderation. The url would have this format http://mydomain.com/hello-world/?unapproved=2&moderation-hash=XXX#comment-2
    screen-shot-2021-11-17-at-14 35 51

  • If the submission is correct, and it doesn’t require approval, it is just redirected to the new comment http://mydomain.com/hello-world/#comment-3
    screen-shot-2021-11-17-at-14 37 17

For future reference, this is the list of actions and filters included in the comment_form documentation:

Actions
These are the actions triggered in the `comment_form()` function:
  1. comment_form_comments_closedLink: Fires after the comment form if comments are closed. When ! comments_open( $post_id ) is true.
  2. comment_form_beforeLink: Fires before the comment form.
  3. comment_form_must_log_in_afterLink: Fires after the HTML-formatted ‘must log in after’ message in the comment form.
  4. comment_form_topLink Fires at the top of the comment form, inside the form tag.
  5. comment_form_logged_in_afterLink Fires after the is_user_logged_in() check in the comment form.
  6. comment_form_before_fieldsLink: Fires before the comment fields in the comment form, excluding the textarea.
  7. comment_form_after_fieldsLink: Fires after the comment fields in the comment form, excluding the textarea.
  8. comment_formLink: Fires at the bottom of the comment form, inside the closing form tag.
  9. comment_form_afterLink: Fires after the comment form.
Filters
These are the filters applied in the `comment_form()` function. Most of them are used to change the form fields HTML.
  1. comment_form_default_fieldsLink: Filters the default comment form fields (author, email, url and cookies).
  2. the_permalinkLink: Filters the display of the permalink for the current post.
  3. comment_form_defaultsLink: Filters the comment form default arguments. Use {@see ‘comment_form_default_fields’} to filter the comment fields.
  4. comment_form_logged_inLink: Filters the ‘logged in’ message for the comment form for display.
  5. comment_form_fieldsLink: Filters the comment form fields, including the textarea.
  6. comment_form_field_commentLink: Filters the content of the comment textarea field for display.
  7. comment_form_field_{$name}Link: Filters a comment form field for display. The dynamic portion of the filter hook, $name, refers to the name of the comment form field. Such as ‘author’, ’email’, or ‘url’.
  8. comment_form_submit_buttonLink: Filters the submit button for the comment form to display.
  9. comment_form_submit_fieldLink: Filters the submit field for the comment form to display. The submit field includes the submit button, hidden fields for the comment form, and any wrapper markup.

4. Potential solution

Just to clarify, this is just a rough initial idea about how the Comment Form blocks could be implemented. We have to properly discuss it and agree on a solution.

A Comment Form template block could be implemented, which could act as a wrapper for its inner blocks. The same way it works in the Comment Query Loop block for example.

Excalidraw link
possible-implementation

Taking this into account, these could be the blocks needed. I’ve included as well the fields, actions, and filters that could be related and a list of potential settings, but I guess this would be better discussed in each individual issue once the structure is clear and they are created.

1 - Comment Form template
This would be the wrapper of the rest of the blocks, and it should include the form settings. One aspect to consider, as mentioned before, is that the interface may change based on if the user is logged in or not.

It isn’t still clear how this should be handled. There is an ongoing conversation to discuss how to handle different interfaces depending on the user state.

If we follow, for example, what WooCommerce Gutenberg Blocks plugin is doing with the cart block, we could add a setting in this wrapper to switch between the different views. For context, this is how it looks in the mentioned plugin:

When “Filled Cart” is selected
screen-shot-2021-11-29-at-14 31 08 (1)

When “Empty Cart” is selected
screen-shot-2021-11-29-at-14 31 52

Related fields

  • id_form
  • class_container
  • class_form
  • format
  • action

Related actions

  • comment_form_comments_closedLink.
  • comment_form_beforeLink.
  • comment_form_topLink.
  • comment_form_logged_in_afterLink.
  • comment_form_before_fieldsLink.
  • comment_form_after_fieldsLink.
  • comment_formLink.
  • comment_form_afterLink.

Related filters

  • comment_form_default_fieldsLink.
  • comment_form_defaultsLink.
  • comment_form_fieldsLink.

Potential settings

  • Change the view between logged in / logged out.
  • Id. Related to id_form field.
  • Classname container. Related to class_container field.
  • Classname form. Related to class_form field.
  • Format. Related to format field.
  • Should we provide a setting to change the action as well?
2 - Title Reply / Reply to
In the same way we could change the view in the template block, we could implement something similar here to switch between new comments and replies.

Related fields

  • title_reply
  • title_reply_to
  • title_reply_before
  • title_reply_after
  • cancel_reply_before
  • cancel_reply_after
  • cancel_reply_link

Related actions

I think there aren’t related actions.

Related filters

  • comment_form_defaultsLink.

Potential settings

  • Setting to change the view between Reply / Reply to.
  • Select heading level (h1, h2, h3…).
3 – Before content
Depending on the view and the settings, the message below the title will be different, but the styles could be reused. Not sure if it makes sense to have a parent block wrapping 3, 4 and 5 or just handle them separately.

Related fields

  • logged_in_as
  • must_log_in
  • comment_notes_before

Related actions

  • comment_form_must_log_in_afterLink

Related filters

  • comment_form_defaultsLink
  • the_permalinkLink
  • comment_form_logged_inLink

I believe 3, 4 and 5 could be wrapped in the same block.

6 – Content

This would be the input of the comment content.

Related fields

  • comment_field
  • comment_notes_after

Related actions

I think there aren’t related actions.

Related filters

  • comment_form_fieldsLink
  • comment_form_field_commentLink
7 – Name
This would be the input for the name. Depending on the global settings, it may be required or not.

Related fields

  • author

Related actions

I think there aren’t related actions

Related filters

  • comment_form_default_fieldsLink
  • comment_form_fieldsLink
  • comment_form_field_{$name}Link
8 – Email

This would be the input for the email. Depending on the global settings, it may be required or not.

Related fields

  • email

Related actions

I think there aren’t related actions.

Related filters

  • comment_form_default_fieldsLink
  • comment_form_fieldsLink
  • comment_form_field_{$name}Link
9 – Website

This would be the input for the website field.

Related fields

  • URL

Related actions

I think there aren’t related actions

Related filters

  • comment_form_default_fieldsLink
  • comment_form_fieldsLink
  • comment_form_field_{$name}Link
10 – Cookies

This would be the input of the cookies field and its message. Depending on the global settings, it may appear or not. I guess we could even overwrite the global setting from the block.

Related fields

  • cookies

Related actions

I think there aren’t related actions

Related filters

  • comment_form_default_fieldsLink
  • comment_form_fieldsLink
11 – Submit button

This block should handle the submit button.

Related fields

  • id_submit
  • class_submit
  • name_submit
  • label_submit
  • submit_button
  • submit_field

Related actions

I think there aren’t related actions.

Related filters

  • comment_form_defaultsLink.
  • comment_form_submit_buttonLink.
  • comment_form_submit_fieldLink.

5. Requirements

I would say there are two main requirements here:

  • Everything should be customizable from the editor.
  • Pre-existing hooks should be included in new blocks so that plugins that interact with the front-end don’t break.

6. References

Relevant actions
These are the actions triggered in the `comment_form()` function:
  1. comment_form_comments_closedLink: Fires after the comment form if comments are closed. When ! comments_open( $post_id ) is true.
  2. comment_form_beforeLink: Fires before the comment form.
  3. comment_form_must_log_in_afterLink: Fires after the HTML-formatted ‘must log in after’ message in the comment form.
  4. comment_form_topLink Fires at the top of the comment form, inside the form tag.
  5. comment_form_logged_in_afterLink Fires after the is_user_logged_in() check in the comment form.
  6. comment_form_before_fieldsLink: Fires before the comment fields in the comment form, excluding the textarea.
  7. comment_form_after_fieldsLink: Fires after the comment fields in the comment form, excluding the textarea.
  8. comment_formLink: Fires at the bottom of the comment form, inside the closing form tag.
  9. comment_form_afterLink: Fires after the comment form.
Relevant filters
These are the filters applied in the `comment_form()` function. Most of them are used to change the form fields HTML.
  1. comment_form_default_fieldsLink: Filters the default comment form fields (author, email, url and cookies).
  2. the_permalinkLink: Filters the display of the permalink for the current post.
  3. comment_form_defaultsLink: Filters the comment form default arguments. Use {@see ‘comment_form_default_fields’} to filter the comment fields.
  4. comment_form_logged_inLink: Filters the ‘logged in’ message for the comment form for display.
  5. comment_form_fieldsLink: Filters the comment form fields, including the textarea.
  6. comment_form_field_commentLink: Filters the content of the comment textarea field for display.
  7. comment_form_field_{$name}Link: Filters a comment form field for display. The dynamic portion of the filter hook, $name, refers to the name of the comment form field. Such as ‘author’, ’email’, or ‘url’.
  8. comment_form_submit_buttonLink: Filters the submit button for the comment form to display.
  9. comment_form_submit_fieldLink: Filters the submit field for the comment form to display. The submit field includes the submit button, hidden fields for the comment form, and any wrapper markup.

7. Questions

  • Does the proposed solution structure make sense? What should be done differently?
  • In the second block of the proposed solution, Title Reply / Reply to, should it be divided into two different blocks or just add a setting to change the view?
  • The blocks 3, 4 and 5 are pretty similar but maybe some users want them to be different. Should they be handled in a wrapper block or individually?
  • Anything not included here that should be considered?
  • Should we include any more requirements?
  • Once the approach is clearer, how this could be divided in specific tasks?
  • Not to be discussed here, but as it will affect the project: how to handle different interfaces depending on the user state?.
@SantosGuillamot SantosGuillamot added the [Type] Overview Comprehensive, high level view of an area of focus often with multiple tracking issues label Jan 20, 2022
@gziolo gziolo added the New Block Suggestion for a new block label Jan 20, 2022
@mtias mtias mentioned this issue Jan 26, 2022
57 tasks
@dmsnell
Copy link
Member

dmsnell commented Mar 2, 2022

We can all acknowledge that this kind of interactive experience is not a challenge within a single block (and within its allowed nested block types if there are any). Spanning across multiple blocks presents a problem not there in a single block: data flow. We're taking a system that was designed as a whole unit (evidenced by the way comment_form() is called in themes) and splitting it into independent parts inside another system that guards the isolation of its parts.

How did you envision this inter-block communication happening? For instance, what is the sequence of events that occurs when we click on that form submit button? How does it find the comment content, the author's name, and the author's email address? When making the relevant API call to the server to submit a comment, how does the comment form know to update itself and how does it do that?

How broadly do we expect people to customize the comment form? Some people or plugins might want to add a captcha challenge; how would that fit in given that it would need to interact with the API call to submit the challenge?

@SantosGuillamot
Copy link
Contributor Author

Thanks for sharing your thoughts 🙂

Just to clarify before trying to answer some of your questions, the goal of this overview issue is just to replicate the behaviour of the current comments form, but using blocks to make it easier to edit the layout and texts. This means that it doesn’t aim to add new functionality and it wouldn’t add any kind of client interactivity yet. I think that is a bigger and more complex project, and it could be covered in a new issue after this one.

what is the sequence of events that occurs when we click on that form submit button?

It could just include an action to .../wp-comment-post.php in the <form action="X">, as it is being done right now. That would go to the server and redirect the user to the comment link (.../test-post/comment-page-2/#comment-3 for example).

How does it find the comment content, the author's name, and the author's email address?

Those fields could be wrapped in a parent Comment Form block. That would organize the HTML properly and it would end up being something like this:

<form action="http://form.local/wp-comments-post.php" method="post" id="commentform">
    <p class="comment-form-comment">
        <label for="comment">Comment</label>
        <textarea id="comment" name="comment"></textarea>
    </p>
    <p class="comment-form-author">
        <label for="author">Name </label>
        <input id="author" name="author" type="text" value="">
    </p>
    <p class="comment-form-email">
        <label for="email">Email</label>
        <input id="email" name="email" type="email" value="" >
    </p>
    <p class="comment-form-url">
        <label for="url">Website</label> 
        <input id="url" name="url" type="url" value="">
    </p>
    <p class="form-submit wp-block-button">
        <input name="submit" type="submit" id="submit" value="Post Comment">
        <input type="hidden" name="comment_post_ID" value="1" id="comment_post_ID">
        <input type="hidden" name="comment_parent" id="comment_parent" value="0">
    </p>
</form>

That should be enough if I'm not mistaken.

When making the relevant API call to the server to submit a comment, how does the comment form know to update itself and how does it do that?

As I said previously, adding client interactivity is out of the scope of this issue, so it would just go to the server and reload the page with the new content.

How broadly do we expect people to customize the comment form?

I assume the main goal is to let people customize easily the layout of the comment form and the different texts included on it. Moreover, with the current form (without blocks), the editor isn't showing the same result as the frontend.

Some people or plugins might want to add a captcha

If there are users adding a captcha using hooks, it should keep working. Ideally, a new captcha block would be created and it could be added just inside the Comments form block.

@ockham
Copy link
Contributor

ockham commented Mar 16, 2022

I think even if we want the (first iteration of) the Comments Form block(s) to strictly reflect the functionality of the comment_form() function (including the redirect upon submit, which is kinda ugly 😝), we still need to present the form inside of the Comment Template (and thus, inside of the Comments Query Loop) -- in the same position as the Reply link that the user clicked. Here's what that currently looks like on the frontend of the Twenty Twenty One theme (i.e. a non-FSE theme):

comment forms

We could reflect this in the editor by mirroring that exact behavior: If the user clicks on any Reply link, it expands into the Comment Form block. This might have some interesting implications: the Comment Form would become another state of the Reply link block, or vice versa -- and the Comment Form sure has a lot of states to handle already, see the spec at the top of this issue 😅

We'd probably need to implement this via a unique "expanded reply link/comment form" marker within the query loop, much like we already handle the currently active (selected) comment within that loop. By default, we'd likely want to expand the comment form at the very bottom (that would allow the user reply directly to the post).

@ClarusDignus
Copy link

I posted my thoughts on the necessity of separate customizable blocks for the comment form heading, "Replying to [...]", and "Cancel reply" here.

@ClarusDignus
Copy link

@ockham

I like the idea of the comment form appearing below the comment being replied to.

For replies to the post, the standard, already-visible comment form should be used.

For replies to comments, regardless of whether the comment being replied to is top-level or nested, the form should appear below the comment as you've illustrated; however, the form shouldn't be indented like the comment being replied to. Otherwise, for deeply nested comments, the comment form will be too narrow. It's best to consistently use the full screen width available. Placing the comment form below the comment sufficiently implies the relationship between the comment form and the comment being replied to, without indentation.

@carolinan carolinan added the [Block] Post Comments Form Affects the Comments Form Block label Apr 25, 2022
@annezazu annezazu added [Type] Tracking Issue Tactical breakdown of efforts across the codebase and/or tied to Overview issues. and removed [Type] Overview Comprehensive, high level view of an area of focus often with multiple tracking issues labels Mar 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Post Comments Form Affects the Comments Form Block New Block Suggestion for a new block [Type] Tracking Issue Tactical breakdown of efforts across the codebase and/or tied to Overview issues.
Projects
No open projects
Archived in project
Development

No branches or pull requests

7 participants