diff --git a/lib/blocks.php b/lib/blocks.php
index 9e0d63a0c6bf0..95b9c16ad09fd 100644
--- a/lib/blocks.php
+++ b/lib/blocks.php
@@ -75,6 +75,7 @@ function gutenberg_reregister_core_block_types() {
'post-comment-content.php' => 'core/post-comment-content',
'post-comment-date.php' => 'core/post-comment-date',
'post-comment-edit.php' => 'core/post-comment-edit',
+ 'post-comment-reply-link.php' => 'core/post-comment-reply-link',
'post-comments.php' => 'core/post-comments',
'post-comments-count.php' => 'core/post-comments-count',
'post-comments-form.php' => 'core/post-comments-form',
diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js
index 77095d01063ca..588edb6070563 100644
--- a/packages/block-library/src/index.js
+++ b/packages/block-library/src/index.js
@@ -84,6 +84,7 @@ import * as postCommentAuthorAvatar from './post-comment-author-avatar';
import * as postCommentContent from './post-comment-content';
import * as postCommentDate from './post-comment-date';
import * as postCommentEdit from './post-comment-edit';
+import * as postCommentReplyLink from './post-comment-reply-link';
import * as postComments from './post-comments';
import * as postCommentsCount from './post-comments-count';
import * as postCommentsForm from './post-comments-form';
@@ -247,6 +248,7 @@ export const __experimentalRegisterExperimentalCoreBlocks =
postCommentContent,
postCommentDate,
postCommentEdit,
+ postCommentReplyLink,
postComments,
postCommentsCount,
postCommentsForm,
diff --git a/packages/block-library/src/post-comment-reply-link/block.json b/packages/block-library/src/post-comment-reply-link/block.json
new file mode 100644
index 0000000000000..ddfdc540e70a6
--- /dev/null
+++ b/packages/block-library/src/post-comment-reply-link/block.json
@@ -0,0 +1,32 @@
+{
+ "apiVersion": 2,
+ "name": "core/post-comment-reply-link",
+ "title": "Post Comment Reply Link",
+ "category": "design",
+ "parent": [ "core/post-comment" ],
+ "description": "Displays a link to reply to a comment.",
+ "textdomain": "default",
+ "usesContext": [ "commentId" ],
+ "attributes": {
+ "textAlign": {
+ "type": "string"
+ }
+ },
+ "supports": {
+ "color": {
+ "gradients": true,
+ "link": true,
+ "text": false
+ },
+ "typography": {
+ "fontSize": true,
+ "lineHeight": true,
+ "__experimentalFontFamily": true,
+ "__experimentalFontWeight": true,
+ "__experimentalFontStyle": true,
+ "__experimentalTextTransform": true,
+ "__experimentalLetterSpacing": true
+ },
+ "html": false
+ }
+}
diff --git a/packages/block-library/src/post-comment-reply-link/edit.js b/packages/block-library/src/post-comment-reply-link/edit.js
new file mode 100644
index 0000000000000..776caa9f3e752
--- /dev/null
+++ b/packages/block-library/src/post-comment-reply-link/edit.js
@@ -0,0 +1,59 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+import { __ } from '@wordpress/i18n';
+import {
+ AlignmentControl,
+ BlockControls,
+ useBlockProps,
+} from '@wordpress/block-editor';
+
+/**
+ * Renders the `core/post-comment-reply-link` block on the editor.
+ *
+ * @param {Object} props React props.
+ * @param {Object} props.setAttributes Callback for updating block attributes.
+ * @param {Object} props.attributes Block attributes.
+ * @param {string} props.attributes.textAlign The `textAlign` attribute.
+ *
+ * @return {JSX.Element} React element.
+ */
+function Edit( { setAttributes, attributes: { textAlign } } ) {
+ const blockProps = useBlockProps( {
+ className: classnames( {
+ [ `has-text-align-${ textAlign }` ]: textAlign,
+ } ),
+ } );
+
+ const blockControls = (
+
+
+ setAttributes( { textAlign: newAlign } )
+ }
+ />
+
+ );
+
+ return (
+ <>
+ { blockControls }
+
+ >
+ );
+}
+
+export default Edit;
diff --git a/packages/block-library/src/post-comment-reply-link/index.js b/packages/block-library/src/post-comment-reply-link/index.js
new file mode 100644
index 0000000000000..7d52091a43abb
--- /dev/null
+++ b/packages/block-library/src/post-comment-reply-link/index.js
@@ -0,0 +1,18 @@
+/**
+ * WordPress dependencies
+ */
+import { postCommentReplyLink as icon } from '@wordpress/icons';
+
+/**
+ * Internal dependencies
+ */
+import metadata from './block.json';
+import edit from './edit';
+
+const { name } = metadata;
+export { metadata, name };
+
+export const settings = {
+ edit,
+ icon,
+};
diff --git a/packages/block-library/src/post-comment-reply-link/index.php b/packages/block-library/src/post-comment-reply-link/index.php
new file mode 100644
index 0000000000000..d3b11b0fbd539
--- /dev/null
+++ b/packages/block-library/src/post-comment-reply-link/index.php
@@ -0,0 +1,80 @@
+context['commentId'] ) ) {
+ return '';
+ }
+
+ $thread_comments = get_option( 'thread_comments' );
+ if ( ! $thread_comments ) {
+ return '';
+ }
+
+ $comment = get_comment( $block->context['commentId'] );
+ if ( empty( $comment ) ) {
+ return '';
+ }
+
+ $depth = 1;
+ $max_depth = get_option( 'thread_comments_depth' );
+ $parent_id = $comment->comment_parent;
+
+ // Compute comment's depth iterating over its ancestors.
+ while ( ! empty( $parent_id ) ) {
+ $depth++;
+ $parent_id = get_comment( $parent_id )->comment_parent;
+ }
+
+ $comment_reply_link = get_comment_reply_link(
+ array(
+ 'depth' => $depth,
+ 'max_depth' => $max_depth,
+ ),
+ $comment
+ );
+
+ // Render nothing if the generated reply link is empty.
+ if ( empty( $comment_reply_link ) ) {
+ return;
+ }
+
+ $classes = '';
+ if ( isset( $attributes['textAlign'] ) ) {
+ $classes .= 'has-text-align-' . $attributes['textAlign'];
+ }
+
+ $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) );
+
+ return sprintf(
+ '%2$s
',
+ $wrapper_attributes,
+ $comment_reply_link
+ );
+}
+
+/**
+ * Registers the `core/post-comment-reply-link` block on the server.
+ */
+function register_block_core_post_comment_reply_link() {
+ register_block_type_from_metadata(
+ __DIR__ . '/post-comment-reply-link',
+ array(
+ 'render_callback' => 'render_block_core_post_comment_reply_link',
+ )
+ );
+}
+
+add_action( 'init', 'register_block_core_post_comment_reply_link' );
diff --git a/packages/block-library/src/post-comment/edit.js b/packages/block-library/src/post-comment/edit.js
index a08048f9c2b2b..d293a45c1fff6 100644
--- a/packages/block-library/src/post-comment/edit.js
+++ b/packages/block-library/src/post-comment/edit.js
@@ -14,10 +14,12 @@ const ALLOWED_BLOCKS = [
'core/post-comment-content',
'core/post-comment-author',
'core/post-comment-date',
+ 'core/post-comment-reply-link',
];
const TEMPLATE = [
[ 'core/post-comment-content' ],
[ 'core/post-comment-author' ],
+ [ 'core/post-comment-reply-link' ],
];
export default function Edit( { attributes: { commentId }, setAttributes } ) {
diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js
index 27d3cdd12c819..885edbd8d1fef 100644
--- a/packages/icons/src/index.js
+++ b/packages/icons/src/index.js
@@ -152,6 +152,7 @@ export { default as plus } from './library/plus';
export { default as postAuthor } from './library/post-author';
export { default as postCategories } from './library/post-categories';
export { default as postContent } from './library/post-content';
+export { default as postCommentReplyLink } from './library/post-comment-reply-link';
export { default as postComments } from './library/post-comments';
export { default as postCommentAuthorAvatar } from './library/post-comment-author-avatar';
export { default as postCommentsCount } from './library/post-comments-count';
diff --git a/packages/icons/src/library/post-comment-reply-link.js b/packages/icons/src/library/post-comment-reply-link.js
new file mode 100644
index 0000000000000..551092c131270
--- /dev/null
+++ b/packages/icons/src/library/post-comment-reply-link.js
@@ -0,0 +1,17 @@
+/**
+ * WordPress dependencies
+ */
+import { Path, SVG } from '@wordpress/primitives';
+
+const postCommentsReplyLink = (
+
+);
+
+export default postCommentsReplyLink;
diff --git a/test/integration/fixtures/blocks/core__post-comment-reply-link.html b/test/integration/fixtures/blocks/core__post-comment-reply-link.html
new file mode 100644
index 0000000000000..af837d2e3e353
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-comment-reply-link.html
@@ -0,0 +1 @@
+
diff --git a/test/integration/fixtures/blocks/core__post-comment-reply-link.json b/test/integration/fixtures/blocks/core__post-comment-reply-link.json
new file mode 100644
index 0000000000000..197e2489561b3
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-comment-reply-link.json
@@ -0,0 +1,31 @@
+[
+ {
+ "clientId": "_clientId_0",
+ "name": "core/post-comment-reply-link",
+ "isValid": true,
+ "attributes": {
+ "textAlign": "right",
+ "fontFamily": "cambria-georgia",
+ "fontSize": "extra-large",
+ "style": {
+ "typography": {
+ "lineHeight": "0.8",
+ "textTransform": "uppercase",
+ "letterSpacing": "10px"
+ },
+ "elements": {
+ "link": {
+ "color": {
+ "text": "var:preset|color|blue"
+ }
+ }
+ },
+ "color": {
+ "background": "#c82222"
+ }
+ }
+ },
+ "innerBlocks": [],
+ "originalContent": ""
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__post-comment-reply-link.parsed.json b/test/integration/fixtures/blocks/core__post-comment-reply-link.parsed.json
new file mode 100644
index 0000000000000..5e34e1feefb75
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-comment-reply-link.parsed.json
@@ -0,0 +1,30 @@
+[
+ {
+ "blockName": "core/post-comment-reply-link",
+ "attrs": {
+ "textAlign": "right",
+ "style": {
+ "typography": {
+ "lineHeight": "0.8",
+ "textTransform": "uppercase",
+ "letterSpacing": "10px"
+ },
+ "elements": {
+ "link": {
+ "color": {
+ "text": "var:preset|color|blue"
+ }
+ }
+ },
+ "color": {
+ "background": "#c82222"
+ }
+ },
+ "fontSize": "extra-large",
+ "fontFamily": "cambria-georgia"
+ },
+ "innerBlocks": [],
+ "innerHTML": "",
+ "innerContent": []
+ }
+]
diff --git a/test/integration/fixtures/blocks/core__post-comment-reply-link.serialized.html b/test/integration/fixtures/blocks/core__post-comment-reply-link.serialized.html
new file mode 100644
index 0000000000000..8e6c147336d66
--- /dev/null
+++ b/test/integration/fixtures/blocks/core__post-comment-reply-link.serialized.html
@@ -0,0 +1 @@
+