diff --git a/css/paragraphs.admin.css b/css/paragraphs.admin.css
index 58971cc..eba31ec 100644
--- a/css/paragraphs.admin.css
+++ b/css/paragraphs.admin.css
@@ -80,3 +80,35 @@
   padding-right: 10px;
   text-align: right;
 }
+
+
+.js .paragraph-type-add-modal {
+  width: 100%;
+  padding: 10px 0;
+  text-align: center;
+  margin-bottom: -3em;
+  height: 30px;
+}
+
+.js .paragraph-type-add-modal.first-button {
+  margin-top: -32px;
+  margin-bottom: -20px;
+}
+
+.js .clearfix > .paragraph-type-add-modal.first-button {
+  margin-left: 12px;
+}
+
+.js .paragraph-type-add-modal.no-paragraphs {
+  margin-bottom: -1em;
+}
+
+.js .paragraph-type-add-modal-button {
+  display: inline-block;
+  margin: 0 auto;
+}
+
+.js .paragraph-type-add-modal-button:hover {
+  color: #ffffff;
+  background: #057ec7 none;
+}
diff --git a/css/paragraphs.modal.css b/css/paragraphs.modal.css
new file mode 100644
index 0000000..01aa393
--- /dev/null
+++ b/css/paragraphs.modal.css
@@ -0,0 +1,12 @@
+ul.paragraphs-add-dialog-list {
+  margin: 0;
+  list-style-type: none;
+}
+
+.paragraphs-add-dialog-row {
+  padding: 5px;
+}
+
+.paragraphs-add-dialog-row button {
+  width: 200px;
+}
diff --git a/css/paragraphs.widget.css b/css/paragraphs.widget.css
index 9994da3..29d7322 100644
--- a/css/paragraphs.widget.css
+++ b/css/paragraphs.widget.css
@@ -80,6 +80,37 @@
   text-align: right;
 }
 
+.js .paragraph-type-add-modal {
+  width: 100%;
+  padding: 10px 0;
+  text-align: center;
+  margin-bottom: -3em;
+  height: 30px;
+}
+
+.js .paragraph-type-add-modal.first-button {
+  margin-top: -32px;
+  margin-bottom: -20px;
+}
+
+.js .clearfix > .paragraph-type-add-modal.first-button {
+  margin-left: 12px;
+}
+
+.js .paragraph-type-add-modal.no-paragraphs {
+  margin-bottom: -1em;
+}
+
+.js .paragraph-type-add-modal-button {
+  display: inline-block;
+  margin: 0 auto;
+}
+
+.js .paragraph-type-add-modal-button:hover {
+  color: #ffffff;
+  background: #057ec7 none;
+}
+
 .paragraph--view-mode--preview {
   padding-right: 1em;
 }
