diff --git a/core/misc/ajax.js b/core/misc/ajax.js
index fefe9f3..f72100b 100644
--- a/core/misc/ajax.js
+++ b/core/misc/ajax.js
@@ -64,6 +64,7 @@
           element_settings.event = 'click';
         }
         element_settings.dialogType = $(this).data('dialog-type');
+        element_settings.dialogRenderer = $(this).data('dialog-renderer');
         element_settings.dialog = $(this).data('dialog-options');
         element_settings.base = $(this).attr('id');
         element_settings.element = this;
@@ -312,6 +313,8 @@
    *   Options for {@link Drupal.dialog}.
    * @prop {string} [dialogType]
    *   One of `'modal'` or `'dialog'`.
+   * @prop {string} [dialogRenderer]
+   *   The Drupal renderer for the dialog.
    * @prop {string} [prevent]
    *   List of events on which to stop default action and stop propagation.
    */
@@ -526,7 +529,12 @@
     else {
       ajax.options.url += '&';
     }
-    ajax.options.url += Drupal.ajax.WRAPPER_FORMAT + '=drupal_' + (element_settings.dialogType || 'ajax');
+    var wrapper_format = 'drupal_' + (element_settings.dialogType || 'ajax');
+    if (element_settings.dialogRenderer) {
+      wrapper_format += '_' + element_settings.dialogRenderer;
+    }
+    ajax.options.url += Drupal.ajax.WRAPPER_FORMAT + '=' + wrapper_format;
+
 
     // Bind the ajaxSubmit function to the element event.
     $(ajax.element).on(element_settings.event, function (event) {
diff --git a/core/misc/dialog/dialog.ajax.js b/core/misc/dialog/dialog.ajax.js
index 3f1b0c2..c73be9a 100644
--- a/core/misc/dialog/dialog.ajax.js
+++ b/core/misc/dialog/dialog.ajax.js
@@ -130,7 +130,7 @@
     ajax.commands.insert(ajax, response, status);
 
     // Move the buttons to the jQuery UI dialog buttons area.
-    if (!response.dialogOptions.buttons) {
+    if (!response.dialogOptions.buttons && response.dialogOptions.drupalAutoButtons !== false) {
       response.dialogOptions.drupalAutoButtons = true;
       response.dialogOptions.buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
     }
diff --git a/core/modules/outside_in/css/outside_in.theme.css b/core/modules/outside_in/css/outside_in.theme.css
index 1a17850..71f006d 100644
--- a/core/modules/outside_in/css/outside_in.theme.css
+++ b/core/modules/outside_in/css/outside_in.theme.css
@@ -64,25 +64,25 @@ button.toolbar-icon.toolbar-icon-edit.toolbar-item:hover > .toolbar-icon-edit:be
  */
 
 /* Highlight editable regions in edit mode. */
-#main-canvas.js-outside-in-edit-mode .outside-in-editable {
+#page-wrapper.js-outside-in-edit-mode .outside-in-editable {
   outline: 1px dashed rgba(0,0,0,0.5);
   box-shadow: 0 0 0 1px rgba(255,255,255,0.7);
 }
-#main-canvas.js-outside-in-edit-mode .outside-in-editable:hover {
+#page-wrapper.js-outside-in-edit-mode .outside-in-editable:hover {
   outline: 1px dashed rgba(0,0,0,0.5);
   box-shadow: 0 0 0 1px rgba(255,255,255,0.7);
   background-color: rgba(0,0,0,0.2);
 }
 /* Turn off the outlines on editables when the tray is open. */
-#main-canvas-wrapper.js-tray-open .outside-in-editable {
+#page-wrapper.js-tray-open .outside-in-editable {
   outline: transparent;
   outline-color: transparent;
   box-shadow: none;
 }
-#main-canvas-wrapper.js-tray-open .contextual {
+#page-wrapper.js-tray-open .contextual {
   opacity: 0;
 }
-#main-canvas-wrapper.js-tray-open .contextual:hover {
+#page-wrapper.js-tray-open .contextual:hover {
   opacity: 1;
 }
 
diff --git a/core/modules/outside_in/js/offcanvas.js b/core/modules/outside_in/js/offcanvas.js
index 0f5ae08..63bc6cf 100644
--- a/core/modules/outside_in/js/offcanvas.js
+++ b/core/modules/outside_in/js/offcanvas.js
@@ -3,129 +3,99 @@
  * Drupal's off-canvas library.
  */
 
