diff --git a/components/clipboard-button/index.js b/components/clipboard-button/index.js
index 3c4a78f30783a0..79f550acc60cb6 100644
--- a/components/clipboard-button/index.js
+++ b/components/clipboard-button/index.js
@@ -38,6 +38,7 @@ class ClipboardButton extends Component {
componentWillUnmount() {
this.clipboard.destroy();
delete this.clipboard;
+ clearTimeout( this.onCopyTimeout );
}
bindContainer( container ) {
@@ -50,9 +51,17 @@ class ClipboardButton extends Component {
// kept within the rendered node.
args.clearSelection();
- const { onCopy } = this.props;
+ const { onCopy, onFinishCopy } = this.props;
if ( onCopy ) {
onCopy();
+ // For convenience and consistency, ClipboardButton offers to call
+ // a secondary callback with delay. This is useful to reset
+ // consumers' state, e.g. to revert a label from "Copied" to
+ // "Copy".
+ if ( onFinishCopy ) {
+ clearTimeout( this.onCopyTimeout );
+ this.onCopyTimeout = setTimeout( onFinishCopy, 4000 );
+ }
}
}
@@ -68,7 +77,7 @@ class ClipboardButton extends Component {
render() {
// Disable reason: Exclude from spread props passed to Button
// eslint-disable-next-line no-unused-vars
- const { className, children, onCopy, text, ...buttonProps } = this.props;
+ const { className, children, onCopy, onFinishCopy, text, ...buttonProps } = this.props;
const classes = classnames( 'components-clipboard-button', className );
return (
diff --git a/components/menu-items/menu-items-group.js b/components/menu-items/menu-items-group.js
index d59f9785b2b097..27a8af4533361d 100644
--- a/components/menu-items/menu-items-group.js
+++ b/components/menu-items/menu-items-group.js
@@ -1,3 +1,8 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
/**
* Internal dependencies
*/
@@ -6,11 +11,23 @@ import { NavigableMenu } from '../navigable-container';
import withInstanceId from '../higher-order/with-instance-id';
import MenuItemsToggle from './menu-items-toggle';
-function MenuItemsGroup( { label, value, choices = [], onSelect, children, instanceId } ) {
+function MenuItemsGroup( {
+ label,
+ value,
+ choices = [],
+ onSelect,
+ children,
+ instanceId,
+ className = '',
+} ) {
const labelId = `components-choice-menu-label-${ instanceId }`;
+ const classNames = classnames( className, 'components-choice-menu' );
+
return (
-
-
{ label }
+
+ { label &&
+
{ label }
+ }
{ choices.map( ( item ) => {
const isSelected = value === item.value;
diff --git a/components/menu-items/menu-items-toggle.js b/components/menu-items/menu-items-toggle.js
index 3d70f4316e4efc..e7b4e97a22f51f 100644
--- a/components/menu-items/menu-items-toggle.js
+++ b/components/menu-items/menu-items-toggle.js
@@ -10,7 +10,7 @@ function MenuItemsToggle( { label, isSelected, onClick, shortcut } ) {
if ( isSelected ) {
return (
@@ -22,7 +22,7 @@ function MenuItemsToggle( { label, isSelected, onClick, shortcut } ) {
return (
diff --git a/editor/edit-post/header/copy-content-button/index.js b/editor/edit-post/header/copy-content-button/index.js
new file mode 100644
index 00000000000000..ed8045165bf038
--- /dev/null
+++ b/editor/edit-post/header/copy-content-button/index.js
@@ -0,0 +1,51 @@
+/**
+ * External dependencies
+ */
+import { connect } from 'react-redux';
+
+/**
+ * WordPress dependencies
+ */
+import { ClipboardButton } from '@wordpress/components';
+import { Component } from '@wordpress/element';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { getEditedPostContent } from '../../../store/selectors';
+
+class CopyContentButton extends Component {
+ constructor() {
+ super( ...arguments );
+ this.state = { hasCopied: false };
+ this.onCopy = this.onCopy.bind( this );
+ this.onFinishCopy = this.onFinishCopy.bind( this );
+ }
+ onCopy() {
+ this.setState( { hasCopied: true } );
+ }
+ onFinishCopy() {
+ this.setState( { hasCopied: false } );
+ }
+ render() {
+ return (
+
+ { this.state.hasCopied ?
+ __( 'Copied!' ) :
+ __( 'Copy All Content' ) }
+
+ );
+ }
+}
+
+export default connect(
+ ( state ) => ( {
+ editedPostContent: getEditedPostContent( state ),
+ } )
+)( CopyContentButton );
diff --git a/editor/edit-post/header/editor-actions/index.js b/editor/edit-post/header/editor-actions/index.js
new file mode 100644
index 00000000000000..43127de4faf22b
--- /dev/null
+++ b/editor/edit-post/header/editor-actions/index.js
@@ -0,0 +1,20 @@
+/**
+ * WordPress dependencies
+ */
+import { MenuItemsGroup } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import CopyContentButton from '../copy-content-button';
+
+export default function EditorActions() {
+ return (
+
+
+
+ );
+}
diff --git a/editor/edit-post/header/ellipsis-menu/index.js b/editor/edit-post/header/ellipsis-menu/index.js
index d78f028d0feb61..be3d8d6ba3e8ed 100644
--- a/editor/edit-post/header/ellipsis-menu/index.js
+++ b/editor/edit-post/header/ellipsis-menu/index.js
@@ -10,6 +10,7 @@ import { IconButton, Dropdown } from '@wordpress/components';
import './style.scss';
import ModeSwitcher from '../mode-switcher';
import FixedToolbarToggle from '../fixed-toolbar-toggle';
+import EditorActions from '../editor-actions';
const element = (
+
+
) }
/>
diff --git a/editor/edit-post/header/fixed-toolbar-toggle/index.js b/editor/edit-post/header/fixed-toolbar-toggle/index.js
index dcc620dab7432e..d9f2d2af3c118c 100644
--- a/editor/edit-post/header/fixed-toolbar-toggle/index.js
+++ b/editor/edit-post/header/fixed-toolbar-toggle/index.js
@@ -21,7 +21,7 @@ function FeatureToggle( { onToggle, active, onMobile } ) {
}
return (