diff --git a/images/collapsed.png b/images/collapsed.png
new file mode 100644
index 0000000000000000000000000000000000000000..91f3fd40ede024798b6de5ea2675bb692a3cfa95
GIT binary patch
literal 105
zcmeAS@N?(olHy`uVBq!ia0vp^>>$j@3?%=}IXVGIu?6^qxc>kDAIJ<nbh!>lF_r}R
y1v5B2yO9Ru2zt6WhH%Ixhb6Q*Xr>9K@iDN~Fr3*g^XWQJlEKr}&t;ucLK6T5e;aZD

literal 0
HcmV?d00001

diff --git a/images/expanded.png b/images/expanded.png
new file mode 100644
index 0000000000000000000000000000000000000000..46f39ecb351cff65243fa9a614a69d039e1302a5
GIT binary patch
literal 106
zcmeAS@N?(olHy`uVBq!ia0vp^>>$j@3?%=}IXVGIu?6^qxc>kDAIJ<nbh!>lF_r}R
z1v5B2yO9Ru2zk0VhE&W+{&76uaKb@_0}N~oA{!VF-#vS9IZ&3t)78&qol`;+0EMF;
ATL1t6

literal 0
HcmV?d00001

diff --git a/paragraphs.collapsible.css b/paragraphs.collapsible.css
new file mode 100644
index 0000000000000000000000000000000000000000..07672d467ec4001207f21177ca081e821986e394
--- /dev/null
+++ b/paragraphs.collapsible.css
@@ -0,0 +1,39 @@
+/**
+ * Admin CSS styles for the paragraphs module.
+ */
+td.paragraph-bundle-content-collapsible {
+  position: relative;
+}
+
+td.paragraph-bundle-content-collapsible > .paragraph-bundle-title,
+td.paragraph-bundle-content-collapsible > .ajax-new-content > .paragraph-bundle-title {
+  cursor: pointer;
+  background: url(images/expanded.png) 5px 65% no-repeat; /* LTR */
+  padding-left: 15px; /* LTR */
+}
+
+td.paragraph-bundle-content-collapsible.collapsed > .paragraph-bundle-title,
+td.paragraph-bundle-content-collapsible.collapsed > .ajax-new-content > .paragraph-bundle-title {
+  background-image: url(images/collapsed.png); /* LTR */
+  background-position: 5px 50%; /* LTR */
+}
+
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.collapsed > :not(.paragraph-bundle-content-collapsible-shown),
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.collapsed > .ajax-new-content > :not(.paragraph-bundle-content-collapsible-shown) {
+  display: none;
+}
+
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.expanded > .form-actions .paragraphs-edit-link,
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.expanded > .ajax-new-content > .form-actions .paragraphs-edit-link {
+  display: none;
+}
+
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.collapsed > .form-actions .paragraphs-collapse-link,
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.collapsed > .ajax-new-content > .form-actions .paragraphs-collapse-link {
+  display: none;
+}
+
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.expanded > .paragraph-bundle-preview,
+td.paragraph-bundle-content-open.paragraph-bundle-content-collapsible.expanded > .ajax-new-content > .paragraph-bundle-preview {
+  display: none;
+}
diff --git a/paragraphs.collapsible.js b/paragraphs.collapsible.js
new file mode 100644
index 0000000000000000000000000000000000000000..00b5af8f59808d8a386b5c947424afcf2be2732a
--- /dev/null
+++ b/paragraphs.collapsible.js
@@ -0,0 +1,920 @@
+/**
+ * @file
+ * Provides JavaScript for Collapsible Paragraphs.
+ */
+
+(function($, Drupal, window, document) {
+  'use strict';
+
+  /**
+   * Toggler object.
+   */
+  var Toggler = Drupal.paragraphsCollapsibleToggler = function(controller, options) {
+    var defaults = {
+      actions: controller.actions || {}
+    };
+
+    $.extend(true, this, defaults, options);
+
+    this.controller = controller;
+  };
+
+  /**
+   * Determine if this item can be toggled by this toggler.
+   *
+   * @param jQuery $items
+   *   The JQuery set of field items.
+   *
+   * @return bool
+   *   TRUE if this toggler can toggle the item.
+   */
+  Toggler.prototype.canToggle = function($item) {
+    if ('canToggle' in this.callbacks) {
+      var self = this;
+      return this.callbacks.canToggle(self, $item);
+    }
+    return true;
+  };
+
+  /**
+   * Toggle callback to show / Hide a single paragraph item.
+   *
+   * @param jQuery $items
+   *   The JQuery set of field items.
+   * @param string action_name
+   *   The toggle action - 'collapse' or 'expand'.
+   * @param object options
+   *   A set of options to configure the toggle:
+   *   - fast (bool): If enabled, the transitions will not use the animated
+   *     slideUp / slideDown. The faster hide / show is used.
+   *   - expandFieldsets (bool): Expand all nested fieldsets.
+   *   - complete (function): Callback on complete.
+   *
+   * @return int
+   *   Count of items toggled or promised to be toggled.
+   */
+  Toggler.prototype.toggle = function($items, action_name, toggle_options) {
+    if ('toggle' in this.callbacks) {
+      var self = this;
+      this.callbacks.toggle(self, $items, action_name, toggle_options);
+    }
+  };
+
+  /**
+   * Toggle the next sibling item.
+   *
+   *  @param jQuery $item
+   *    The current element of the field item row.
+   *  @param string action_name
+   *    The toggle action - 'collapse' or 'expand'.
+   *  @param object options
+   *    See toggle().
+   */
+  Toggler.prototype.toggleNextItem = function($item, action_name, options) {
+    if ($item.length > 0) {
+      var $nextItem = this.controller.nextItem($item);
+      if ($nextItem.length > 0) {
+        this.toggle($nextItem, action_name, options);
+      }
+    }
+  };
+
+  /**
+   * Determine the Toggle action based on the element's current classes.
+   *
+   * @param object element
+   *   The fieldset element or jQuery.
+   *
+   * @return object
+   *   The action object.
+   */
+  Toggler.prototype.getCurrentAction = function(element) {
+    var self = this;
+    var $element = $(element);
+
+    var current_action = self.actions.expand;
+    $.each(self.actions, function(action_name, action_data) {
+      if ($element.hasClass(action_data.classname)) {
+        current_action = action_data;
+        return false;
+      }
+    });
+
+    return current_action;
+  };
+
+  /**
+   * Determine the Toggle action based on the element's current classes.
+   *
+   * @param object element
+   *   The fieldset element or jQuery.
+   *
+   * @return object
+   *   The action object.
+   */
+  Toggler.prototype.getToggleAction = function(element) {
+    var self = this;
+    var current_action = self.getCurrentAction(element);
+    return current_action && ('opposite' in current_action) && (current_action.opposite in self.actions) ? self.actions[current_action.opposite] : self.actions.expand;
+  };
+
+
+  /**
+   * Toggle Controller.
+   */
+  var controller = Drupal.paragraphsCollapsibleController = Drupal.paragraphsCollapsibleController || {};
+
+  controller.savedStates = {};
+  controller.toolBarHeight = null;
+
+  controller.actions = {
+    collapse: {
+      name: 'collapse',
+      opposite: 'expand',
+      isOpen: false,
+      classname: 'collapsed',
+      onText: Drupal.t('Show'),
+      allOnText: Drupal.t('Expand All')
+    },
+    expand: {
+      name: 'expand',
+      opposite: 'collapse',
+      isOpen: true,
+      classname: 'expanded',
+      onText: Drupal.t('Hide'),
+      allOnText: Drupal.t('Collapse All')
+    }
+  };
+
+  // Initialize togglers.
+  controller.togglers = {};
+
+  /**
+   * AJAX based toggler.
+   */
+  controller.togglers.ajax = new Toggler(controller, {
+    actions: {
+      collapse: {
+        ajax: {
+          button: {
+            name: 'collapse',
+            classname: 'paragraphs-collapse-button'
+          }
+        }
+      },
+      expand: {
+        ajax: {
+          button: {
+            name: 'edit',
+            classname: 'paragraphs-edit-button'
+          }
+        }
+      }
+    },
+    callbacks: {
+      canToggle: function(self, $items) {
+        // Check the first item.
+        var $item = $items.first();
+        var item_element = $item.get(0);
+
+        // Check for an existing value.
+        if (('paragraphsItemIsAjax' in item_element)) {
+          return item_element.paragraphsItemIsAjax;
+        }
+
+        // Check for AJAX elements.
+        var is_ajax = false;
+        var button_selectors = [];
+        $.each(self.actions, function(action_key, action_data) {
+          button_selectors.push('.' + action_data.ajax.button.classname);
+        });
+
+        if (button_selectors.length > 0) {
+          is_ajax = $item.children('.form-actions').find(button_selectors.join()).length > 0;
+        }
+
+        item_element.paragraphsItemIsAjax = is_ajax;
+        return is_ajax;
+      },
+      toggle: function(self, $items, action_name, options) {
+        // Enable the crawler if toggling more than 1 item.
+        // Since this is AJAX, the subsequent item objects would get destroyed
+        // and replaced after the AJAX request. With crawl enabled,
+        // only the first item is processed and then the next item is found
+        // after AJAX Complete.  The combined settings is passed to toggle() in
+        // subsequent calls so this only needs to be set once.
+        if ($items.length > 1) {
+          options.crawl = true;
+        }
+
+        // Get the first item to process or seed the crawler.
+        var $item = $items.first();
+        var item_element = $item.get(0);
+
+        // Merge settings.
+        var settings = $.extend(true,
+          {
+            'fast': false,
+            'expandFieldsets': true,
+            'crawl': false
+          },
+          options
+        );
+
+        // Crawl to the next item.
+        var crawl = function($current_item) {
+          if (settings.crawl && $current_item.length > 0) {
+            self.toggleNextItem($current_item, action_name, settings);
+          }
+        };
+
+        // Check flags to avoid processing multiple times.
+        if (item_element.animating || item_element.paragraphsAjaxing) {
+          return crawl($item);
+        }
+
+        // Get form actions wrapper element.
+        var $form_actions = $item.children('.form-actions');
+        if (!$form_actions.length) {
+          return crawl($item);
+        }
+
+        // Block action for special cases.
+        if ($form_actions.find('.paragraphs-deleteconfirm-button').length > 0) {
+          // Exit, nothing to do.
+          return crawl($item);
+        }
+
+        // Find the action button.
+        var requested_action = (action_name && action_name in self.actions) ? self.actions[action_name] : self.getToggleAction($item);
+
+        // Set vars based on requested action.
+        action_name = requested_action.name;
+        var other_action = self.actions[requested_action.opposite];
+
+        var $button = $form_actions.find('.' + requested_action.ajax.button.classname);
+        if (!$button.length) {
+          return crawl($item);
+        }
+
+        // Determine id to track states.
+        var id = self.controller.createItemId($item);
+        if (id) {
+          // Set state to match class added for action.
+          self.controller.savedStates[id] = requested_action.classname;
+        }
+
+        // Process button.
+        $button = $button.first();
+        var button_element_name = $button.attr('name');
+
+        // Catch the AJAX Complete.
+        // This is needed since Drupal.ajax blocks concurrent
+        // requests. The local Drupal.ajax.options.complete will fire
+        // first and then the global ajaxComplete listeners.
+        $(document).on('ajaxComplete.paragraphsCollapsible__' + button_element_name, function(ajax_event, ajax_xhr, ajax_settings) {
+          if (('extraData' in ajax_settings) && ('_triggering_element_name' in ajax_settings.extraData) &&
+              ajax_settings.extraData._triggering_element_name === button_element_name) {
+            var new_button_element_name = button_element_name.replace(/\_[^_]+\_button$/, '_' + other_action.ajax.button.name + '_button');
+            var $new_item = $('.paragraph-bundle-content-collapsible > .form-actions [name="' + new_button_element_name + '"]')
+              .closest('.paragraph-bundle-content-collapsible');
+            // On complete actions.
+            if ($new_item.length > 0) {
+              // Expand nested elements.
+              if (requested_action.isOpen) {
+                // Expand collapsible fieldsets.
+                if (settings.expandFieldsets) {
+                  var $fieldsets = self.controller.findItemCollapsedFieldsets($new_item);
+                  $fieldsets.each(function() {
+                    self.controller.expandCollapsibleFieldset(this);
+                  });
+                }
+
+                var new_item_element = $new_item.get(0);
+                new_item_element.paragraphsAjaxing = false;
+              }
+            }
+
+            // Unbind this listener.
+            $(document).off('ajaxComplete.paragraphsCollapsible__' + button_element_name);
+
+            // Crawl to the next item.
+            crawl($new_item);
+          }
+        });
+
+        // Trigger the AJAX button.
+        item_element.paragraphsAjaxing = true;
+        $button.trigger('mousedown');
+
+        // Promise / assume all to be toggled.
+        return $items.length;
+      }
+    }
+  });
+
+  /**
+   * Javascript based toggler.
+   */
+  controller.togglers.js = new Toggler(controller, {
+    actions: {
+      collapse: {
+        js: {
+          fx: 'slideUp'
+        }
+      },
+      expand: {
+        js: {
+          fx: 'slideDown',
+          fastFx: 'show'
+        }
+      }
+    },
+    callbacks: {
+      canToggle: function(self, $items) {
+        // Can JS toggle if it's not AJAX.
+        return !self.controller.togglers.ajax.canToggle($items);
+      },
+      toggle: function(self, $items, action_name, toggle_options) {
+        var toggledCount = 0;
+
+        // Merge settings.
+        var settings = $.extend(true,
+          {
+            'fast': false,
+            'expandFieldsets': true,
+            'crawl': false
+          },
+          toggle_options
+        );
+
+        // Determine initial requested action.
+        var initial_requested_action = (action_name && action_name in self.actions) ? self.actions[action_name] : self.getToggleAction($items.first());
+
+        // Process each item.
+        $items.each(function () {
+          // Skip if already animating.
+          if (this.animating) {
+            return true;
+          }
+
+          // Initialize item processing.
+          var item_element = this;
+          var $item = $(item_element);
+          var requested_action = initial_requested_action;
+
+          // Block collapse for special cases.
+          if (!requested_action.isOpen) {
+            // Do not collapse deleted paragraphs.
+            if ($item.children('.form-actions').find('.paragraphs-deleteconfirm-button').length > 0) {
+              if ($item.hasClass(self.actions.collapse.classname)) {
+                // Expand this special item.
+                requested_action = self.actions.expand;
+              }
+              else {
+                // Skip, nothing to do.
+                return true;
+              }
+            }
+          }
+
+          // Set vars based on requested action.
+          action_name = requested_action.name;
+          var other_action = self.actions[requested_action.opposite];
+
+          // Skip early if this item is already in the correct state.
+          if ($item.hasClass(requested_action.classname)) {
+            toggledCount++;
+            return true;
+          }
+
+          // Find elements to toggle.
+          var $elements = self.controller.findItemCollapsibleElements($item);
+          if (!$elements || $elements.length === 0) {
+            return true;
+          }
+
+          // Determine id to track states.
+          var id = self.controller.createItemId($item);
+          if (id) {
+            // Set state to match class added for action.
+            self.controller.savedStates[id] = requested_action.classname;
+          }
+
+          // Invoke collapse actions.
+          var fn_complete = function() {
+            // Toggle classes on the item.
+            $item
+              .removeClass(other_action.classname)
+              .addClass(requested_action.classname);
+
+            // Update hidden toggle text.
+            $item
+              .find('> .paragraph-bundle-title > .paragraph-bundle-title-collapsible-prefix')
+              .html(requested_action.onText);
+
+            // Expand nested elements.
+            if (requested_action.isOpen) {
+              // Expand collapsible fieldsets.
+              if (settings.expandFieldsets) {
+                var $fieldsets = self.controller.findItemCollapsedFieldsets($elements);
+                $fieldsets.each(function() {
+                  self.controller.expandCollapsibleFieldset(this);
+                });
+              }
+
+              // Expand nested triggers.
+              var child_settings = $.extend(settings, {'fast': true});
+              // TODO: limit this to next level only since the toggleAll of the next
+              // level will keep digging with this line.
+              $('.field-multiple-table .paragraphs-collapsible-trigger-link', $elements).each(function() {
+                self.controller.toggleAll(this, child_settings, action_name);
+              });
+            }
+
+            // Clear animating flag.
+            item_element.animating = false;
+          };
+
+          // Set animating flag.
+          item_element.animating = true;
+
+          if (settings.fast) {
+            // Fast effect.
+            if ('fastFx' in requested_action.js) {
+              $elements[requested_action.js.fastFx]();
+            }
+
+            // Item complete actions.
+            fn_complete();
+          }
+          else if ('fx' in requested_action.js) {
+            $elements[requested_action.js.fx]('fast', fn_complete);
+          }
+
+          toggledCount++;
+          return true;
+        });
+
+        return toggledCount;
+      }
+    }
+  });
+
+  /**
+   * Load the toggler for a given item.
+   *
+   * @param jQuery $items
+   *   The element of the field item row.
+   *
+   * @return Toggler|null
+   *   The found toggler or null.
+   */
+  controller.loadToggler = function($items) {
+    var self = this;
+
+    // Detect toggler in order of togglers built order.
+    var active_toggler = null;
+    $.each(self.togglers, function(toggler_name, obj) {
+      if (obj.canToggle($items)) {
+        active_toggler = obj;
+        return false;
+      }
+    });
+
+    return active_toggler;
+  };
+
+  /**
+   * Find all collapsible elements within a field item.
+   *
+   * @param object item
+   *   The element of the field item row.
+   *
+   * @return object
+   *   The jQuery set of found elements.
+   */
+  controller.findItemCollapsibleElements = function(item) {
+    var $item = $(item);
+    var $elements;
+    var $ajax_content = $item.children('.ajax-new-content');
+    if ($ajax_content.length > 0) {
+      $elements = $ajax_content.children(':not(.paragraph-bundle-content-collapsible-shown)');
+    }
+    else {
+      $elements = $item.children(':not(.paragraph-bundle-content-collapsible-shown)');
+    }
+
+    return $elements;
+  };
+
+  /**
+   * Find all collapsible fieldsets within an item.
+   *
+   * @param jQuery $elements
+   *   The item's collapsible elements to limit the search or the item itself.
+   *
+   * @return object
+   *   The jQuery set of found elements.
+   */
+  controller.findItemCollapsedFieldsets = function($elements) {
+    var $fieldsets = $('> fieldset.collapsible.collapsed, *:not(.filter-guidelines-item) fieldset.collapsible.collapsed', $elements);
+    if ($elements.is('fieldset')) {
+      var $top_fieldsets = $elements.filter('fieldset.collapsible.collapsed');
+      if ($top_fieldsets.length > 0) {
+        $fieldsets.add($top_fieldsets);
+      }
+    }
+    return $fieldsets;
+  };
+
+  /**
+   * Create a paragraph id for the field item.
+   *
+   * @param object item
+   *   The element of the field item row.
+   *
+   * @return string|null
+   *   The unique id.
+   */
+  controller.createItemId = function(item) {
+    var $item = $(item);
+    var item_element = $item.get(0);
+
+    // Check for an existing id.
+    if (('paragraphsCollapsibleItemId' in item_element) && item_element.paragraphsCollapsibleItemId) {
+      return item_element.paragraphsCollapsibleItemId;
+    }
+
+    // Create the id.
+    var id = null;
+    var $title = $(item).children('.paragraph-bundle-title').first();
+    if ($title.length > 0) {
+      id = $title.attr('id');
+      if (id) {
+        id = id.replace(/\-paragraph\-bundle\-title(?:\-\-\d+)?$/, '');
+
+        item_element.paragraphsCollapsibleItemId = id;
+      }
+    }
+
+    return id;
+  };
+
+  /**
+   * Determine if the field item is toggle by AJAX.
+   *
+   * @param object item
+   *   The element of the field item row.
+   *
+   * @return bool
+   *   TRUE if the item is toggle by AJAX.
+   */
+  controller.itemIsAjax = function(item) {
+    return this.togglers.ajax.canToggle(item);
+  };
+
+  /**
+   * Determine if the field item is toggled by JavaScript.
+   *
+   * @param object item
+   *   The element of the field item row.
+   *
+   * @return bool
+   *   TRUE if the item is toggled by JavaScript.
+   */
+  controller.itemIsJs = function(item) {
+    return this.togglers.js.canToggle(item);
+  };
+
+  /**
+   * Find the next field item.
+   *
+   * @param object item
+   *   The current element of the field item row.
+   *
+   * @return object
+   *   The next field item element.
+   */
+  controller.nextItem = function(item) {
+    var $item = $(item).first();
+    return $item.closest('tr').next('tr').find('> .paragraph-bundle-content-collapsible');
+  };
+
+  /**
+   * Show / Hide a single paragraph.
+   *
+   * @param object item
+   *   The element of the field item row.
+   * @param string action_name
+   *   The toggle action - 'collapse' or 'expand'.
+   * @param object options
+   *   A set of options to configure the toggle:
+   *   - fast (bool): If enabled, the transitions will not use the animated
+   *     slideUp / slideDown. The faster hide / show is used.
+   *   - expandFieldsets (bool): Expand all nested fieldsets.
+   *   - complete (function): Callback on complete.
+   *
+   * @return boolean
+   *   TRUE if the paragraph was toggled.
+   */
+  controller.toggleItem = function(item, action_name, options) {
+    var settings = options || {};
+    var $item = $(item);
+    var active_toggler = this.loadToggler($item);
+    if (active_toggler) {
+      active_toggler.toggle($item, action_name, settings);
+      return true;
+    }
+    return false;
+  };
+
+  /**
+   * Show / Hide all paragraphs.
+   *
+   * @param object triggerElement
+   *   The trigger element to toggle all child paragraphs.
+   * @param string action_name
+   *   The toggle action - 'collapse' or 'expand'.
+   * @param object options
+   *   See toggleItem().
+   *
+   * @return int
+   *   The count of paragraphs toggled.
+   */
+  controller.toggleItems = function(triggerElement, action_name, options) {
+    var toggledCount = 0;
+    var settings = options || {};
+
+    var $form_item = $(triggerElement).closest('.form-item');
+    if ($form_item.length > 0) {
+      var $items = $form_item.children('.field-multiple-table').find('> tbody > tr > .paragraph-bundle-content-collapsible');
+      if ($items.length > 0) {
+        var active_toggler = this.loadToggler($items);
+        if (active_toggler) {
+          // Assume toggler will toggle all items. Any return is not reliable
+          // since the toggle action is async or AJAX.
+          toggledCount = $items.length;
+          active_toggler.toggle($items, action_name, settings);
+        }
+      }
+    }
+
+    return toggledCount;
+  };
+
+  /**
+   * Trigger show / hide for given trigger element.
+   *
+   * @param object triggerElement
+   *   The trigger element to toggle all child paragraphs.
+   * @param object options
+   *   See toggleItem().
+   * @param string action_name
+   *   The toggle action - 'collapse', 'expand'. If not defined, it will be
+   *   derive from the class name.
+   *
+   * @return int
+   *   The count of paragraphs toggled.
+   */
+  controller.toggleAll = function(triggerElement, options, action_name) {
+    var $t = $(triggerElement);
+
+    // Determine action.
+    var requested_action = (action_name && action_name in controller.actions) ? controller.actions[action_name] : this.getToggleAction($t);
+    var requested_action_name = requested_action.name;
+
+    // Toggle paragraphs.
+    var toggledCount = this.toggleItems(triggerElement, requested_action_name, options);
+
+    // Update trigger class and label.
+    if (toggledCount > 0) {
+      this.updateAllTrigger(triggerElement, requested_action_name);
+    }
+
+    return toggledCount;
+  };
+
+  /**
+   * Update the trigger element based on the action.
+   *
+   * @param object triggerElement
+   *   The trigger element.
+   * @param string action_name
+   *   The toggle action - 'collapse', 'expand'. If not defined, it will be
+   *   derive from the class name.
+   */
+  controller.updateAllTrigger = function(triggerElement, action_name) {
+    var $t = $(triggerElement);
+
+    var requested_action = (action_name && action_name in controller.actions) ? controller.actions[action_name] : this.getToggleAction($t);
+    action_name = requested_action.name;
+    var other_action = controller.actions[requested_action.opposite];
+
+    // Build triggers.
+    var $triggers = [$t];
+
+    // Add other trigger.
+    var $parent_table = $t.closest('table');
+    if ($parent_table.length > 0) {
+      if ($parent_table.hasClass('field-multiple-table')) {
+        // Items table click, add sticky header trigger.
+        $triggers.push($parent_table.siblings('.sticky-header').find('.paragraphs-collapsible-trigger-link'));
+      }
+      else if ($parent_table.hasClass('sticky-header')) {
+        // Sticky header click, add items table click.
+        $triggers.push($parent_table.siblings('table.field-multiple-table').find('.paragraphs-collapsible-trigger-link'));
+      }
+    }
+
+    $.each($triggers, function(index, $trigger) {
+      if ($trigger.length > 0) {
+        $trigger
+          .removeClass(other_action.classname)
+          .addClass(requested_action.classname)
+          .text(requested_action.allOnText);
+      }
+    });
+  };
+
+  /**
+   * Determine the Toggle action based on the element's current classes.
+   *
+   * @param object element
+   *   The fieldset element or jQuery.
+   *
+   * @return object
+   *   The action object.
+   */
+  controller.getCurrentAction = function(element) {
+    var $element = $(element);
+    var active_toggler = this.loadToggler($element);
+    if (active_toggler) {
+      return active_toggler.getCurrentAction($element);
+    }
+
+    // Default to expand if no toggler found.
+    return controller.actions.expand;
+  };
+
+  /**
+   * Determine the Toggle action based on the element's current classes.
+   *
+   * @param object element
+   *   The fieldset element or jQuery.
+   *
+   * @return object
+   *   The action object.
+   */
+  controller.getToggleAction = function(element) {
+    var $element = $(element);
+    var active_toggler = this.loadToggler($element);
+    if (active_toggler) {
+      return active_toggler.getToggleAction($element);
+    }
+
+    // Default to expand if no toggler found.
+    return controller.actions.expand;
+  };
+
+  /**
+   * Expand a collapsible fieldset.
+   *
+   * Based on Drupal.toggleFieldset() to toggle without clicks and window
+   * scrolling.
+   *
+   * @param object element
+   *   The fieldset element or jQuery.
+   */
+  controller.expandCollapsibleFieldset = function(element) {
+    var $fieldset = $(element);
+    var fieldset = $fieldset.get(0);
+
+    if (!fieldset.animating && $fieldset.is('.collapsed')) {
+      fieldset.animating = true;
+      $('> .fieldset-wrapper', fieldset).show();
+      $fieldset
+        .removeClass('collapsed')
+        .trigger({ type: 'collapsed', value: false })
+        .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
+
+      fieldset.animating = false;
+    }
+  };
+
+  /**
+   * Scroll a given fieldset into view as much as possible.
+   */
+  controller.collapseScrollIntoView = function(element) {
+    var $element = $(element).first();
+    var offset = $element.offset();
+    var slack = 55;
+
+    if (offset.top > 0) {
+      if (this.toolBarHeight === null) {
+        this.toolBarHeight = $('#toolbar').outerHeight() || 0;
+      }
+      var y = Math.floor(offset.top - this.toolBarHeight - slack);
+      y = y > 0 ? y : 0;
+      $(window).scrollTop(y);
+    }
+  };
+
+  /**
+   * Enable Expand/Collapse feature for paragraph bundles.
+   * Show the name & type of each bundle and hide contents inside those.
+   */
+  Drupal.behaviors.paragraphsCollapsible = {
+    attach: function (context, settings) {
+      var $new_items = $('.paragraph-bundle-content-collapsible', context).once('paragraphs');
+
+      if ($new_items.length > 0) {
+        // Trigger for a single paragaph.
+        $('> .paragraph-bundle-title, > .ajax-new-content > .paragraph-bundle-title', $new_items).each(function() {
+          var $t = $(this);
+          var $item = $t.closest('.paragraph-bundle-content-collapsible');
+
+          var has_errors = $item.find('.error:first').length > 0;
+          var is_ajax_new = $item.children('.ajax-new-content').length > 0;
+          var is_ajax_form = controller.itemIsAjax($item);
+          var current_action = controller.getCurrentAction($item);
+          var is_expanded = current_action.isOpen;
+
+          // Prefix title with a toggle image.
+          $('<span class="paragraph-bundle-title-collapsible-prefix element-invisible"></span>')
+              .append(current_action.onText)
+              .prependTo($t)
+              .after(' ');
+
+          // Update toggle state.
+          var id;
+          var expandFieldsets = is_expanded;
+          if (has_errors || is_ajax_new) {
+            // Expand errors and new content.
+            if (!is_expanded && !is_ajax_form) {
+              expandFieldsets = false;
+              controller.toggleItem($item, controller.actions.expand.name);
+            }
+          }
+          else if (!is_ajax_form && !is_ajax_new && !$item.hasClass('no-collapsible-state-restore') &&
+                (id = controller.createItemId($item)) && (id in controller.savedStates) &&
+                controller.savedStates[id] && !$item.hasClass(controller.savedStates[id])) {
+            // Restore saved states.
+            expandFieldsets = false;
+            var restore_action_name = controller.savedStates[id] === controller.actions.collapse.classname ? controller.actions.collapse.name : controller.actions.collapse.opposite;
+            controller.toggleItem($item, restore_action_name);
+          }
+
+          // Ensure fieldsets are expanded.
+          if (expandFieldsets) {
+            var $fieldsets = controller.findItemCollapsedFieldsets($item);
+            $fieldsets.each(function() {
+              controller.expandCollapsibleFieldset(this);
+            });
+          }
+        })
+        .click(function(event) {
+          // Prevent the default click event.
+          event.preventDefault();
+          var $item = $(this).closest('.paragraph-bundle-content-collapsible');
+          if ($item.length > 0) {
+            var action = controller.getToggleAction($item);
+            controller.toggleItem($item, action.name);
+          }
+        });
+
+        // JS Only edit link.
+        var $fake_buttons = $('> .form-actions, > .ajax-new-content > .form-actions', $new_items).find('.paragraphs-edit-link, .paragraphs-collapse-link');
+        if ($fake_buttons.length > 0) {
+          $fake_buttons.click(function(event) {
+            // Prevent the default click event.
+            event.preventDefault();
+            var $item = $(this).closest('.paragraph-bundle-content-collapsible');
+            if ($item.length > 0) {
+              var action = controller.getToggleAction($item);
+              controller.toggleItem($item, action.name, {
+                'complete': function($element) {
+                  controller.collapseScrollIntoView($element);
+                }
+              });
+            }
+          });
+
+          // Add jQuery UI button effects.
+          if ($.fn.button) {
+            $fake_buttons.button();
+          }
+        }
+      }
+
+      // Trigger for toggle all paragaphs.
+      $('.paragraphs-collapsible-trigger-link', context).once("paragraphs")
+        .click(function(event) {
+          // Prevent the default click event.
+          event.preventDefault();
+          controller.toggleAll(this);
+        });
+    }
+  };
+
+})(jQuery, Drupal, this, this.document);
diff --git a/paragraphs.field_widget.inc b/paragraphs.field_widget.inc
index 921843c5da4730328349ca02bfb042ec23251261..c2e8fa985d01723aac37723da583768ea59051c8 100644
--- a/paragraphs.field_widget.inc
+++ b/paragraphs.field_widget.inc
@@ -345,6 +345,10 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
     $instance['settings']['title_multiple'] = PARAGRAPHS_DEFAULT_TITLE_MULTIPLE;
   }
 