-(function ($, Drupal) {
+(function ($, Drupal, debounce, displace) {
 
   'use strict';
 
-  // Set the initial state of the off-canvas element.
-  // If the state has been set previously, use it.
-  Drupal.offCanvas = {
-    visible: (Drupal.offCanvas ? Drupal.offCanvas.visible : false)
-  };
-
-  /**
-   * Create a wrapper container for the off-canvas element.
-   *
-   * @return {jQuery}
-   *   jQuery object that is the off-canvas wrapper element.
-   */
-  Drupal.theme.createOffCanvasWrapper = function createOffCanvasWrapper() {
-    return $('<div id="offcanvas" ' + (document.dir === 'ltr' ? 'data-offset-right' : 'data-offset-left') + ' role="region" aria-labelledby="offcanvas-header"></div>');
-  };
-
-  /**
-   * Create the title element for the off-canvas element.
-   *
-   * @param {string} title
-   *   The title string.
-   *
-   * @return {object}
-   *   jQuery object that is the off-canvas title element.
-   */
-  Drupal.theme.createTitle = function createTitle(title) {
-    return $('<h1 id="offcanvas-header">' + title + '</h1>');
-  };
-
-  /**
-   * Create the actual off-canvas content.
-   *
-   * @param {string} data
-   *   This is fully rendered HTML from Drupal.
-   *
-   * @return {object}
-   *   jQuery object that is the off-canvas content element.
-   */
-  Drupal.theme.createOffCanvasContent = function createOffCanvasContent(data) {
-    return $('<div class="offcanvas-content">' + data + '</div>');
-  };
-
-  /**
-   * Create the off-canvas close element.
-   *
-   * @param {object} offCanvasWrapper
-   *   The jQuery off-canvas wrapper element
-   * @param {object} pageWrapper
-   *   The jQuery off page wrapper element
-   *
-   * @return {jQuery}
-   *   jQuery object that is the off-canvas close element.
-   */
-  Drupal.theme.createOffCanvasClose = function createOffCanvasClose(offCanvasWrapper, pageWrapper) {
-    return $([
-      '<button class="offcanvasClose" aria-label="',
-      Drupal.t('Close configuration tray.'),
-      '"><span class="visually-hidden">',
-      Drupal.t('Close'),
-      '</span></button>'
-    ].join(''))
-    .on('click', function () {
-      pageWrapper
-        .removeClass('js-tray-open')
-        .one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function () {
-          Drupal.offCanvas.visible = false;
-          offCanvasWrapper.remove();
-          Drupal.announce(Drupal.t('Configuration tray closed.'));
-        }
-      );
+  function resetSize(event) {
+    var offsets = displace.offsets;
+    var $element = event.data.$element;
+    var $widget = $element.dialog('widget');
+
+    var adjustedOptions = {
+      position: {
+        my: 'right top',
+        at: 'right top' + (offsets.top !== 0 ? '+' + offsets.top : ''),
+        of: window
+      }
+    };
+
+    $widget.css({
+      position: 'fixed',
+      height: ($(window).height() - (offsets.top + offsets.bottom)) + 'px'
     });
-  };
-
-
-  /**
-   * Command to open an off-canvas element.
-   *
-   * @param {Drupal.Ajax} ajax
-   *   The Drupal Ajax object.
-   * @param {object} response
-   *   Object holding the server response.
-   * @param {number} [status]
-   *   The HTTP status code.
-   */
-  Drupal.AjaxCommands.prototype.openOffCanvas = function (ajax, response, status) {
-    // Discover display/viewport size.
-    // @todo Work on breakpoints for tray size:
-    //   https://www.drupal.org/node/2784599.
-    var $pageWrapper = $('#main-canvas-wrapper');
-    // var pageWidth = $pageWrapper.width();
-
-    // Construct off-canvas wrapper
-    var $offcanvasWrapper = Drupal.theme('createOffCanvasWrapper');
-
-    // Construct off-canvas internal elements.
-    var $offcanvasClose = Drupal.theme('createOffCanvasClose', $offcanvasWrapper, $pageWrapper);
-    var $title = Drupal.theme('createTitle', response.dialogOptions.title);
-    var $offcanvasContent = Drupal.theme('createOffCanvasContent', response.data);
-
-    // Put everything together.
-    $offcanvasWrapper.append([$offcanvasClose, $title, $offcanvasContent]);
-
-    // Handle opening or updating tray with content.
-    var existingTray = false;
-    if (Drupal.offCanvas.visible) {
-      // Remove previous content then append new content.
-      $pageWrapper.find('#offcanvas').remove();
-      existingTray = true;
-    }
-    $pageWrapper.addClass('js-tray-open');
-    Drupal.offCanvas.visible = true;
-    $pageWrapper.append($offcanvasWrapper);
-    if (existingTray) {
-      Drupal.announce(Drupal.t('Configuration tray content has been updated.'));
+
+    $element
+      .dialog('option', adjustedOptions)
+      .trigger('dialogContentResize.outsidein');
+  }
+
+  function handleDialogResize(event) {
+    var $element = event.data.$element;
+    var $widget = $element.dialog('widget');
+
+    var $offsets = $widget.find('> :not(#drupal-offcanvas, .ui-resizable-handle)');
+    var offset = 0;
+    var modalHeight;
+
+    // Let scroll element take all the height available.
+    $element.css({overflow: 'visible', height: 'auto'});
+    modalHeight = $widget.height();
+    $offsets.each(function () { offset += $(this).outerHeight(); });
+
+    // Take internal padding into account.
+    var scrollOffset = $element.outerHeight() - $element.height();
+    $element.height(modalHeight - offset - scrollOffset);
+  }
+
+  function bodyPadding(event) {
+    var $element = event.data.$element;
+    var $widget = $element.dialog('widget');
+    var $body = $('body');
+
+    var width = $widget.outerWidth();
+    var bodyPadding = $body.css('padding-right');
+    if (width !== bodyPadding) {
+      $body.css('padding-right', width + 'px');
+      $widget.attr('data-offset-right', width);
+      displace();
     }
-    else {
-      Drupal.announce(Drupal.t('Configuration tray opened.'));
+  }
+
+
+  $(window).on({
+    'dialog:aftercreate': function (event, dialog, $element, settings) {
+      if ($element.is('#drupal-offcanvas')) {
+        var eventData = {settings: settings, $element: $element};
+
+        $element
+          .on('dialogresize.outsidein', eventData, debounce(bodyPadding, 100))
+          .on('dialogContentResize.outsidein', eventData, handleDialogResize)
+          .trigger('dialogresize.outsidein');
+
+        $element.dialog('widget').attr('data-offset-right', '');
+
+        $(window)
+          .on('resize.outsidein scroll.outsidein', eventData, debounce(resetSize, 100))
+          .trigger('resize.outsidein');
+
+        //$(document).on('drupalViewportOffsetChange.outsidein', eventData, autoResize);
+      }
+    },
+    'dialog:beforecreate': function (event, dialog, $element, settings) {
+      if ($element.is('#drupal-offcanvas')) {
+        settings.position = {
+          my: 'left top',
+          at: 'right top',
+          of: window
+        };
+      }
+    },
+    'dialog:beforeclose': function (event, dialog, $element) {
+      $(document).off('.outsidein');
+      $(window).off('.outsidein');
+      $('body').css('padding-right', 0);
     }
-    Drupal.attachBehaviors(document.querySelector('#offcanvas'), drupalSettings);
-  };
+  });
 
-})(jQuery, Drupal);
+})(jQuery, Drupal, Drupal.debounce, Drupal.displace);
diff --git a/core/modules/outside_in/js/outside_in.js b/core/modules/outside_in/js/outside_in.js
index f67fa9d..995b54b 100644
--- a/core/modules/outside_in/js/outside_in.js
+++ b/core/modules/outside_in/js/outside_in.js
@@ -3,7 +3,7 @@
  * Drupal's Outside-In library.
  */
 
-(function ($, Drupal) {
+(function ($, window, Drupal) {
 
   'use strict';
 
@@ -26,10 +26,10 @@
       if (!localStorage.getItem('Drupal.contextualToolbar.isViewing')) {
         return;
       }
-      var editLink = $(e.target).find('li.outside-inblock-configure a')[0];
+      var editLink = $(e.target).find('a[data-dialog-renderer="offcanvas"]')[0];
       if (!editLink) {
         var closest = $(e.target).closest('.outside-in-editable');
-        editLink = closest.find('li.outside-inblock-configure a')[0];
+        editLink = closest.find('li a[data-dialog-renderer="offcanvas"]')[0];
       }
       editLink.click();
     });
@@ -63,6 +63,7 @@
       }
       element_settings.dialogType = $(this).data('dialog-type');
       element_settings.dialog = $(this).data('dialog-options');
+      element_settings.dialogRenderer = $(this).data('dialog-renderer');
       element_settings.base = $(this).attr('id');
       element_settings.element = this;
       Drupal.ajax(element_settings);
@@ -85,7 +86,7 @@
    *   Items that should be toggled.
    */
   var getItemsToToggle = function () {
-    return $('#main-canvas, #toolbar-bar, .outside-in-editable a, .outside-in-editable button')
+    return $('#page-wrapper, #toolbar-bar, .outside-in-editable a, .outside-in-editable button')
       .not('div.contextual a, div.contextual button');
   };
 
@@ -143,5 +144,4 @@
       });
     }
   };