diff --git a/js/paragraphs.modal.js b/js/paragraphs.modal.js
new file mode 100644
index 0000000..2670d4d
--- /dev/null
+++ b/js/paragraphs.modal.js
@@ -0,0 +1,257 @@
+/**
+ * @file paragraphs.modal.js
+ *
+ */
+
+(function ($, Drupal, drupalSettings) {
+
+  'use strict';
+
+  /**
+   * Method to apply data on template element.
+   *
+   * For more information about template please take a look at documentation
+   * provided in: templates/paragraphs-add-dialog.html.twig
+   *
+   * @param {Object} $templateElement
+   *   jQuery element for template element.
+   * @param {Object} data
+   *   Data object used to apply on template.
+   *
+   * @private
+   */
+  var _templateApplyData = function ($templateElement, data) {
+    $.each(data, function (name, value) {
+      var selector = '[data-' + name + ']';
+
+      $templateElement.find(selector)
+        .addBack(selector)
+        .each(function (index, childElement) {
+          var $child = $(childElement);
+          var attrName = $child.attr('data-' + name);
+          $child.removeAttr('data-' + name);
+
+          if (attrName === 'content') {
+            $child.text(value);
+          }
+          else {
+            $child.attr(attrName, value);
+          }
+        });
+    });
+  };
+
+  /**
+   * Method to clone template and apply data on it.
+   *
+   * @param {Object} $template
+   *   jQuery element for template element used for cloning.
+   * @param {Object} data
+   *   Data object used to apply on template.
+   *
+   * @return {Object}
+   *   Returns cloned template with applied data on it.
+   *
+   * @private
+   */
+  var _templateClone = function ($template, data) {
+    var $templateClone = $template
+      .clone()
+      .appendTo($template.parent());
+
+    // Adjust all CSS classes with suffix "-template".
+    var classEnding = '-template';
+    $.each(
+      $templateClone.attr('class').toString().split(' '),
+      function (index, className) {
+        if (className.substr(-classEnding.length) === classEnding) {
+          var newClassName = className.substr(0, className.length - classEnding.length);
+          $templateClone
+            .removeClass(className)
+            .toggleClass(newClassName);
+        }
+      }
+    );
+
+    _templateApplyData($templateClone, data);
+
+    return $templateClone;
+  };
+
+  /**
+   * Click handler for click "+ Add" button between paragraphs.
+   *
+   * @type {Object}
+   */
+  Drupal.behaviors.modalAdd = {
+    attach: function (context) {
+      $('.paragraph-type-add-modal-button', context)
+        .once('add-click-handler')
+        .on('click', function (event) {
+          var $button = $(this);
+
+          // Stop default execution of click event.
+          event.preventDefault();
+          event.stopPropagation();
+
+          // Global data for dialog template.
+          // delta: '' -> means that paragraph will be added to end of list.
+          var config = {delta: ''};
+
+          // Get wrapper of elements used for submitting of add paragraph
+          // functionality. It's also used as context for opening of dialog.
+          var $addMoreWrapper;
+          if ($button.attr('name') === 'first_button_add_modal') {
+            // Case for last button in list (of for empty list).
+            $addMoreWrapper = $button
+              .parent()
+              .siblings('.js-hide')
+              .parent();
+          }
+          else {
+            // For button between paragraphs.
+            $addMoreWrapper = $button
+              .closest('table')
+              .parent()
+              .find('.paragraphs-add-dialog-template')
+              .parent();
+
+            // Set delta to correct position in list of paragraphs.
+            config.delta = $button.closest('tr').index();
+          }
+
+          // Get types from ComboBox.
+          var paragraphTypes = Drupal.modalAddParagraphs.getParagraphTypes($addMoreWrapper.find('[name$="[add_more_select]"]'));
+
+          // Open dialog in context of "add_more" element, with provided
+          // configuration and list of paragraph types.
+          Drupal.modalAddParagraphs.openDialog($addMoreWrapper, config, paragraphTypes);
+        });
+    }
+  };
+
+  /**
+   * Namespace for modal related javascript methods.
+   *
+   * @type {Object}
+   */
+  Drupal.modalAddParagraphs = {};
+
+  /**
+   * Fetch list of paragraph types from options provided in combobox.
+   *
+   * @param {Object} $typeComboBox
+   *   jQuery element of combobox with list of available paragraph types.
+   *
+   * @return {Array}
+   *   List of paragraph type objects with type and it's name.
+   */
+  Drupal.modalAddParagraphs.getParagraphTypes = function ($typeComboBox) {
+    var paragraphTypes = [];
+
+    $typeComboBox.find('option').each(function (index, optionElement) {
+      var $option = $(optionElement);
+
+      paragraphTypes.push(
+        {
+          'type': $option.attr('value'),
+          'type-name': $option.text()
+        }
+      );
+    });
+
+    return paragraphTypes;
+  };
+
+  /**
+   * Open modal dialog for adding new paragraph in list.
+   *
+   * @param {Object} $context
+   *   jQuery element of form wrapper used to submit request for adding new
+   *   paragraph to list. Wrapper also contains dialog template.
+   * @param {Object} config
+   *   Global configuration for dialog template. It will be applied on dialog
+   *   template to generated customized dialog.
+   * @param {Array} paragraphTypes
+   *   List of objects with information for paragraph type. Every object
+   *   contains type and name for it and list is used to generate correct action
+   *   elements in customized dialog.
+   */
+  Drupal.modalAddParagraphs.openDialog = function ($context, config, paragraphTypes) {
+
+    // Get dialog template and apply data on it.
+    var $dialogTemplate = $('.paragraphs-add-dialog-template', $context);
+    var $dialog = _templateClone($dialogTemplate, config);
+
+    // Get row template and duplicate it for every paragraph type.
+    var $rowTemplate = $dialog.find('.paragraphs-add-dialog-row-template');
+    for (var i = 0; i < paragraphTypes.length; i++) {
+      _templateClone($rowTemplate, paragraphTypes[i]);
+    }
+    $rowTemplate.remove();
+
+    // Open dialog after data is applied on template.
+    $dialog.dialog({
+      modal: true,
+      resizable: false,
+      close: function () {
+        var $dialog = $(this);
+
+        // Destroy dialog object.
+        $dialog.dialog('destroy');
+
+        // Remove created html element for dialog.
+        $dialog.remove();
+      }
+    });
+
+    // Attach behaviours to dialog action triggering elements.
+    $('.paragraphs-add-type-trigger-element', $dialog)
+      .once('add-click-handler')
+      .on('click', function (event) {
+        var $this = $(this);
+
+        // Stop default execution of click event.
+        event.preventDefault();
+        event.stopPropagation();
+
+        Drupal.modalAddParagraphs.setValues(
+          $context,
+          {
+            add_more_select: $this.attr('data-type'),
+            add_more_delta: $this.attr('data-delta')
+          }
+        );
+
+        // Close dialog afterwards.
+        $this.closest('div.ui-dialog-content').dialog('close');
+      });
+  };
+
+  /**
+   * Method to set hidden fields and trigger adding of paragraph.
+   *
+   * @param {Object} $context
+   *   Jquery object containing element where form for submitting exists.
+   * @param {Object} options
+   *   Object with key value pair, where key is name of field that should be set
+   *   and value is value for that field.
+   */
+  Drupal.modalAddParagraphs.setValues = function ($context, options) {
+    var $submitButton = $('.js-hide input[name$="_add_more"]', $context);
+    var $wrapper = $submitButton.parent();
+
+    // Set all field values defined in options.
+    $.each(options, function (fieldName, fieldValue) {
+      var $field = $wrapper.find('[name$="[' + fieldName + ']"]');
+
+      if ($field) {
+        $field.val(fieldValue);
+      }
+    });
+
+    // Trigger ajax call on add button.
+    $submitButton.trigger('mousedown');
+  };
+
+}(jQuery, Drupal, drupalSettings));
diff --git a/paragraphs.libraries.yml b/paragraphs.libraries.yml
index bb2015d..00ab60f 100644
--- a/paragraphs.libraries.yml
+++ b/paragraphs.libraries.yml
@@ -16,3 +16,15 @@ drupal.paragraphs.widget:
   css:
     theme:
       css/paragraphs.widget.css: {}