+  if (!isset($instance['settings']['collapsible'])) {
+    $instance['settings']['collapsible'] = PARAGRAPHS_DEFAULT_EDIT_COLLAPSIBLE;
+  }
+
   // If the paragraph item form contains another paragraph,
   // we might ran into a recursive loop. Prevent that.
   if ($recursion++ > PARAGRAPHS_RECURSION_LIMIT) {
@@ -386,6 +390,7 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
 
   $default_edit_mode = isset($instance['settings']['default_edit_mode']) ? $instance['settings']['default_edit_mode'] : PARAGRAPHS_DEFAULT_EDIT_MODE;
   $default_edit_mode_override = isset($instance['settings']['default_edit_mode_override']) ? $instance['settings']['default_edit_mode_override'] : PARAGRAPHS_DEFAULT_EDIT_MODE_OVERRIDE;
+  $default_edit_open = isset($instance['settings']['default_edit_open']) ? $instance['settings']['default_edit_open'] : PARAGRAPHS_DEFAULT_EDIT_OPEN;
   $force_open = (!empty($instance['widget']['paragraphs_edit_mode_open']) || count($items) < $default_edit_mode_override);
 
   $being_edited_paragraph = ($default_edit_mode === 'open');
@@ -397,11 +402,16 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
     if (isset($field_state['entity'][$delta]->confirmed_removed) && $field_state['entity'][$delta]->confirmed_removed) {
       $confirmed_deleted_paragraph = TRUE;
     }
-    if ($being_edited_paragraph || (isset($field_state['entity'][$delta]->being_edited) && $field_state['entity'][$delta]->being_edited)) {
-      $being_edited_paragraph = TRUE;
-    }
-    else {
-      $being_edited_paragraph = FALSE;
+    if ($default_edit_mode !== 'open')  {
+      // Closed edit modes.
+      if (isset($field_state['entity'][$delta]->being_edited)) {
+        // Entity state controls being_edited.
+        $being_edited_paragraph = !empty($field_state['entity'][$delta]->being_edited);
+      }
+      elseif ($default_edit_mode !== 'open') {
+        // Default open controls being_edited.
+        $being_edited_paragraph = $default_edit_open;
+      }
     }
 
     /* @var $paragraph_item ParagraphsItemEntity */
@@ -409,6 +419,11 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
     $paragraph_item->setHostEntity($field_state['instance']['entity_type'], $element['#entity'], $langcode, FALSE);
   }
   else {
+    // Set being_edited to default open initially.
+    if ($default_edit_mode !== 'open') {
+      $being_edited_paragraph = $default_edit_open;
+    }
+
     if (isset($items[$delta])) {
       $paragraph_item = paragraphs_field_get_entity($items[$delta]);
     }
@@ -445,6 +460,7 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
       $element['paragraph_bundle_title'] = array(
         '#type' => 'container',
         '#weight' => -100,
+        '#attributes' => array('class' => array('paragraph-bundle-title')),
       );
       $element['paragraph_bundle_title']['info'] = array(
         '#markup' => t('!title type: %bundle', array('!title' => t($instance['settings']['title']), '%bundle' => $bundle_info->name)),
@@ -490,6 +506,9 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
             '#validate' => array(),
             '#submit' => array('paragraphs_collapse_submit'),
             '#limit_validation_errors' => array(),
+            '#attributes' => array(
+              'class' => array('paragraphs-collapse-button'),
+            ),
             '#ajax' => array(
               'path' => 'paragraphs/collapse/ajax',
               'effect' => 'fade',
@@ -503,6 +522,7 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
         if($default_edit_mode === 'preview' && entity_access('view', 'paragraphs_item', $paragraph_item)) {
           $element['paragraph_bundle_preview'] = array(
             '#type' => 'container',
+            '#attributes' => array('class' => array('paragraph-bundle-preview')),
           );
           $preview = $paragraph_item->view('paragraphs_editor_preview');
           $element['paragraph_bundle_preview']['preview'] = $preview;
@@ -533,6 +553,9 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
           '#validate' => array(),
           '#submit' => array('paragraphs_edit_submit'),
           '#limit_validation_errors' => array(),
+          '#attributes' => array(
+            'class' => array('paragraphs-edit-button'),
+          ),
           '#ajax' => array(
             'path' => 'paragraphs/edit/ajax',
             'effect' => 'fade',
@@ -542,7 +565,6 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
         );
       }
 
-
       if (isset($paragraph_item)) {
         $element['actions']['remove_button'] = array(
           '#delta' => $delta,
@@ -552,6 +574,9 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
           '#validate' => array(),
           '#submit' => array('paragraphs_remove_submit'),
           '#limit_validation_errors' => array(),
+          '#attributes' => array(
+            'class' => array('paragraphs-remove-button'),
+          ),
           '#ajax' => array(
             'path' => 'paragraphs/remove/ajax',
             'effect' => 'fade',
@@ -610,6 +635,9 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
         '#validate' => array(),
         '#submit' => array('paragraphs_restore_submit'),
         '#limit_validation_errors' => array(),
+        '#attributes' => array(
+          'class' => array('paragraphs-restore-button'),
+        ),
         '#ajax' => array(
           'path' => 'paragraphs/restore/ajax',
           'effect' => 'fade',
@@ -624,6 +652,9 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
         '#validate' => array(),
         '#submit' => array('paragraphs_deleteconfirm_submit'),
         '#limit_validation_errors' => array(),
+        '#attributes' => array(
+          'class' => array('paragraphs-deleteconfirm-button'),
+        ),
         '#ajax' => array(
           'path' => 'paragraphs/deleteconfirm/ajax',
           'effect' => 'fade',
@@ -631,6 +662,61 @@ function paragraphs_field_widget_form_build(&$form, &$form_state, $field, $insta
         '#weight' => 1001,
       );
     }
+
+    // Collapsible open paragraphs.
+    if (!empty($instance['settings']['collapsible'])) {
+      // Attach js and css.
+      $element['#attached']['js'][] = drupal_get_path('module', 'paragraphs') . '/paragraphs.collapsible.js';
+      $element['#attached']['css'][] = drupal_get_path('module', 'paragraphs') . '/paragraphs.collapsible.css';
+
+      // Add fake buttons for open mode.
+      if ($default_edit_mode === 'open' && $field['cardinality'] != 1 &&
+          isset($paragraph_item) && entity_access('update', 'paragraphs_item', $paragraph_item)) {
+        $fake_button_links = array(
+          'edit' => t('Edit'),
+          'collapse' => t('Collapse'),
+        );
+        foreach ($fake_button_links as $fake_button_action => $fake_button_label) {
+          if (!isset($element['actions'][$fake_button_action . '_button'])) {
+            $fake_button_link_name = implode('_', $parents) . '_' . $fake_button_action . '_link';
+            $fake_button_link_attributes = array(
+              'class' => array(
+                drupal_html_class($fake_button_link_name),
+                'paragraphs-' . $fake_button_action . '-link',
+              ),
+            );
+
+            $element['actions'][$fake_button_action . '_link'] = array(
+              '#delta' => $delta,
+              '#name' => $fake_button_link_name,
+              '#type' => 'markup',
+              '#prefix' => '<a href="#"' . drupal_attributes($fake_button_link_attributes) . '>',
+              '#markup' => $fake_button_label,
+              '#suffix' => '</a>',
+              '#access' => TRUE,
+              '#weight' => 999,
+              '#attached' => array(
+                'library' => array(
+                  array('system', 'ui.button'),
+                ),
+              ),
+            );
+          }
+        }
+      }
+
+      // Add classes to always show these elements.
+      $collapsible_elements_shown = array(
+        'paragraph_bundle_title',
+        'paragraph_bundle_preview',
+        'actions',
+      );
+      foreach ($collapsible_elements_shown as $collapsible_element_name) {
+        if (isset($element[$collapsible_element_name])) {
+          $element[$collapsible_element_name]['#attributes']['class'][] = 'paragraph-bundle-content-collapsible-shown';
+        }
+      }
+    }
   }
 
   // Hide full item when we are confirmed delete.
diff --git a/paragraphs.module b/paragraphs.module
index 47093b6ca57d217ea0c88b6491dc3d4fa1447600..2385bd5c490b17d7c7dcb8265cd391b07b6e5e10 100644
--- a/paragraphs.module
+++ b/paragraphs.module
@@ -10,6 +10,8 @@ define('PARAGRAPHS_DEFAULT_TITLE', 'Paragraph');
 define('PARAGRAPHS_DEFAULT_TITLE_MULTIPLE', 'Paragraphs');
 define('PARAGRAPHS_DEFAULT_EDIT_MODE', 'open');
 define('PARAGRAPHS_DEFAULT_EDIT_MODE_OVERRIDE', 1);
+define('PARAGRAPHS_DEFAULT_EDIT_OPEN', FALSE);
+define('PARAGRAPHS_DEFAULT_EDIT_COLLAPSIBLE', FALSE);
 define('PARAGRAPHS_DEFAULT_ADD_MODE', 'select');
 
 /**
@@ -431,6 +433,8 @@ function paragraphs_field_info() {
       'title_multiple' => PARAGRAPHS_DEFAULT_TITLE_MULTIPLE,
       'allowed_bundles' => array(),
       'bundle_weights' => array(),
+      'collapsible' => PARAGRAPHS_DEFAULT_EDIT_COLLAPSIBLE,
+      'default_edit_open' => PARAGRAPHS_DEFAULT_EDIT_OPEN,
     ),
     'default_widget' => 'paragraphs_hidden',
     'default_formatter' => 'paragraphs_view',
@@ -547,9 +551,9 @@ function paragraphs_field_instance_settings_form($field, $instance) {
     '#title' => t('Default edit mode'),
     '#description' => t('The default edit mode the paragraph item is in. Preview will render the paragraph in the preview view mode.'),
     '#options' => array(
-      'open' => t('Open'),
-      'closed' => t('Closed'),
-      'preview' => t('Preview'),
+      'open' => t('Fully loaded form'),
+      'closed' => t('AJAX form'),
+      'preview' => t('AJAX form + Preview'),
     ),
     '#default_value' => isset($settings['default_edit_mode']) ? $settings['default_edit_mode'] : PARAGRAPHS_DEFAULT_EDIT_MODE,
     '#required' => TRUE,
@@ -581,6 +585,20 @@ function paragraphs_field_instance_settings_form($field, $instance) {
     $element['default_edit_mode_override']['#element_validate'] = array('element_validate_integer_positive');
   }
 
+  $element['default_edit_open'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Open paragraph forms initially'),
+    '#default_value' => isset($settings['default_edit_open']) ? $settings['default_edit_open'] : PARAGRAPHS_DEFAULT_EDIT_OPEN,
+    '#description' => t('The "Fully loaded form" edit mode only supports "collapsed" initially if "Enable improved collapsibility" is enabled.'),
+  );
+
+  $element['collapsible'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable improved collapsibility'),
+    '#description' => t('Provides improved collapsible support with clickable bundle labels and a collapse / expand all trigger for the "Fully loaded form" edit mode.'),
+    '#default_value' => isset($settings['collapsible']) ? $settings['collapsible'] : PARAGRAPHS_DEFAULT_EDIT_COLLAPSIBLE,
+  );
+
   $element['add_mode'] = array(
     '#type' => 'select',
     '#title' => t('Add mode'),
@@ -1156,7 +1174,9 @@ function theme_paragraphs_field_multiple_value_form($variables) {
   }
 
   $add_mode = (isset($instance['settings']['add_mode']) ? $instance['settings']['add_mode'] : PARAGRAPHS_DEFAULT_ADD_MODE);
-
+  $default_edit_mode = isset($instance['settings']['default_edit_mode']) ? $instance['settings']['default_edit_mode'] : PARAGRAPHS_DEFAULT_EDIT_MODE;
+  $default_edit_open = isset($instance['settings']['default_edit_open']) ? $instance['settings']['default_edit_open'] : PARAGRAPHS_DEFAULT_EDIT_OPEN;
+  $collapsible = isset($instance['settings']['collapsible']) ? $instance['settings']['collapsible'] : PARAGRAPHS_DEFAULT_EDIT_COLLAPSIBLE;
   $required = !empty($element['#required']) ? theme('form_required_marker', $variables) : '';
 
   // Sort items according to '_weight' (needed when the form comes back after
@@ -1182,23 +1202,67 @@ function theme_paragraphs_field_multiple_value_form($variables) {
     $table_id = drupal_html_id($element['#field_name'] . '_values');
     $order_class = $element['#field_name'] . '-delta-order';
 
-    $header = array(
-      array(
-        'data' => '<label>' . t('!title !required', array('!title' => $element['#title'], '!required' => $required)) . '</label>',
-        'colspan' => 2,
-        'class' => array('field-label'),
-      ),
-      t('Order'),
-    );
+    // Build table rows.
     $rows = array();
+    $collapsed_row_count = 0;
 
     // Add the items as table rows.
+    $item_base_classes = array(
+      'paragraph-bundle-content',
+      'paragraph-bundle-content-' . drupal_html_class($default_edit_mode),
+    );
+    if ($collapsible) {
+      $item_base_classes[] = 'paragraph-bundle-content-collapsible';
+    }
+
     foreach ($items as $key => $item) {
+      $item_classes = $item_base_classes;
+      $is_ajax_new = isset($item['#prefix']) && strpos($item['#prefix'], 'class="ajax-new-content"') !== FALSE;
+
+      if ($collapsible) {
+        $expanded = $default_edit_open;
+        $collapsible_restore = TRUE;
+        if ($default_edit_mode === 'open') {
+          // Non-AJAX collapsing.
+          $collapsible_restore = $default_edit_open;
+          if (!$expanded && !$is_ajax_new && empty($item['#entity']->removed)) {
+            // Collapse if set to initially collapse and the paragraph is not
+            // new content or deleted. The being_edited flag is set for all
+            // new open form items so it cannot be used to determine the state.
+            $expanded = FALSE;
+          }
+        }
+        else {
+          // AJAX collapsing.
+          $collapsible_restore = FALSE;
+          if (isset($item['#entity']->removed)) {
+            $expanded = !empty($item['#entity']->removed);
+          }
+          elseif (isset($item['#entity']->being_edited)) {
+            $expanded = !empty($item['#entity']->being_edited);
+          }
+        }
+
+        // Set collapsible state classes.
+        if ($expanded) {
+          $item_classes[] = 'expanded';
+        }
+        else {
+          $item_classes[] = 'collapsed';
+          $collapsed_row_count++;
+        }
+
+        // Block collapsible state restore for this item.
+        if (!$collapsible_restore) {
+          $item_classes[] = 'no-collapsible-state-restore';
+        }
+      }
+
       $item['_weight']['#attributes']['class'] = array($order_class);
       $delta_element = drupal_render($item['_weight']);
       $cells = array(
         array('data' => '', 'class' => array('field-multiple-drag')),
-        drupal_render($item),
+        array('data' => drupal_render($item), 'class' => $item_classes),
         array('data' => $delta_element, 'class' => array('delta-order')),
       );
       $rows[] = array(
@@ -1207,6 +1271,60 @@ function theme_paragraphs_field_multiple_value_form($variables) {
       );
     }
 
+    // Collapsible All trigger markup.
+    // Currently only displayed for non-AJAX forms.
+    // The JavaScript supports AJAX forms, however it is very inefficient since
+    // it has to serially trigger the AJAX callbacks due to Drupal.ajax only
+    // allowing 1 request at a time.
+    // Example: 9 large paragraphs could take 20+ seconds to collapse / expand.
+    $collapsible_all_markup = '';
+    if ($collapsible && $default_edit_mode === 'open') {
+      $collapsible_all_link_classes = array(
+        'paragraphs-collapsible-trigger-link',
+      );
+      if ($collapsed_row_count > 0) {
+        $collapsible_all_link_text = t('Expand All');
+        $collapsible_all_link_classes[] = 'collapsed';
+      }
+      else {
+        $collapsible_all_link_text = t('Collapse All');
+        $collapsible_all_link_classes[] = 'expanded';
+      }
+
+      $collapsible_all_markup = '<span style="float: right" class="paragraphs-collapsible-trigger">';
+      $collapsible_all_markup .= l($collapsible_all_link_text, '#', array(
+        'external' => TRUE,
+        'attributes' => array(
+          'class' => $collapsible_all_link_classes,
+        ),
+      ));
+      $collapsible_all_markup .= '</span>';
+    }
+
+    // Build table header.
+    if ($collapsible_all_markup) {
+      $header_text = t('!title !required !collapsible', array(
+        '!collapsible' => $collapsible_all_markup,
+        '!title' => $element['#title'],
+        '!required' => $required,
+      ));
+    }
+    else {
+      $header_text = t('!title !required', array(
+        '!title' => $element['#title'],
+        '!required' => $required,
+      ));
+    }
+
+    $header = array(
+      array(
+        'data' => '<label>' . $header_text . '</label>',
+        'colspan' => 2,
+        'class' => array('field-label'),
+      ),
+      t('Order'),
+    );
+
     $field_content = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => $table_id, 'class' => array('field-multiple-table'))));
 
     drupal_add_tabledrag($table_id, 'order', 'sibling', $order_class);
@@ -1454,4 +1572,4 @@ function paragraphs_modules_uninstalled($modules) {
   if (in_array('entitycache', $modules)) {
     paragraphs_remove_entitycache_table();
   }
-}
\ No newline at end of file
+}
