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

Add PluginHeaderToolbar SlotFill to edit-post package. #52261

Open
wants to merge 11 commits into
base: trunk
Choose a base branch
from
32 changes: 32 additions & 0 deletions packages/edit-post/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,38 @@ _Returns_

- `WPComponent`: The component to be rendered.

### PluginHeaderToolbar

Renders a button and association dropdown in the header toolbar.

_Usage_

```js
import { registerPlugin } from '@wordpress/plugins';
import { PluginHeaderToolbar } from '@wordpress/edit-post';

const MyHeaderToolbarPlugin = () => (
<PluginHeaderToolbar
className="plugin-header-toolbar-button"
classContentName="plugin-header-toolbar-content"
renderContent={ () => <div>Rendered Content</div> }
/>
);

registerPlugin( 'my-header-toolbar-plugin', {
render: MyHeaderToolbarPlugin,
icon: 'smiley',
} );
```

_Parameters_

- _props_ `Object`: Component properties.
- _renderContent_ `WPComponent`: The component to render as the UI for the dropdown.
- _props.className_ `[string]`: Optional. The class name for the button.
- _props.contentClassName_ `[string]`: Optional. The class name of the dropdown item.
- _props.icon_ `[WPBlockTypeIconRender]`: The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element.

### PluginMoreMenuItem

Renders a menu item in `Plugins` group in `More Menu` drop down, and can be used to as a button or link depending on the props provided. The text within the component appears as the menu item label.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
*/
import { store as editPostStore } from '../../../store';
import { unlock } from '../../../lock-unlock';
import PluginHeaderToolbar from '../plugin-header-toolbar';

const { useShouldContextualToolbarShow } = unlock( blockEditorPrivateApis );

Expand Down Expand Up @@ -168,6 +169,11 @@ function HeaderToolbar() {
variant={ showIconLabels ? 'tertiary' : undefined }
/>
{ overflowItems }
{ isLargeViewport && (
<PluginHeaderToolbar.Slot
fillProps={ { showIconLabels } }
/>
) }
</>
) }
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* WordPress dependencies
*/
import {
createSlotFill,
Button,
ToolbarItem,
Dropdown,
} from '@wordpress/components';
import warning from '@wordpress/warning';
import { plugins as pluginsIcon } from '@wordpress/icons';
import { compose } from '@wordpress/compose';
import { withPluginContext } from '@wordpress/plugins';

const { Fill, Slot } = createSlotFill( 'PluginHeaderToolbar' );

/**
* Whether the argument is a function.
*
* @param {*} maybeFunc The argument to check.
* @return {boolean} True if the argument is a function, false otherwise.
*/
function isFunction( maybeFunc ) {
return typeof maybeFunc === 'function';
}

const PluginHeaderToolbarFill = ( {
icon = pluginsIcon,
renderContent = null,
className = 'plugin-header-toolbar-button',
contentClassName = 'plugin-header-toolbar-content',
} ) => {
if ( null === renderContent || ! isFunction( renderContent ) ) {
warning(
'PluginHeaderToolbar requires renderContent property to be specified and be a valid function.'
);
return null;
}
return (
<Fill>
{ ( { showIconLabels } ) => (
<ToolbarItem
showTooltip={ ! showIconLabels }
variant={ showIconLabels ? 'tertiary' : undefined }
as={ () => (
<Dropdown
className={ className }
contentClassName={ contentClassName }
popoverProps={ { placement: 'bottom-start' } }
renderToggle={ ( { isOpen, onToggle } ) => (
<Button
onClick={ onToggle }
aria-expanded={ isOpen }
icon={ icon }
className="components-button"
/>
) }
renderContent={ renderContent }
/>
) }
/>
) }
</Fill>
);
};

/**
* Renders a button and association dropdown in the header toolbar.
*
* @param {Object} props Component properties.
* @param {WPComponent} renderContent The component to render as the UI for the dropdown.
* @param {string} [props.className] Optional. The class name for the button.
* @param {string} [props.contentClassName] Optional. The class name of the dropdown item.
* @param {WPBlockTypeIconRender} [props.icon=inherits from the plugin] The [Dashicon](https://developer.wordpress.org/resource/dashicons/) icon slug string, or an SVG WP element.
*
* @example
* ```js
* import { registerPlugin } from '@wordpress/plugins';
* import { PluginHeaderToolbar } from '@wordpress/edit-post';
*
* const MyHeaderToolbarPlugin = () => (
* <PluginHeaderToolbar
* className="plugin-header-toolbar-button"
* classContentName="plugin-header-toolbar-content"
* renderContent={() => <div>Rendered Content</div>}
* />
* );
*
* registerPlugin( 'my-header-toolbar-plugin', { render: MyHeaderToolbarPlugin, icon: 'smiley' } );
* ```
*
*/
const PluginHeaderToolbar = compose(
withPluginContext( ( context, ownProps ) => {
return {
icon: ownProps.icon || context.icon,
};
} )
)( PluginHeaderToolbarFill );

PluginHeaderToolbar.Slot = Slot;

export default PluginHeaderToolbar;
1 change: 1 addition & 0 deletions packages/edit-post/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export { default as PluginPostStatusInfo } from './components/sidebar/plugin-pos
export { default as PluginPrePublishPanel } from './components/sidebar/plugin-pre-publish-panel';
export { default as PluginSidebar } from './components/sidebar/plugin-sidebar';
export { default as PluginSidebarMoreMenuItem } from './components/header/plugin-sidebar-more-menu-item';
export { default as PluginHeaderToolbar } from './components/header/plugin-header-toolbar';
export { default as __experimentalFullscreenModeClose } from './components/header/fullscreen-mode-close';
export { default as __experimentalMainDashboardButton } from './components/header/main-dashboard-button';
export { store } from './store';