+
+drupal.paragraphs.modal:
+  js:
+    js/paragraphs.modal.js: {}
+  css:
+    theme:
+      css/paragraphs.modal.css: {}
+  dependencies:
+    - core/drupal.dialog.ajax
+    - core/jquery.once
+    - core/jquery.ui.tabs
+    - core/drupal
diff --git a/paragraphs.module b/paragraphs.module
index 7d73bfd..c05a6b6 100644
--- a/paragraphs.module
+++ b/paragraphs.module
@@ -59,6 +59,11 @@ function paragraphs_theme() {
     'paragraphs_dropbutton_wrapper' => array(
       'variables' => array('children' => NULL),
     ),
+    'paragraphs_add_dialog' => [
+      'variables' => [],
+      'template' => 'paragraphs-add-dialog',
+//      'render element' => 'elements',
+    ],
   );
 }
 
diff --git a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
index 4a6b0bf..aa33320 100644
--- a/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
+++ b/src/Plugin/Field/FieldWidget/InlineParagraphsWidget.php
@@ -135,7 +135,8 @@ class InlineParagraphsWidget extends WidgetBase {
       '#options' => array(
         'select' => $this->t('Select list'),
         'button' => $this->t('Buttons'),
-        'dropdown' => $this->t('Dropdown button')
+        'dropdown' => $this->t('Dropdown button'),
+        'modal' => $this->t('Modal form'),
       ),
       '#default_value' => $this->getSetting('add_mode'),
       '#required' => TRUE,
@@ -201,6 +202,9 @@ class InlineParagraphsWidget extends WidgetBase {
       case 'dropdown':
         $add_mode = $this->t('Dropdown button');
         break;
+      case 'modal':
+        $add_mode = $this->t('Modal form');
+        break;
     }
 
     $summary[] = $this->t('Edit mode: @edit_mode', ['@edit_mode' => $edit_mode]);
@@ -260,17 +264,6 @@ class InlineParagraphsWidget extends WidgetBase {
         }
       }
     }
