diff --git a/packages/editor/src/components/table-of-contents/panel.js b/packages/editor/src/components/table-of-contents/panel.js
index 48ca98c2fd04a..7e1b9ed5c7512 100644
--- a/packages/editor/src/components/table-of-contents/panel.js
+++ b/packages/editor/src/components/table-of-contents/panel.js
@@ -9,6 +9,7 @@ import { store as blockEditorStore } from '@wordpress/block-editor';
* Internal dependencies
*/
import WordCount from '../word-count';
+import TimeToRead from '../time-to-read';
import DocumentOutline from '../document-outline';
import CharacterCount from '../character-count';
@@ -38,6 +39,10 @@ function TableOfContentsPanel( { hasOutlineItemsDisabled, onRequestClose } ) {
tabIndex="0"
>
+ -
+ { __( 'Words' ) }
+
+
-
{ __( 'Characters' ) }
@@ -45,8 +50,8 @@ function TableOfContentsPanel( { hasOutlineItemsDisabled, onRequestClose } ) {
-
- { __( 'Words' ) }
-
+ { __( 'Time to read' ) }
+
-
{ __( 'Headings' ) }
diff --git a/packages/editor/src/components/time-to-read/index.js b/packages/editor/src/components/time-to-read/index.js
new file mode 100644
index 0000000000000..0ff85b2e717d0
--- /dev/null
+++ b/packages/editor/src/components/time-to-read/index.js
@@ -0,0 +1,59 @@
+/**
+ * WordPress dependencies
+ */
+import { useSelect } from '@wordpress/data';
+import { _x, _n, __, sprintf } from '@wordpress/i18n';
+import { count as wordCount } from '@wordpress/wordcount';
+import { createInterpolateElement } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import { store as editorStore } from '../../store';
+
+/**
+ * Average reading rate - based on average taken from
+ * https://irisreading.com/average-reading-speed-in-various-languages/
+ * (Characters/minute used for Chinese rather than words).
+ *
+ * @type {number} A rough estimate of the average reading rate across multiple languages.
+ */
+const AVERAGE_READING_RATE = 189;
+
+export default function TimeToRead() {
+ const content = useSelect(
+ ( select ) => select( editorStore ).getEditedPostAttribute( 'content' ),
+ []
+ );
+
+ /*
+ * translators: If your word count is based on single characters (e.g. East Asian characters),
+ * enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
+ * Do not translate into your own language.
+ */
+ const wordCountType = _x( 'words', 'Word count type. Do not translate!' );
+ const minutesToRead = Math.round(
+ wordCount( content, wordCountType ) / AVERAGE_READING_RATE
+ );
+ const minutesToReadString =
+ minutesToRead === 0
+ ? createInterpolateElement( __( '< 1 minute' ), {
+ span: ,
+ } )
+ : createInterpolateElement(
+ sprintf(
+ /* translators: %s is the number of minutes the post will take to read. */
+ _n(
+ '%d minute',
+ '%d minutes',
+ minutesToRead
+ ),
+ minutesToRead
+ ),
+ {
+ span: ,
+ }
+ );
+
+ return { minutesToReadString };
+}