-
-})(jQuery, Drupal);
+})(jQuery, window, Drupal);
diff --git a/core/modules/outside_in/outside_in.module b/core/modules/outside_in/outside_in.module
index 2822e24..3ff6b4e 100644
--- a/core/modules/outside_in/outside_in.module
+++ b/core/modules/outside_in/outside_in.module
@@ -32,7 +32,8 @@ function outside_in_contextual_links_view_alter(&$element, $items) {
   if (isset($element['#links']['outside-inblock-configure'])) {
     $element['#links']['outside-inblock-configure']['attributes'] = [
       'class' => ['use-ajax'],
-      'data-dialog-type' => 'offcanvas',
+      'data-dialog-type' => 'dialog',
+      'data-dialog-renderer' => 'offcanvas',
     ];
 
     $element['#attached']['library'][] = 'outside_in/drupal.off_canvas';
@@ -52,26 +53,6 @@ function outside_in_block_view_alter(array &$build) {
 }
 
 /**
- * Implements hook_element_info_alter().
- */
-function outside_in_element_info_alter(&$type) {
-  if (isset($type['page'])) {
-    $type['page']['#theme_wrappers']['outside_in_page_wrapper'] = ['#weight' => -1000];
-  }
-}
-
-/**
- * Implements hook_theme().
- */
-function outside_in_theme() {
-  return [
-    'outside_in_page_wrapper' => [
-      'variables' => ['children' => NULL],
-    ],
-  ];
-}
-
-/**
  * Implements hook_entity_type_build().
  */
 function outside_in_entity_type_build(array &$entity_types) {
diff --git a/core/modules/outside_in/outside_in.services.yml b/core/modules/outside_in/outside_in.services.yml
index 9ac920a..48f5824 100644
--- a/core/modules/outside_in/outside_in.services.yml
+++ b/core/modules/outside_in/outside_in.services.yml
@@ -3,7 +3,7 @@ services:
     class: Drupal\outside_in\Render\MainContent\OffCanvasRender
     arguments: ['@title_resolver', '@renderer']
     tags:
-      - { name: render.main_content_renderer, format: drupal_offcanvas }
+      - { name: render.main_content_renderer, format: drupal_dialog_offcanvas }
 
   outside_in.manager:
     class: Drupal\outside_in\OutsideInManager
diff --git a/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php b/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php
index 7a49505..73354ed 100644
--- a/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php
+++ b/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php
@@ -31,18 +31,21 @@ class OpenOffCanvasDialogCommand extends OpenDialogCommand {
    *   populated automatically from the current request.
    */
   public function __construct($title, $content, array $dialog_options = [], $settings = NULL) {
-    $dialog_options['modal'] = FALSE;
     parent::__construct('#drupal-offcanvas', $title, $content, $dialog_options, $settings);
+    $this->dialogOptions['modal'] = FALSE;
+    $this->dialogOptions['autoResize'] = FALSE;
+    $this->dialogOptions['resizable'] = 'w';
+    $this->dialogOptions['draggable'] = FALSE;
+    $this->dialogOptions['drupalAutoButtons'] = FALSE;
   }
 
   /**
    * {@inheritdoc}
    */
   public function render() {
-    $this->dialogOptions['modal'] = FALSE;
     return [
-      'command' => 'openOffCanvas',
-      'selector' => $this->selector,
+      'command' => 'openDialog',
+      'selector' => '#drupal-offcanvas',
       'settings' => $this->settings,
       'data' => $this->getRenderedContent(),
       'dialogOptions' => $this->dialogOptions,
diff --git a/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php b/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php
index 2d360f9..42c0ecf 100644
--- a/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php
+++ b/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php
@@ -33,18 +33,23 @@ public function testDialog() {
     $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable);
 
     $offcanvas_expected_response = [
-      'command' => 'openOffCanvas',
+      'command' => 'openDialog',
       'selector' => '#drupal-offcanvas',
       'settings' => NULL,
       'data' => $dialog_contents,
-      'dialogOptions' => [
-        'modal' => FALSE,
-        'title' => 'AJAX Dialog contents',
-      ],
+      'dialogOptions' =>
+        [
+          'title' => 'AJAX Dialog contents',
+          'modal' => FALSE,
+          'autoResize' => FALSE,
+          'resizable' => 'w',
+          'draggable' => FALSE,
+          'drupalAutoButtons' => FALSE,
+        ],
     ];
 
     // Emulate going to the JS version of the page and check the JSON response.
-    $ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_offcanvas']]);
+    $ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog_offcanvas']]);
     $this->assertEqual($offcanvas_expected_response, $ajax_result[3], 'Off-canvas dialog JSON response matches.');
   }
 
diff --git a/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig b/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig
deleted file mode 100644
index 76ff5ce..0000000
--- a/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig
+++ /dev/null
@@ -1,22 +0,0 @@
-{#
-/**
- * @file
- * Default theme implementation for a page wrapper.
- *
- * For consistent wrapping to {{ page }} render in all themes.
- *
- * Available variables:
- * - children: Contains the child elements of the page.
- *
- * @ingroup themeable
- */
-#}
-{% if children %}
-  {% spaceless %}
-    <div id="main-canvas-wrapper">
-      <div id="main-canvas">
-        {{ children }}
-      </div>
-    </div>
-  {% endspaceless %}
-{% endif %}
diff --git a/core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php b/core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php
index 6295f55..8a2f115 100644
--- a/core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php
+++ b/core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php
@@ -49,7 +49,8 @@ public function linksDisplay() {
         '#url' => Url::fromRoute('offcanvas_test.thing1'),
         '#attributes' => [
           'class' => ['use-ajax'],
-          'data-dialog-type' => 'offcanvas',
+          'data-dialog-type' => 'dialog',
+          'data-dialog-renderer' => 'offcanvas'
         ],
         '#attached' => [
           'library' => [
@@ -63,7 +64,8 @@ public function linksDisplay() {
         '#url' => Url::fromRoute('offcanvas_test.thing2'),
         '#attributes' => [
           'class' => ['use-ajax'],
-          'data-dialog-type' => 'offcanvas',
+          'data-dialog-type' => 'dialog',
+          'data-dialog-renderer' => 'offcanvas'
         ],
         '#attached' => [
           'library' => [
diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php
index 32ccc55..7ca575d 100644
--- a/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php
+++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php
@@ -28,7 +28,7 @@ public function testOffCanvasLinks() {
       $web_assert = $this->assertSession();
 
       // Make sure off-canvas tray is on page when first loaded.
-      $web_assert->elementNotExists('css', '#offcanvas');
+      $web_assert->elementNotExists('css', '#drupal-offcanvas');
 
       // Check opening and closing with two separate links.
       // Make sure tray updates to new content.
@@ -38,18 +38,18 @@ public function testOffCanvasLinks() {
         $this->waitForOffCanvasToOpen();
 
         // Check that the canvas is not on the page.
-        $web_assert->elementExists('css', '#offcanvas');
+        $web_assert->elementExists('css', '#drupal-offcanvas');
         // Check that response text is on page.
         $web_assert->pageTextContains("Thing $link_index says hello");
         $offcanvas_tray = $this->getTray();
 
         // Check that tray is visible.
         $this->assertEquals(TRUE, $offcanvas_tray->isVisible());
-        $header_text = $offcanvas_tray->findById('offcanvas-header')->getText();
+        $header_text = $offcanvas_tray->find('css', '.ui-dialog-title')->getText();
 
         // Check that header is correct.
         $this->assertEquals("Thing $link_index", $header_text);
-        $tray_text = $offcanvas_tray->find('css', '.offcanvas-content')->getText();
+        $tray_text = $offcanvas_tray->findById('drupal-offcanvas')->getText();
         $this->assertEquals("Thing $link_index says hello", $tray_text);
       }
     }
diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php
index 5871aef..bc9ff9a 100644
--- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php
+++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php
@@ -27,14 +27,14 @@ public function enableTheme($theme) {
    * Waits for Off-canvas tray to open.
    */
   protected function waitForOffCanvasToOpen() {
-    $this->waitForElement('#offcanvas');
+    $this->waitForElement('#drupal-offcanvas');
   }
 
   /**
    * Waits for Off-canvas tray to close.
    */
   protected function waitForOffCanvasToClose() {
-    $condition = "(jQuery('#offcanvas').length == 0)";
+    $condition = "(jQuery('#drupal-offcanvas').length == 0)";
     $this->assertJsCondition($condition);
   }
 
@@ -57,7 +57,9 @@ protected function waitForElement($selector, $timeout = 1000) {
    * @return \Behat\Mink\Element\NodeElement|null
    */
   protected function getTray() {
-    return $this->getSession()->getPage()->findById('offcanvas');
+    $tray = $this->getSession()->getPage()->find('css', '.ui-dialog[aria-describedby="drupal-offcanvas"]');
+    $this->assertEquals(FALSE, empty($tray), 'The tray was found.');
+    return $tray;
   }
 
 }