-    elseif (isset($widget_state['selected_bundle'])) {
-
-      $entity_type = $entity_manager->getDefinition($target_type);
-      $bundle_key = $entity_type->getKey('bundle');
-
-      $paragraphs_entity = $entity_manager->getStorage($target_type)->create(array(
-        $bundle_key => $widget_state['selected_bundle'],
-      ));
-
-      $item_mode = 'edit';
-    }
 
     if ($item_mode == 'collapsed') {
       $item_mode = $default_edit_mode;
@@ -689,6 +682,10 @@ class InlineParagraphsWidget extends WidgetBase {
       $widget_state['paragraphs'][$delta]['display'] = $display;
       $widget_state['paragraphs'][$delta]['mode'] = $item_mode;
 
+      if ($this->getSetting('add_mode') == 'modal') {
+        $this->buildInBetweenAddButton($element, $id_prefix);
+      }
+
       static::setWidgetState($parents, $field_name, $form_state, $widget_state);
     }
     else {
@@ -698,6 +695,47 @@ class InlineParagraphsWidget extends WidgetBase {
     return $element;
   }
 
+  /**
+   * Builds an add paragraph button between paragraphs for opening of modal.
+   *
+   * @param array $element
+   *   Render element.
+   * @param string $id_prefix
+   *   Prefix.
+   */
+  protected function buildInBetweenAddButton(array &$element, $id_prefix) {
+    if (empty($this->uuid)) {
+      $this->uuid = \Drupal::service('uuid')->generate();
+    }
+
+    $element[$id_prefix . '_area'] = [
+      '#type' => 'container',
+      '#attributes' => [
+        'class' => [
+          'paragraph-type-add-modal',
+          'first-button',
+        ],
+      ],
+      '#access' => !$this->isTranslating,
+      '#weight' => -2000,
+    ];
+
+    $element[$id_prefix . '_area']['add_more'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('+ Add'),
+      '#name' => strtr($id_prefix, '-', '_') . '_add_modal',
+      '#attributes' => [
+        'class' => [
+          'paragraph-type-add-modal-button',
+          'button--small',
+          'js-show',
+        ],
+      ],
+    ];
+
+    $element['#attached']['library'][] = 'paragraphs/drupal.paragraphs.modal';
+  }
+
   public function getAllowedTypes() {
 
     $return_bundles = array();
@@ -848,6 +886,7 @@ class InlineParagraphsWidget extends WidgetBase {
 
     $field_state = static::getWidgetState($this->fieldParents, $field_name, $form_state);
     $field_state['real_item_count'] = $this->realItemCount;
+    $field_state['add_mode'] = $this->getSetting('add_mode');
     static::setWidgetState($this->fieldParents, $field_name, $form_state, $field_state);
 
     if ($this->realItemCount > 0) {
@@ -945,7 +984,7 @@ class InlineParagraphsWidget extends WidgetBase {
         ];
       }
 
-      return $add_more_elements ;
+      return $add_more_elements;
     }
 
     if ($this->getSetting('add_mode') == 'button' || $this->getSetting('add_mode') == 'dropdown') {
@@ -1048,7 +1087,24 @@ class InlineParagraphsWidget extends WidgetBase {
   protected function buildSelectAddMode() {
     $field_name = $this->fieldDefinition->getName();
     $title = $this->fieldDefinition->getLabel();
-    $add_more_elements['add_more_select'] = [
+
+    $add_more_elements = [];
+
+    // Add button at end of list, when modal dialog is used to add paragraphs.
+    if ($this->getSetting('add_mode') == 'modal') {
+      $this->buildInBetweenAddButton($add_more_elements, 'first-button');
+
+      // Append template for modal add paragraph dialog.
+      $add_more_elements['paragraphs_add_dialog_template'] = $this->getModalAddDialogTemplate();
+
+      // Selection form elements.
+      $selection_form_elements['add_more_delta'] = [
+        '#type' => 'hidden',
+        '#title' => 'Delta',
+      ];
+    }
+
+    $selection_form_elements['add_more_select'] = [
       '#type' => 'select',
       '#options' => $this->getAccessibleOptions(),
       '#title' => $this->t('@title type', ['@title' => $this->getSetting('title')]),
@@ -1056,12 +1112,11 @@ class InlineParagraphsWidget extends WidgetBase {
     ];
 
     $text = $this->t('Add @title', ['@title' => $this->getSetting('title')]);
-
     if ($this->realItemCount > 0) {
       $text = $this->t('Add another @title', ['@title' => $this->getSetting('title')]);
     }
 
-    $add_more_elements['add_more_button'] = [
+    $selection_form_elements['add_more_button'] = [
       '#type' => 'submit',
       '#name' => strtr($this->fieldIdPrefix, '-', '_') . '_add_more',
       '#value' => $text,
@@ -1074,8 +1129,18 @@ class InlineParagraphsWidget extends WidgetBase {
         'effect' => 'fade',
       ],
     ];
+    $selection_form_elements['add_more_button']['#suffix'] = $this->t(' to %type', ['%type' => $title]);
+
+    // If we have a modal, the selection form should be hidden.
+    if ($this->getSetting('add_mode') == 'modal') {
+      $add_more_elements['selection_form'] = $selection_form_elements;
+      $add_more_elements['selection_form']['#type'] = 'container';
+      $add_more_elements['selection_form']['#attributes']['class'][] = 'js-hide';
+    }
+    else {
+      $add_more_elements = $selection_form_elements;
+    }
 
-    $add_more_elements['add_more_button']['#suffix'] = $this->t(' to %type', ['%type' => $title]);
     return $add_more_elements;
   }
 
@@ -1101,6 +1166,10 @@ class InlineParagraphsWidget extends WidgetBase {
     $button = $form_state->getTriggeringElement();
     // Go one level up in the form, to the widgets container.
     $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));
+    // The structure of modal is different.
+    if (!isset($element['#field_name'])) {
+      $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -3));
+    }
 
     // Add a DIV around the delta receiving the Ajax effect.
     $delta = $element['#max_delta'];
@@ -1118,6 +1187,11 @@ class InlineParagraphsWidget extends WidgetBase {
 
     // Go one level up in the form, to the widgets container.
     $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));
+    // The structure of modal is different.
+    if (!isset($element['#field_name'])) {
+      $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -3));
+    }
+
     $field_name = $element['#field_name'];
     $parents = $element['#field_parents'];
 
@@ -1126,20 +1200,104 @@ class InlineParagraphsWidget extends WidgetBase {
 
     if ($widget_state['real_item_count'] < $element['#cardinality'] || $element['#cardinality'] == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
       $widget_state['items_count']++;
+      $widget_state['real_item_count']++;
     }
 
+    $position = $widget_state['real_item_count'] - 1;
     if (isset($button['#bundle_machine_name'])) {
       $widget_state['selected_bundle'] = $button['#bundle_machine_name'];
     }
+    elseif ($widget_state['add_mode'] == 'modal') {
+      $widget_state['selected_bundle'] = $element['add_more']['selection_form']['add_more_select']['#value'];
+      if ($element['add_more']['selection_form']['add_more_delta']['#value'] !== "") {
+        $position = $element['add_more']['selection_form']['add_more_delta']['#value'];
+      }
+    }
     else {
       $widget_state['selected_bundle'] = $element['add_more']['add_more_select']['#value'];
     }
 
+    // Create new paragraph entity.
+    $entity_type = \Drupal::entityTypeManager()->getDefinition('paragraph');
+    $bundle_key = $entity_type->getKey('bundle');
+
+    $paragraphs_entity = \Drupal::entityTypeManager()->getStorage('paragraph')->create(array(
+      $bundle_key => $widget_state['selected_bundle'],
+    ));
+
+    $paragraph = [
+      'entity' => $paragraphs_entity,
+      'mode' => 'edit',
+    ];
+
+    if (isset($widget_state['paragraphs'][$position])) {
+      $paragraph['display'] = $widget_state['paragraphs'][$position]['display'];
+    }
+
+    // Add paragraph to the widget state.
+    // This also creates it, when it doesn't exist.
+    $widget_state['paragraphs'][] = $paragraph;
+
+    // If we use a modal, we have to place the new paragraph
+    // in the correct position.
+    if ($widget_state['add_mode'] == 'modal') {
+      // Clean form_state.
+      $user_input = $user_input_save = $form_state->getUserInput();
+
+      // Temporarily remove 'add_more' from array.
+      unset($user_input[$field_name]['add_more']);
+
+      self::normalizeWeights($user_input[$field_name], $position);
+
+      // It is important, that the key maps with the one from $widget_state
+      // The weight handles the position.
+      $key = count($widget_state['paragraphs']) - 1;
+      $item[$key] = [
+        'subform' => [],
+        '_weight' => $position,
+      ];
+
+      $user_input[$field_name] += $item;
+
+      // Add back 'add_more'.
+      $user_input[$field_name]['add_more'] = $user_input_save[$field_name];
+
+      $form_state->setUserInput($user_input);
+    }
+
     static::setWidgetState($parents, $field_name, $form_state, $widget_state);
 
     $form_state->setRebuild();
   }
 
+  /**
+   * This resets the weights, ascending, starting from 0.
+   *
+   * It keeps the indices.
+   *
+   * E.g. [-6, -5, -4] will become [0, 1, 2]
+   *
+   * Starting at position, the elements will get weight+1, to make space
+   * for a new element.
+   *
+   * E.g. [-6, -5, -4], position = 1, will become [ 0,  2,  3]
+   *
+   * @param array $array
+   *   The array, which weights should be normalised.
+   * @param int $position
+   *   The position from which on the weights will be increased by 1.
+   */
+  private static function normalizeWeights(array &$array, $position) {
+    $weigth = 0;
+    foreach ($array as &$value) {
+      if ($weigth == $position) {
+        $weigth++;
+      }
+      $value['_weight'] = $weigth;
+      $weigth++;
+    }
+  }
+
   public static function paragraphsItemSubmit(array $form, FormStateInterface $form_state) {
     $button = $form_state->getTriggeringElement();
 
@@ -1460,6 +1618,21 @@ class InlineParagraphsWidget extends WidgetBase {
     return strip_tags($collapsed_summary_text);
   }
 
+  /**
+   * Returns render array for template of add paragraph modal dialog.
+   *
+   * @return array
+   *   Render array.
+   */
+  protected function getModalAddDialogTemplate() {
+    return [
+      '#theme' => 'paragraphs_add_dialog',
+      '#attached' => [
+        'library' => ['paragraphs/drupal.paragraphs.modal'],
+      ],
+    ];
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/src/Plugin/Field/FieldWidget/ParagraphsWidget.php b/src/Plugin/Field/FieldWidget/ParagraphsWidget.php
index eda8415..4669fcb 100644
--- a/src/Plugin/Field/FieldWidget/ParagraphsWidget.php
+++ b/src/Plugin/Field/FieldWidget/ParagraphsWidget.php
@@ -130,7 +130,8 @@ class ParagraphsWidget extends WidgetBase {
       '#options' => array(
         'select' => $this->t('Select list'),
         'button' => $this->t('Buttons'),
-        'dropdown' => $this->t('Dropdown button')
+        'dropdown' => $this->t('Dropdown button'),
+        'modal' => $this->t('Modal form'),
       ),
       '#default_value' => $this->getSetting('add_mode'),
       '#required' => TRUE,
@@ -196,6 +197,9 @@ class ParagraphsWidget extends WidgetBase {
       case 'dropdown':
         $add_mode = $this->t('Dropdown button');
         break;
+      case 'modal':
+        $add_mode = $this->t('Modal form');
+        break;
     }
 
     $summary[] = $this->t('Edit mode: @edit_mode', ['@edit_mode' => $edit_mode]);
@@ -227,7 +231,6 @@ class ParagraphsWidget extends WidgetBase {
     $host = $items->getEntity();
     $widget_state = static::getWidgetState($parents, $field_name, $form_state);
 
-    $entity_manager = \Drupal::entityTypeManager();
     $target_type = $this->getFieldSetting('target_type');
 
     $item_mode = isset($widget_state['paragraphs'][$delta]['mode']) ? $widget_state['paragraphs'][$delta]['mode'] : 'edit';
@@ -255,17 +258,6 @@ class ParagraphsWidget extends WidgetBase {
         }
       }
     }
-    elseif (isset($widget_state['selected_bundle'])) {
-
-      $entity_type = $entity_manager->getDefinition($target_type);
-      $bundle_key = $entity_type->getKey('bundle');
-
-      $paragraphs_entity = $entity_manager->getStorage($target_type)->create(array(
-        $bundle_key => $widget_state['selected_bundle'],
-      ));
-
-      $item_mode = 'edit';
-    }
 
     if ($item_mode == 'closed') {
       // Validate closed paragraphs and expand if needed.
@@ -676,6 +668,10 @@ class ParagraphsWidget extends WidgetBase {
       $widget_state['paragraphs'][$delta]['display'] = $display;
       $widget_state['paragraphs'][$delta]['mode'] = $item_mode;
 
+      if ($this->getSetting('add_mode') == 'modal') {
+        $this->buildInBetweenAddButton($element, $id_prefix);
+      }
+
       static::setWidgetState($parents, $field_name, $form_state, $widget_state);
     }
     else {
@@ -685,6 +681,47 @@ class ParagraphsWidget extends WidgetBase {
     return $element;
   }
 
+  /**
+   * Builds an add paragraph button between paragraphs for opening of modal.
+   *
+   * @param array $element
+   *   Render element.
+   * @param string $id_prefix
+   *   Prefix.
+   */
+  protected function buildInBetweenAddButton(array &$element, $id_prefix) {
+    if (empty($this->uuid)) {
+      $this->uuid = \Drupal::service('uuid')->generate();
+    }
+
+    $element[$id_prefix . '_area'] = [
+      '#type' => 'container',
+      '#attributes' => [
+        'class' => [
+          'paragraph-type-add-modal',
+          'first-button',
+        ],
+      ],
+      '#access' => !$this->isTranslating,
+      '#weight' => -2000,
+    ];
+
+    $element[$id_prefix . '_area']['add_more'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('+ Add'),
+      '#name' => strtr($id_prefix, '-', '_') . '_add_modal',
+      '#attributes' => [
+        'class' => [
+          'paragraph-type-add-modal-button',
+          'button--small',
+          'js-show',
+        ],
+      ],
+    ];
+
+    $element['#attached']['library'][] = 'paragraphs/drupal.paragraphs.modal';
+  }
+
   public function getAllowedTypes() {
 
     $return_bundles = array();
@@ -838,6 +875,7 @@ class ParagraphsWidget extends WidgetBase {
 
     $field_state = static::getWidgetState($this->fieldParents, $field_name, $form_state);
     $field_state['real_item_count'] = $this->realItemCount;
+    $field_state['add_mode'] = $this->getSetting('add_mode');
     static::setWidgetState($this->fieldParents, $field_name, $form_state, $field_state);
 
     if ($this->realItemCount > 0) {
@@ -935,7 +973,7 @@ class ParagraphsWidget extends WidgetBase {
         ];
       }
 
-      return $add_more_elements ;
+      return $add_more_elements;
     }
 
     if ($this->getSetting('add_mode') == 'button' || $this->getSetting('add_mode') == 'dropdown') {
@@ -1038,7 +1076,24 @@ class ParagraphsWidget extends WidgetBase {
   protected function buildSelectAddMode() {
     $field_name = $this->fieldDefinition->getName();
     $title = $this->fieldDefinition->getLabel();
-    $add_more_elements['add_more_select'] = [
+
+    $add_more_elements = [];
+
+    // Add button at end of list, when modal dialog is used to add paragraphs.
+    if ($this->getSetting('add_mode') == 'modal') {
+      $this->buildInBetweenAddButton($add_more_elements, 'first-button');
+
+      // Append template for modal add paragraph dialog.
+      $add_more_elements['paragraphs_add_dialog_template'] = $this->getModalAddDialogTemplate();
+
+      // Selection form elements.
+      $selection_form_elements['add_more_delta'] = [
+        '#type' => 'hidden',
+        '#title' => 'Delta',
+      ];
+    }
+
+    $selection_form_elements['add_more_select'] = [
       '#type' => 'select',
       '#options' => $this->getAccessibleOptions(),
       '#title' => $this->t('@title type', ['@title' => $this->getSetting('title')]),
@@ -1046,12 +1101,11 @@ class ParagraphsWidget extends WidgetBase {
     ];
 
     $text = $this->t('Add @title', ['@title' => $this->getSetting('title')]);
-
     if ($this->realItemCount > 0) {
       $text = $this->t('Add another @title', ['@title' => $this->getSetting('title')]);
     }
 
-    $add_more_elements['add_more_button'] = [
+    $selection_form_elements['add_more_button'] = [
       '#type' => 'submit',
       '#name' => strtr($this->fieldIdPrefix, '-', '_') . '_add_more',
       '#value' => $text,
@@ -1064,8 +1118,19 @@ class ParagraphsWidget extends WidgetBase {
         'effect' => 'fade',
       ],
     ];
+    $selection_form_elements['add_more_button']['#suffix'] = $this->t(' to %type', ['%type' => $title]);
+
+
+    // If we have a modal, the selection form should be hidden.
+    if ($this->getSetting('add_mode') == 'modal') {
+      $add_more_elements['selection_form'] = $selection_form_elements;
+      $add_more_elements['selection_form']['#type'] = 'container';
+      $add_more_elements['selection_form']['#attributes']['class'][] = 'js-hide';
+    }
+    else {
+      $add_more_elements = $selection_form_elements;
+    }
 
-    $add_more_elements['add_more_button']['#suffix'] = $this->t(' to %type', ['%type' => $title]);
     return $add_more_elements;
   }
 
@@ -1076,6 +1141,10 @@ class ParagraphsWidget extends WidgetBase {
     $button = $form_state->getTriggeringElement();
     // Go one level up in the form, to the widgets container.
     $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));
+    // The structure of modal is different.
+    if (!isset($element['#field_name'])) {
+      $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -3));
+    }
 
     // Add a DIV around the delta receiving the Ajax effect.
     $delta = $element['#max_delta'];
@@ -1093,6 +1162,11 @@ class ParagraphsWidget extends WidgetBase {
 
     // Go one level up in the form, to the widgets container.
     $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));
+    // The structure of modal is different.
+    if (!isset($element['#field_name'])) {
+      $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -3));
+    }
+
     $field_name = $element['#field_name'];
     $parents = $element['#field_parents'];
 
@@ -1101,20 +1175,104 @@ class ParagraphsWidget extends WidgetBase {
 
     if ($widget_state['real_item_count'] < $element['#cardinality'] || $element['#cardinality'] == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) {
       $widget_state['items_count']++;
+      $widget_state['real_item_count']++;
     }
 
+    $position = $widget_state['real_item_count'] - 1;
     if (isset($button['#bundle_machine_name'])) {
       $widget_state['selected_bundle'] = $button['#bundle_machine_name'];
     }
+    elseif ($widget_state['add_mode'] == 'modal') {
+      $widget_state['selected_bundle'] = $element['add_more']['selection_form']['add_more_select']['#value'];
+      if ($element['add_more']['selection_form']['add_more_delta']['#value'] !== "") {
+        $position = $element['add_more']['selection_form']['add_more_delta']['#value'];
+      }
+    }
     else {
       $widget_state['selected_bundle'] = $element['add_more']['add_more_select']['#value'];
     }
 
+    // Create new paragraph entity.
+    $entity_type = \Drupal::entityTypeManager()->getDefinition('paragraph');
+    $bundle_key = $entity_type->getKey('bundle');
+
+    $paragraphs_entity = \Drupal::entityTypeManager()->getStorage('paragraph')->create(array(
+      $bundle_key => $widget_state['selected_bundle'],
+    ));
+
+    $paragraph = [
+      'entity' => $paragraphs_entity,
+      'mode' => 'edit',
+    ];
+
+    if (isset($widget_state['paragraphs'][$position])) {
+      $paragraph['display'] = $widget_state['paragraphs'][$position]['display'];
+    }
+
+    // Add paragraph to the widget state.
+    // This also creates it, when it doesn't exist.
+    $widget_state['paragraphs'][] = $paragraph;
+
+    // If we use a modal, we have to place the new paragraph
+    // in the correct position.
+    if ($widget_state['add_mode'] == 'modal') {
+      // Clean form_state.
+      $user_input = $user_input_save = $form_state->getUserInput();
+
+      // Temporarily remove 'add_more' from array.
+      unset($user_input[$field_name]['add_more']);
+
+      self::normalizeWeights($user_input[$field_name], $position);
+
+      // It is important, that the key maps with the one from $widget_state
+      // The weight handles the position.
+      $key = count($widget_state['paragraphs']) - 1;
+      $item[$key] = [
+        'subform' => [],
+        '_weight' => $position,
+      ];
+
+      $user_input[$field_name] += $item;
+
+      // Add back 'add_more'.
+      $user_input[$field_name]['add_more'] = $user_input_save[$field_name];
+
+      $form_state->setUserInput($user_input);
+    }
+
     static::setWidgetState($parents, $field_name, $form_state, $widget_state);
 
     $form_state->setRebuild();
   }
 
+  /**
+   * This resets the weights, ascending, starting from 0.
+   *
+   * It keeps the indices.
+   *
+   * E.g. [-6, -5, -4] will become [0, 1, 2]
+   *
+   * Starting at position, the elements will get weight+1, to make space
+   * for a new element.
+   *
+   * E.g. [-6, -5, -4], position = 1, will become [ 0,  2,  3]
+   *
+   * @param array $array
+   *   The array, which weights should be normalised.
+   * @param int $position
+   *   The position from which on the weights will be increased by 1.
+   */
+  private static function normalizeWeights(array &$array, $position) {
+    $weigth = 0;
+    foreach ($array as &$value) {
+      if ($weigth == $position) {
+        $weigth++;
+      }
+      $value['_weight'] = $weigth;
+      $weigth++;
+    }
+  }
+
   /**
    * Creates a duplicate of the paragraph entity.
    */
@@ -1487,6 +1645,21 @@ class ParagraphsWidget extends WidgetBase {
     return strip_tags($collapsed_summary_text);
   }
 
+  /**
+   * Returns render array for template of add paragraph modal dialog.
+   *
+   * @return array
+   *   Render array.
+   */
+  protected function getModalAddDialogTemplate() {
+    return [
+      '#theme' => 'paragraphs_add_dialog',
+      '#attached' => [
+        'library' => ['paragraphs/drupal.paragraphs.modal'],
+      ],
+    ];
+  }
+
   /**
    * {@inheritdoc}
    */
diff --git a/templates/paragraphs-add-dialog.html.twig b/templates/paragraphs-add-dialog.html.twig
new file mode 100644
index 0000000..0c7b5e8
--- /dev/null
+++ b/templates/paragraphs-add-dialog.html.twig
@@ -0,0 +1,28 @@
+{#
+/**
+ * @file
+ * Default theme implementation of modal add paragraph dialog template.
+ *
+ * This template for dialog will be handled in javascript, where data-[key]="[attribute]"
+ * attributes will be replaced with data provided for that key. New attribute will be
+ * created like follows: [attribute]="[value-for-key]".
+ *
+ * Following classes have custom use:
+ *   - paragraphs-add-dialog-template - is used to clone dialog.
+ *   - paragraphs-add-dialog-row-template - is used to clone paragraph type rows.
+ *
+ * All listed classes will be renamed in final created dialog with "-template" sufix and
+ * they can be used with that name for theming.
+ *
+ * @ingroup themeable
+ */
+#}
+
+<div class="paragraphs-add-dialog-template" title="{{ 'Add paragraph'|t }}" style="display: none;">
+    <ul class="paragraphs-add-dialog-list">
+        <li class="paragraphs-add-dialog-row-template">
+            <button class="paragraphs-add-type-trigger-element button" data-type-name="content" data-type="data-type"
+                    data-delta="data-delta"></button>
+        </li>
+    </ul>
+</div>
