diff --git a/index.php b/index.php
index ba63aa04e575d..139ba71466e6d 100644
--- a/index.php
+++ b/index.php
@@ -79,7 +79,7 @@ function gutenberg_scripts_and_styles( $hook ) {
function the_gutenberg_project() {
?>
-
+
{
+ return el( 'div', null,
+ el( 'div', { contentEditable: true },
+ wp.blocks.createBlockElement( blocks[ 1 ] )
+ ),
+ el( InserterButton, { onClick: toggleInserter, opened: inserter.opened } )
+ );
+};
+
+export default Editor;
diff --git a/modules/editor/editor/index.js b/modules/editor/editor/index.js
new file mode 100644
index 0000000000000..4b05fbad8c417
--- /dev/null
+++ b/modules/editor/editor/index.js
@@ -0,0 +1,41 @@
+/**
+ * Internal dependencies
+ */
+import EditorComponent from './editor';
+
+const el = wp.element.createElement;
+
+export default class Editor {
+ constructor( id, settings ) {
+ this.toggleInserter = this.toggleInserter.bind( this );
+ this.id = id;
+ this.settings = settings;
+ this.state = {
+ inserter: { opened: false },
+ blocks: wp.blocks.parse( settings.content )
+ };
+ console.log( this.state.blocks ); // eslint-disable-line no-console
+ this.render();
+ }
+
+ setState( newState ) {
+ this.state = Object.assign( {}, this.state, newState );
+ this.render();
+ }
+
+ toggleInserter() {
+ this.setState( {
+ inserter: { opened: ! this.state.inserter.opened }
+ } );
+ }
+
+ render() {
+ wp.element.render(
+ el( EditorComponent, {
+ state: this.state,
+ toggleInserter: this.toggleInserter
+ } ),
+ document.getElementById( this.id )
+ );
+ }
+}
diff --git a/modules/editor/inserter/button.js b/modules/editor/inserter/button.js
new file mode 100644
index 0000000000000..d3f1eb38b172f
--- /dev/null
+++ b/modules/editor/inserter/button.js
@@ -0,0 +1,17 @@
+/**
+ * Internal dependencies
+ */
+import Inserter from './';
+
+const el = wp.element.createElement;
+
+const InserterButton = ( { opened, onClick } ) => {
+ return el( 'div', { className: 'inserter__button' },
+ el( 'a', { className: 'inserter__button-toggle', onClick },
+ el( 'span', { className: 'dashicons dashicons-plus' } )
+ ),
+ opened && el( Inserter )
+ );
+};
+
+export default InserterButton;
diff --git a/modules/editor/inserter/index.js b/modules/editor/inserter/index.js
new file mode 100644
index 0000000000000..dd486099f0a40
--- /dev/null
+++ b/modules/editor/inserter/index.js
@@ -0,0 +1,22 @@
+const el = wp.element.createElement;
+
+const Inserter = () => {
+ const blocks = wp.blocks.getBlocks();
+
+ return el( 'div', { className: 'inserter' },
+ el( 'div', { className: 'inserter__arrow' } ),
+ el( 'div', { className: 'inserter__content' },
+ el( 'div', { className: 'inserter__category-blocks' },
+ blocks.map( ( { slug, title, icon } ) => (
+ el( 'div', { key: slug, className: 'inserter__block' },
+ el( 'span', { className: 'dashicons dashicons-' + icon } ),
+ title
+ )
+ ) )
+ )
+ ),
+ el( 'input', { className: 'inserter__search', type: 'search', placeholder: 'Search...' } )
+ );
+};
+
+export default Inserter;
diff --git a/modules/editor/inserter/style.scss b/modules/editor/inserter/style.scss
new file mode 100644
index 0000000000000..e247f9754e43f
--- /dev/null
+++ b/modules/editor/inserter/style.scss
@@ -0,0 +1,136 @@
+.inserter__button {
+ display: inline-block;
+ position: relative;
+ background: none;
+ border: none;
+ padding: 0;
+ margin-top: 20px;
+}
+
+.inserter__button-toggle {
+ display: inline-block;
+ color: #87919d;
+ cursor: pointer;
+ border-radius: 12px;
+ border: 2px solid #87919d;
+ width: 24px;
+ height: 24px;
+ padding: 0;
+ margin: 0;
+
+ .dashicons {
+ padding: 1px 0;
+ }
+
+ &:hover {
+ color: #12181e;
+ border-color: #12181e;
+ }
+}
+
+.inserter {
+ width: 280px;
+ box-shadow: 0px 3px 20px rgba( 18, 24, 30, .1 ), 0px 1px 3px rgba( 18, 24, 30, .1 );
+ border: 1px solid #e0e5e9;
+ position: absolute;
+ left: -130px;
+ bottom: 40px;
+ background: #fff;
+}
+
+.inserter__arrow {
+ border: 10px dashed #e0e5e9;
+ height: 0;
+ line-height: 0;
+ position: absolute;
+ width: 0;
+ z-index: 1;
+ bottom: -10px;
+ left: 50%;
+ margin-left: -10px;
+ border-top-style: solid;
+ border-bottom: none;
+ border-left-color: transparent;
+ border-right-color: transparent;
+
+ &:before {
+ bottom: 2px;
+ border: 10px solid white;
+ content: " ";
+ position: absolute;
+ left: 50%;
+ margin-left: -10px;
+ border-top-style: solid;
+ border-bottom: none;
+ border-left-color: transparent;
+ border-right-color: transparent;
+ }
+}
+
+.inserter__content {
+ max-height: 180px;
+ overflow: auto;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+.inserter__search {
+ display: block;
+ width: 100%;
+ border: none;
+ margin: 0;
+ border-top: 1px solid #e0e5e9;
+ padding: 8px 16px;
+ font-size: 13px;
+
+ &:focus {
+ outline: none;
+ }
+}
+
+.inserter__category-blocks {
+ display: flex;
+ flex-flow: row wrap;
+}
+
+.inserter__block {
+ display: flex;
+ width: 50%;
+ color: #86909B;
+ padding: 8px;
+ font-size: 11px;
+ align-items: center;
+ cursor: pointer;
+ border: 1px solid transparent;
+
+ &:hover {
+ background: #f8f9f9;
+ border: 1px solid #6d7882;
+ position: relative;
+ }
+
+ &.is-active {
+ background: #eef0f0;
+ border: 1px solid #6d7882;
+ position: relative;
+ color: #3e444c;
+ }
+
+ .dashicons {
+ color: #191e23;
+ margin-right: 8px;
+ }
+}
+
+.inserter__separator {
+ background: rgb(247,248,249);
+ display: block;
+ padding: 2px 12px;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+ font-size: 11px;
+ font-weight: 500;
+ color: #9ea7af;
+}