diff --git a/editor/components/button/index.js b/editor/components/button/index.js
index 4f56ecd2b7e46d..34342d0909d631 100644
--- a/editor/components/button/index.js
+++ b/editor/components/button/index.js
@@ -16,6 +16,7 @@ function Button( { isPrimary, isLarge, isToggled, className, ...additionalProps
);
}
diff --git a/editor/components/inserter/helpers/index.js b/editor/components/inserter/helpers/index.js
new file mode 100644
index 00000000000000..e2a979e9809123
--- /dev/null
+++ b/editor/components/inserter/helpers/index.js
@@ -0,0 +1,83 @@
+/**
+ * Helpers associated with the Inserter Component.
+ *
+ * This file contains a group of functions that help in managing the inserter.
+ */
+
+export const isShownBlock = state => block => block.title.toLowerCase().indexOf( state.filterValue.toLowerCase() ) !== -1;
+
+export const listVisibleBlocksByCategory = ( state ) => ( blocks ) => {
+ return blocks.reduce( ( groups, block ) => {
+ if ( ! isShownBlock( state )( block ) ) {
+ return groups;
+ }
+ if ( ! groups[ block.category ] ) {
+ groups[ block.category ] = [];
+ }
+ groups[ block.category ].push( block );
+ return groups;
+ }, {} );
+};
+
+const flattenObjectIntoArray = ( object ) => {
+ let list = [];
+ for ( const key in object ) {
+ list.push( object[ key ] );
+ }
+ list = list.reduce( ( values, objectValue ) => values.concat( objectValue ), [] );
+
+ return list;
+};
+
+const nextFocusableRef = ( component ) => {
+ const visibleBlocksByCategory = flattenObjectIntoArray( listVisibleBlocksByCategory( component.state )( component.blockTypes ) );
+ const focusables = visibleBlocksByCategory.map( blockType => blockType.slug ).concat( 'search' );
+
+ if ( null === component.state.focusedElementRef ) {
+ return focusables[ 0 ];
+ }
+
+ const currentIndex = focusables.findIndex( ( elementRef ) => elementRef === component.state.focusedElementRef );
+ const nextIndex = currentIndex + 1;
+ const highestIndex = focusables.length - 1;
+
+ // Check boundary so that the index is does not exceed the length.
+ if ( nextIndex > highestIndex ) {
+ // Cycle back to other end.
+ return focusables[ 0 ];
+ }
+
+ return focusables[ nextIndex ];
+};
+
+const previousFocusableRef = ( component ) => {
+ const visibleBlocksByCategory = flattenObjectIntoArray( listVisibleBlocksByCategory( component.state )( component.blockTypes ) );
+ const focusables = visibleBlocksByCategory.map( blockType => blockType.slug ).concat( 'search' );
+
+ // Initiate the menu with the first block.
+ if ( null === component.state.focusedElementRef ) {
+ return focusables[ 0 ];
+ }
+
+ const currentIndex = focusables.findIndex( ( elementRef ) => elementRef === component.state.focusedElementRef );
+ const nextIndex = currentIndex - 1;
+ const lowestIndex = 0;
+
+ // Check boundary so that the index is does not exceed the length.
+ if ( nextIndex < lowestIndex ) {
+ // Cycle back to other end.
+ return focusables[ focusables.length - 1 ];
+ }
+
+ return focusables[ nextIndex ];
+};
+
+export const focusNextFocusableRef = ( component ) => {
+ const next = nextFocusableRef( component );
+ component.changeMenuSelection( next );
+};
+
+export const focusPreviousFocusableRef = ( component ) => {
+ const previous = previousFocusableRef( component );
+ component.changeMenuSelection( previous );
+};
diff --git a/editor/components/inserter/index.js b/editor/components/inserter/index.js
index dab8bf2d4b1cc2..faf2bb274930c1 100644
--- a/editor/components/inserter/index.js
+++ b/editor/components/inserter/index.js
@@ -7,6 +7,7 @@ import IconButton from 'components/icon-button';
class Inserter extends wp.element.Component {
constructor() {
super( ...arguments );
+ this.nodes = {};
this.toggle = this.toggle.bind( this );
this.close = this.close.bind( this );
this.state = {
@@ -15,6 +16,10 @@ class Inserter extends wp.element.Component {
}
toggle() {
+ if ( this.state.opened === true ) {
+ this.nodes.toggle.focus();
+ }
+
this.setState( {
opened: ! this.state.opened
} );
@@ -36,8 +41,12 @@ class Inserter extends wp.element.Component {
icon="insert"
label={ wp.i18n.__( 'Insert block' ) }
onClick={ this.toggle }
- className="editor-inserter__toggle" />
- { opened &&