diff --git a/claro.info.yml b/claro.info.yml
index 7cfd751..f86f02b 100644
--- a/claro.info.yml
+++ b/claro.info.yml
@@ -44,6 +44,8 @@ libraries-override:
     css:
       component:
         /core/themes/stable/css/core/vertical-tabs.css: false
+    js:
+      misc/vertical-tabs.js: js/claro.vertical-tabs.js
 
   core/jquery.ui:
     css:
@@ -118,10 +120,10 @@ libraries-extend:
     - claro/details-focus
   core/drupal.dropbutton:
     - claro/drupal-theme
-  core/drupal.vertical-tabs:
-    - claro/vertical-tabs
   core/drupal.tableselect:
     - claro/drupal.tableselect
+  core/drupal.vertical-tabs:
+    - claro/vertical-tabs
   core/jquery.ui:
     - claro/claro.jquery.ui
   media_library/view:
diff --git a/claro.libraries.yml b/claro.libraries.yml
index c106d4b..fedaf70 100644
--- a/claro.libraries.yml
+++ b/claro.libraries.yml
@@ -103,12 +103,6 @@ drupal.responsive-detail:
     - core/jquery.once
     - core/collapse
 
-vertical-tabs:
-  version: VERSION
-  css:
-    component:
-      css/dist/components/vertical-tabs.css: {}
-
 claro.jquery.ui:
   version: VERSION
   css:
@@ -222,3 +216,23 @@ views:
   css:
     component:
       css/dist/components/views-exposed-form.css: {}
+
+vertical-tabs:
+  css:
+    component:
+      css/dist/components/vertical-tabs.css: {}
+  drupalSettings:
+    verticalTabs:
+      paneClasses: []
+      paneClassesFirst:
+        - vertical-tabs__item--first
+      paneClassesLast:
+        - vertical-tabs__item--last
+      paneClassesHidden:
+        - vertical-tab--hidden
+      paneWrapperClasses:
+        - vertical-tabs__items--processed
+      menuItemClassesHidden:
+        - vertical-tabs__menu-item--hidden
+  dependencies:
+    - claro/global-styling
diff --git a/claro.theme b/claro.theme
index 1b1f0e4..80ca173 100644
--- a/claro.theme
+++ b/claro.theme
@@ -24,6 +24,15 @@ function claro_theme_suggestions_form_element_alter(&$suggestions, $variables) {
   }
 }
 
+/**
+ * Implements hook_theme_suggestions_HOOK_alter() for details.
+ */
+function claro_theme_suggestions_details_alter(&$suggestions, $variables) {
+  if (!empty($variables['element']['#vertical_tab_item'])) {
+    $suggestions[] = 'details__vertical_tabs';
+  }
+}
+
 /**
  * Implements hook_preprocess_HOOK() for HTML document templates.
  */
@@ -257,6 +266,62 @@ function claro_element_info_alter(&$type) {
   if (isset($type['dropbutton'])) {
     $type['dropbutton']['#pre_render'][] = '_claro_dropbutton_prerender';
   }
+
+  if (isset($type['vertical_tabs'])) {
+    $vertical_tabs_pre_renders = !empty($type['vertical_tabs']['#pre_render']) ? $type['vertical_tabs']['#pre_render'] : [];
+    array_unshift($vertical_tabs_pre_renders, '_claro_vertical_tabs_prerender');
+
+    $type['vertical_tabs']['#pre_render'] = $vertical_tabs_pre_renders;
+  }
+}
+
+/**
+ * Prerender callback for Vertical Tabs element
+ */
+function _claro_vertical_tabs_prerender($element) {
+  // If the vertical tabs have a details group, add attributes to those details
+  // elements so they are styled as accordion items and have BEM classes.
+  if (
+    isset($element['group']['#type']) &&
+    $element['group']['#type'] === 'details' &&
+    isset($element['group']['#groups']) &&
+    is_array($element['group']['#groups'])
+  ) {
+    $group_keys = Element::children($element['group']['#groups'], TRUE);
+    $first_key = TRUE;
+    $last_group_with_child_key = NULL;
+    $last_group_with_child_key_last_child_key = NULL;
+
+    foreach($group_keys as $group_key) {
+      $children_keys = Element::children($element['group']['#groups'][$group_key], TRUE);
+
+      foreach ($children_keys as $child_key) {
+        $last_group_with_child_key = $group_key;
+        $type = isset($element['group']['#groups'][$group_key][$child_key]['#type']) ? $element['group']['#groups'][$group_key][$child_key]['#type'] : FALSE;
+        if ($type === 'details') {
+          // Add BEM class to specify the details element is in a vertical
+          // tabs group.
+          $element['group']['#groups'][$group_key][$child_key]['#attributes']['class'][] = 'vertical-tabs__item';
+          $element['group']['#groups'][$group_key][$child_key]['#vertical_tab_item'] = TRUE;
+
+          if ($first_key) {
+          $element['group']['#groups'][$group_key][$child_key]['#attributes']['class'][] = 'vertical-tabs__item--first';
+            $first_key = FALSE;
+          }
+
+          $last_group_with_child_key_last_child_key = $child_key;
+        }
+      }
+    }
+  }
+
+  if ($last_group_with_child_key && $last_group_with_child_key_last_child_key) {
+    $element['group']['#groups'][$last_group_with_child_key][$last_group_with_child_key_last_child_key]['#attributes']['class'][] = 'vertical-tabs__item--last';
+  }
+
+  $element['#attributes']['class'][] = 'vertical-tabs__items';
+
+  return $element;
 }
 
 /**
diff --git a/css/src/base/variables.css b/css/src/base/variables.css
index f1c7206..36014e9 100644
--- a/css/src/base/variables.css
+++ b/css/src/base/variables.css
@@ -10,8 +10,8 @@
   --color-whitesmoke-light: #fafbfd;
   --color-whitesmoke-o-40: rgba(243, 244, 249, 0.4);
   /* Secondary. */
-  --color-lightgray: #d8d9e0;
-  --color-lightgray-o-80: rgba(216, 217, 224, 0.8);
+  --color-lightgray: #d4d4d8;
+  --color-lightgray-o-80: rgba(212, 212, 218, 0.8);
   --color-grayblue: #8e929c;
   --color-oldsilver: #82828c;
   --color-davysgrey: #545560;
diff --git a/css/src/components/details.css b/css/src/components/details.css
index 66bdfa8..da93603 100644
--- a/css/src/components/details.css
+++ b/css/src/components/details.css
@@ -9,13 +9,10 @@
  * Available modifiers are:
  *  - .claro-details--accordion
  *  - .claro-details--accordion-item
+ *  - .claro-details--vertical-tabs-item
  *
- * 'Accordion item' is used for the details of the node edit sidebar. For creating
- * accordion item list from a set of details, set the surrounding Container
- * render element's '#accordion' key to TRUE.
- *
- * The other variant is 'accordion'. Despite the fact that it isn't used
- * anywhere right now, we implemented it (since the design defines that).
+ * Despite the fact that 'accordion' isn't used anywhere right now, we
+ * implemented it (since the design defines that).
  * This variant can be used by setting the '#accordion' to TRUE for a
  * Details render element:
  * @code
@@ -23,11 +20,20 @@
  *   '#type' => 'details',
  *   '#accordion' => TRUE,
  * ];
+ *
+ * 'Accordion item' is used for the details of the node edit sidebar. For
+ * creating accordion item list from a set of details, set the surrounding
+ * Container render element's '#accordion' key to TRUE.
+ *
+ * 'Vertical tabs item' is used for the children of the VerticalTabs render
+ * element.
  */
 
 :root {
   --size-summary-border-radius: calc(var(--details-border-size-radius) - var(--details-border-size));
   --size-summary-focus-border: 3px;
+  --summary-accordion-padding-vertical: calc(var(--space-l) + ((var(--space-m) - var(--space-l)) / 2));
+  --summary-accordion-line-height: var(--space-l);
 }
 
 .claro-details {
@@ -41,7 +47,8 @@
   box-shadow: var(--details-box-shadow);
 }
 
-.claro-details--accordion-item {
+.claro-details--accordion-item,
+.claro-details--vertical-tabs-item {
   margin-top: 0;
   margin-bottom: 0;
   border-radius: 0;
@@ -82,12 +89,15 @@
 
 /* Modifiers */
 .claro-details__summary--accordion,
-.claro-details__summary--accordion-item {
-  padding: var(--space-l) var(--space-l) var(--space-l) var(--details-desktop-wrapper-padding-start); /* LTR */
+.claro-details__summary--accordion-item,
+.claro-details__summary--vertical-tabs-item {
+  padding: var(--summary-accordion-padding-vertical) var(--space-l) var(--summary-accordion-padding-vertical) var(--details-desktop-wrapper-padding-start); /* LTR */
+  line-height: var(--summary-accordion-line-height);
   background: var(--color-white);
 }
 [dir="rtl"] .claro-details__summary--accordion,
-[dir="rtl"] .claro-details__summary--accordion-item {
+[dir="rtl"] .claro-details__summary--accordion-item,
+[dir="rtl"] .claro-details__summary--vertical-tabs-item {
   padding-right: var(--details-desktop-wrapper-padding-start);
   padding-left: var(--space-l);
 }
@@ -163,7 +173,7 @@
 }
 
 /**
- * Safari (at least version 12.1) cannot handle our details marker
+ * [1] Safari (at least version 12.1) cannot handle our details marker
  * transition properly.
  *
  * Every additional pointer triggered toggle event freezes the transition,
@@ -204,16 +214,21 @@
   pointer-events: none;
 }
 
-.claro-details > .claro-details__summary--accordion-item::after {
+.claro-details > .claro-details__summary--accordion-item::after,
+.vertical-tabs__item > .claro-details__summary--vertical-tabs-item::after {
   border-radius: 0;
 }
 
-.claro-details:first-child > .claro-details__summary--accordion-item::after {
-  border-radius: var(--details-border-size-radius) var(--details-border-size-radius) 0 0;
+.claro-details:first-child > .claro-details__summary--accordion-item::after,
+.vertical-tabs__item--first > .claro-details__summary--vertical-tabs-item::after {
+  border-top-right-radius: var(--details-border-size-radius);
+  border-top-left-radius: var(--details-border-size-radius);
 }
 
-.claro-details:last-child > .claro-details__summary--accordion-item::after {
-  border-radius: 0 0 var(--details-border-size-radius) var(--details-border-size-radius);
+.claro-details:last-child > .claro-details__summary--accordion-item::after,
+.vertical-tabs__item--last > .claro-details__summary--vertical-tabs-item::after {
+  border-bottom-right-radius: var(--details-border-size-radius);
+  border-bottom-left-radius: var(--details-border-size-radius);
 }
 
 /**
@@ -221,7 +236,8 @@
  * radius if their accordion is expanded.
  */
 .claro-details[open] > .claro-details__summary--accordion::after,
-.claro-details[open] > .claro-details__summary--accordion-item::after {
+.claro-details[open] > .claro-details__summary--accordion-item::after,
+.vertical-tabs__item--last[open] > .claro-details__summary--vertical-tabs-item::after {
   border-bottom-left-radius: 0;
   border-bottom-right-radius: 0;
 }
@@ -234,7 +250,8 @@
 }
 
 [open] .claro-details__summary--accordion,
-[open] .claro-details__summary--accordion-item {
+[open] .claro-details__summary--accordion-item,
+[open] .claro-details__summary--vertical-tabs-item {
   color: var(--color-absolutezero);
 }
 
@@ -242,7 +259,8 @@
 .claro-details__summary:hover:focus::before,
 .claro-details[open] > .claro-details__summary:focus::before,
 .claro-details[open] > .claro-details__summary--accordion::before,
-.claro-details[open] > .claro-details__summary--accordion-item::before {
+.claro-details[open] > .claro-details__summary--accordion-item::before,
+.claro-details[open] > .claro-details__summary--vertical-tabs-item::before {
   background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath d='M5.2109375,1.3144531 3.7890625,2.7226562 9.0917969,8.0761719 3.7890625,13.429688 5.2109375,14.837891 11.908203,8.0761719Z' fill='%230036B1'/%3E%3C/svg%3E");
 }
 
@@ -270,7 +288,8 @@
 }
 
 .claro-details[open] > .claro-details__summary--accordion,
-.claro-details[open] > .claro-details__summary--accordion-item {
+.claro-details[open] > .claro-details__summary--accordion-item,
+.claro-details[open] > .claro-details__summary--vertical-tabs-item {
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
 
@@ -287,11 +306,12 @@
  * Active has to be here for Firefox.
  * Merges standard collapse-processed selectors.
  */
-
 [open] > .claro-details__summary--accordion:not(:focus):not(:active)::after,
 [open] > .claro-details__summary--accordion-item:not(:focus):not(:active)::after,
 .collapse-processed[open] > .claro-details__summary--accordion .details-title:not(:focus)::after,
-.collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after {
+.collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after,
+[open] > .claro-details__summary--vertical-tabs-item:not(:focus):not(:active)::after,
+.collapse-processed[open] > .claro-details__summary--vertical-tabs-item .details-title:not(:focus)::after {
   box-shadow: none;
   border: 3px solid var(--color-absolutezero);
   border-width: 0 0 0 3px; /* LTR */
@@ -300,7 +320,9 @@
 [dir="rtl"] [open] > .claro-details__summary--accordion:not(:focus)::after,
 [dir="rtl"] [open] > .claro-details__summary--accordion-item:not(:focus)::after,
 [dir="rtl"] .collapse-processed[open] > .claro-details__summary--accordion .details-title:not(:focus)::after,
-[dir="rtl"] .collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after {
+[dir="rtl"] .collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after,
+[dir="rtl"] [open] > .claro-details__summary--vertical-tabs-item:not(:focus)::after,
+[dir="rtl"] .collapse-processed[open] > .claro-details__summary--vertical-tabs-item .details-title:not(:focus)::after {
   border-width: 0 3px 0 0;
 }
 
@@ -316,8 +338,7 @@
 /* stylelint-disable-next-line unit-whitelist */
 @media not all and (min-resolution: 0.001dpcm) {
   @media {
-    .claro-details__summary:focus::after,
-    .claro-details__summary:active::after {
+    .claro-details__summary::after {
       transition: none;
     }
   }
@@ -346,13 +367,16 @@
 }
 
 .claro-details__wrapper--accordion,
-.claro-details__wrapper--accordion-item {
+.claro-details__wrapper--accordion-item,
+.claro-details__wrapper--vertical-tabs-item {
   margin: 0;
 }
 .claro-details__wrapper--accordion::before,
 .claro-details__wrapper--accordion::after,
 .claro-details__wrapper--accordion-item::before,
-.claro-details__wrapper--accordion-item::after {
+.claro-details__wrapper--accordion-item::after,
+.claro-details__wrapper--vertical-tabs-item::before,
+.claro-details__wrapper--vertical-tabs-item::after {
   display: table;
   clear: both;
   content: "";
@@ -364,18 +388,21 @@
   }
 
   .claro-details__wrapper--accordion,
-  .claro-details__wrapper--accordion-item {
+  .claro-details__wrapper--accordion-item,
+  .claro-details__wrapper--vertical-tabs-item {
     margin: 0;
   }
 }
 
 .claro-details__content--accordion,
-.claro-details__content--accordion-item {
+.claro-details__content--accordion-item,
+.claro-details__content--vertical-tabs-item {
   margin: var(--space-m) var(--space-m) var(--space-l);
 }
 
 .claro-details__wrapper--accordion,
-.claro-details__wrapper--accordion-item {
+.claro-details__wrapper--accordion-item,
+.claro-details__wrapper--vertical-tabs-item {
   background-color: var(--color-whitesmoke-o-40);
   border-top: var(--details-border-size) solid var(--details-border-color);
 }
@@ -404,11 +431,13 @@
 }
 
 .collapse-processed > .claro-details__summary--accordion .details-title,
-.collapse-processed > .claro-details__summary--accordion-item .details-title {
-  padding: var(--space-l) var(--space-l) var(--space-l) var(--details-desktop-wrapper-padding-start); /* LTR */
+.collapse-processed > .claro-details__summary--accordion-item .details-title,
+.collapse-processed > .claro-details__summary--vertical-tabs-item .details-title {
+  padding: var(--summary-accordion-padding-vertical) var(--space-l) var(--summary-accordion-padding-vertical) var(--details-desktop-wrapper-padding-start); /* LTR */
 }
 [dir="rtl"] .collapse-processed > .claro-details__summary--accordion .details-title,
-[dir="rtl"] .collapse-processed > .claro-details__summary--accordion-item .details-title {
+[dir="rtl"] .collapse-processed > .claro-details__summary--accordion-item .details-title,
+[dir="rtl"] .collapse-processed > .claro-details__summary--vertical-tabs-item .details-title {
   padding-right: var(--details-desktop-wrapper-padding-start);
   padding-left: var(--space-l);
 }
@@ -442,22 +471,26 @@
 
 /* Accordion item modifiers for the focus box. */
 
-.collapse-processed > .claro-details__summary--accordion-item .details-title::after {
+.collapse-processed > .claro-details__summary--accordion-item .details-title::after,
+.vertical-tabs__item > .claro-details__summary--vertical-tabs-item .details-title::after {
   border-radius: 0;
 }
 
-.collapse-processed:first-child > .claro-details__summary--accordion-item .details-title::after {
+.collapse-processed:first-child > .claro-details__summary--accordion-item .details-title::after,
+.vertical-tabs__item--first > .claro-details__summary--vertical-tabs-item .details-title::after {
   border-top-right-radius: var(--details-border-size-radius);
   border-top-left-radius: var(--details-border-size-radius);
 }
 
-.collapse-processed:last-child > .claro-details__summary--accordion-item .details-title::after {
+.collapse-processed:last-child > .claro-details__summary--accordion-item .details-title::after,
+.vertical-tabs__item--last > .claro-details__summary--vertical-tabs-item .details-title::after {
   border-bottom-right-radius: var(--details-border-size-radius);
   border-bottom-left-radius: var(--details-border-size-radius);
 }
 
 .collapse-processed[open] > .claro-details__summary--accordion .details-title::after,
-.collapse-processed[open] > .claro-details__summary--accordion-item .details-title::after {
+.collapse-processed[open] > .claro-details__summary--accordion-item .details-title::after,
+.vertical-tabs__item[open] > .claro-details__summary--vertical-tabs-item .details-title::after {
   border-bottom-right-radius: 0;
   border-bottom-left-radius: 0;
 }
@@ -470,13 +503,15 @@
  * been solved.
  */
 .claro-details__summary--accordion .summary,
-.claro-details__summary--accordion-item .summary {
+.claro-details__summary--accordion-item .summary,
+.claro-details__summary--vertical-tabs-item .summary {
   display: none;
 }
 
 @media screen and (-ms-high-contrast: active) {
   .collapse-processed[open] > .claro-details__summary--accordion .details-title:not(:focus)::after,
-  .collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after {
+  .collapse-processed[open] > .claro-details__summary--accordion-item .details-title:not(:focus)::after,
+  .collapse-processed[open] > .claro-details__summary--vertical-tabs-item .details-title:not(:focus)::after {
     top: -1px;
     right: -1px;
     bottom: -1px;
diff --git a/css/src/components/form--checkbox-radio--ie.css b/css/src/components/form--checkbox-radio--ie.css
index 0efb739..2532528 100644
--- a/css/src/components/form--checkbox-radio--ie.css
+++ b/css/src/components/form--checkbox-radio--ie.css
@@ -9,7 +9,7 @@
   width: 18px;
   height: 18px;
   background: var(--input-bg-color) no-repeat 50% 50%;
-  background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10'xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E");
+  background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E");
   background-size: 100% 100%;
   border-radius: 2px;
   box-shadow: 0 0 0 4px transparent;
diff --git a/css/src/components/form--checkbox-radio.css b/css/src/components/form--checkbox-radio.css
index e6555a7..599f989 100644
--- a/css/src/components/form--checkbox-radio.css
+++ b/css/src/components/form--checkbox-radio.css
@@ -65,7 +65,7 @@
   width: 18px;
   height: 18px;
   background: var(--input-bg-color) no-repeat 50% 50%;
-  background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10'xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E");
+  background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' viewBox='0 0 12 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.18182 6.96572L1.97655 4.64855L1.79545 4.45826L1.61436 4.64855L0.818904 5.48437L0.654878 5.65672L0.818904 5.82907L4.00072 9.17235L4.18182 9.36263L4.36291 9.17235L11.1811 2.00817L11.3451 1.83582L11.1811 1.66347L10.3856 .827651L10.2045 .637365L10.0234 .82765L4.18182 6.96572Z' fill='white' /%3E%3C/svg%3E");
   background-size: 100% 100%;
   border-radius: 2px;
   box-shadow: 0 0 0 4px transparent;
diff --git a/css/src/components/vertical-tabs.css b/css/src/components/vertical-tabs.css
index 221f503..8a98a4c 100644
--- a/css/src/components/vertical-tabs.css
+++ b/css/src/components/vertical-tabs.css
@@ -3,124 +3,341 @@
  * Override of misc/vertical-tabs.css.
  */
 
-.vertical-tabs {
-  position: relative;
-  overflow: hidden;
-  margin: 10px 0;
-  border: 1px solid #bdbdbd;
-  border-radius: 4px;
-  background: #e6e5e1;
+:root {
+  --vtabs-trigger-border: 1px solid var(--color-lightgray);
+  --vtabs-invisible-border: 1px solid transparent;
+  --shadow-trigger-active-vertical-tab: 0 2px 4px rgba(0, 0, 0, 0.1);
+  --vtabs-max-width: 20em;
+}
+
+.vertical-tabs__items {
+  display: flex;
+  margin: var(--space-s) 0;
+  flex-direction: column;
+  background-color: var(--color-white);
+  color: var(--color-text);
+  border: var(--details-border-size) solid var(--details-border-color);
+  border-radius: var(--details-accordion-border-size-radius);
+  box-shadow: var(--details-box-shadow);
+}
+
+/**
+ * Styles for .vertical-tabs are needed only from medium and wide breakpoints.
+ */
+@media screen and (min-width: 38em) {
+  .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs,
+  body:not(.toolbar-tray-open) .vertical-tabs {
+    display: flex;
+    align-items: stretch;
+    flex-direction: row;
+  }
+}
+
+@media screen and (min-width: 60em) {
+  .vertical-tabs {
+    display: flex;
+    align-items: stretch;
+    flex-direction: row;
+  }
+}
+
+.vertical-tabs__item {
+  margin: -1px -1px 0;
+  border-radius: 0;
 }
 
+.vertical-tabs__item--first {
+  border-top-right-radius: var(--details-accordion-border-size-radius);
+  border-top-left-radius: var(--details-accordion-border-size-radius);
+}
+
+@media screen and (min-width: 38em) {
+  .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__item,
+  .js body:not(.toolbar-tray-open) .vertical-tabs__item {
+    margin-top: 0;
+  }
+}
+
+@media screen and (min-width: 60em) {
+  .js .vertical-tabs__item {
+    margin-top: 0;
+  }
+}
+
+.vertical-tabs__item--last {
+  margin-bottom: -1px;
+  border-bottom-right-radius: var(--details-accordion-border-size-radius);
+  border-bottom-left-radius: var(--details-accordion-border-size-radius);
+}
+
+/* Tab menu. */
 .vertical-tabs__menu {
-  float: left; /* LTR */
-  width: 240px;
-  margin: 0 -100% -1px 0; /* LTR */
-  padding: 0;
-  border-bottom: 1px solid #ccc;
+  position: relative;
+  display: none;
+  flex: 0 0 40%;
+  margin: 0;
+  max-width: 20rem;
+  padding-top: 0.5rem;
+  border-top: 1px solid transparent;
   line-height: 1;
+  list-style: none;
+  color: var(--color-text);
+  background: var(--color-white);
 }
 [dir="rtl"] .vertical-tabs__menu {
-  float: right;
-  margin: 0 0 -1px -100%;
+  margin: 0;
 }
-.vertical-tabs__menu-item {
-  position: relative;
+
+@media screen and (min-width: 38em) {
+  .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__menu,
+  body:not(.toolbar-tray-open) .vertical-tabs__menu {
+    display: block;
+  }
 }
-.vertical-tabs__menu-item.is-selected {
-  z-index: 1;
-  overflow-x: hidden;
-  width: 100%;
-  border-right: 1px solid #fcfcfa; /* LTR */
-  box-shadow: 0 5px 5px -5px hsla(0, 0%, 0%, 0.3);
-  border-bottom: 1px solid #b3b2ad;
+
+@media screen and (min-width: 60em) {
+  .vertical-tabs__menu {
+    display: block;
+  }
 }
-.vertical-tabs__menu-item.last {
-  border-bottom: none;
+
+/* Tab menu item. */
+.vertical-tabs__menu-item {
+  margin: -1rem -1px -0.5rem -0.5rem; /* LTR */
+  padding: 0.5rem 0 0.5rem 0.5rem; /* LTR */
+  overflow: hidden;
 }
-[dir="rtl"] .vertical-tabs__menu-item.is-selected {
-  border-left: 1px solid #fcfcfa;
-  border-right: none;
+[dir="rtl"] .vertical-tabs__menu-item {
+  margin-right: -0.5rem;
+  margin-left: -1px;
+  padding-right: 0.5rem;
+  padding-left: 0;
 }
-.vertical-tabs__menu-item:focus,
-.vertical-tabs__menu-item:active {
+
+.vertical-tabs__menu-item::after {
+  display: block;
+  position: absolute;
+  width: 100%;
+  border-top: 1px solid var(--color-white);
+  margin-top: -1px;
   z-index: 2;
 }
-.vertical-tabs__menu-item a {
+
+.vertical-tabs__menu-item::before {
   display: block;
-  padding: 10px 15px 15px;
-  border-bottom: 1px solid #b3b2ad;
-  background-color: #f2f2f0;
-  text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
-  text-decoration: none;
+  position: absolute;
+  width: 100%;
+  border-top: 1px solid var(--color-lightgray);
+  margin-top: -1px;
+  z-index: 1;
 }
-.vertical-tabs__menu-item:last-child a {
-  border-bottom: 0;
+
+.vertical-tabs__menu-item:not(.vertical-tabs__menu-item--hidden) ~ .vertical-tabs__menu-item::before {
+  content: '';
+}
+
+.vertical-tabs__menu-item.is-selected::before,
+.vertical-tabs__menu-item:not(.vertical-tabs__menu-item--hidden) ~ .vertical-tabs__menu-item.is-selected::before {
+  content: none;
+}
+
+/* Tab menu item selected. */
+
+.vertical-tabs__menu-item.is-selected::after {
+  content: '';
 }
-.vertical-tabs__menu-item.is-selected a,
-.vertical-tabs__menu-item a:hover,
-.vertical-tabs__menu-item a:focus {
-  background: #fcfcfa;
-  text-shadow: none;
+
+.vertical-tabs__menu-item:focus {
+  outline: 0;
+  box-shadow: none;
 }
-.vertical-tabs__menu-item a:focus {
-  outline: none;
+
+/* Tab menu item anchor. */
+.vertical-tabs__menu-link {
+  position: relative;
+  display: block;
+  padding: var(--space-s) var(--space-s) var(--space-s) calc(var(--space-l) - 4px); /* LTR */
+  line-height: var(--line-height); /* ?? */
+  text-decoration: none;
+  border: 1px solid transparent;
+  margin-top: -1px;
+  border-width: 1px 0 1px 4px; /* LTR */
+  border-radius: 2px 0 0 2px; /* LTR */
+  color: var(--color-text);
 }
-.vertical-tabs__menu-item a:focus .vertical-tabs__menu-item-title {
-  text-decoration: underline;
+[dir="rtl"] .vertical-tabs__menu-link {
+  padding-right: calc(var(--space-l) - 4px);
+  padding-left: var(--space-s);
+  border-width: 1px 4px 1px 0;
+  border-radius: 0 2px 2px 0;
 }
-.vertical-tabs__menu-item a:active .vertical-tabs__menu-item-title,
-.vertical-tabs__menu-item.is-selected a:focus .vertical-tabs__menu-item-title {
+
+.vertical-tabs__menu-link:hover {
+  color: var(--color-absolutezero);
+  background-color: var(--color-bgblue-hover);
   text-decoration: none;
 }
-.vertical-tabs__menu-item.is-selected a {
-  color: #004f80;
-  padding-left: 11px; /* LTR */
-  border-bottom: none;
+
+.vertical-tabs__menu-item-summary,
+.vertical-tabs__details-summary-summary {
+  display: block;
+  font-size: var(--font-size-s);
+  color: var(--color-davysgrey);
+  font-weight: normal;
+}
+
+.vertical-tabs__menu-link:focus {
   text-decoration: none;
+  box-shadow: none;
+  z-index: 4;
 }
-[dir=rtl] .vertical-tabs__menu-item.is-selected a {
-  padding-left: 15px;
-  padding-right: 11px;
+
+.vertical-tabs__menu-link:focus::after {
+  content: '';
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  margin: -6px -9px;
+  border: 3px solid var(--color-focus);
+  border-radius: 2px;
 }
-.vertical-tabs__menu-item.is-selected a:hover,
-.vertical-tabs__menu-item.is-selected a:focus {
-  color: #007ecc;
+
+.is-selected .vertical-tabs__menu-link {
+  color: var(--color-absolutezero);
+  background-color: var(--color-white);
+  border-color: var(--color-lightgray) transparent;
+  box-shadow: var(--shadow-trigger-active-vertical-tab);
+  z-index: 3;
 }
-[data-vertical-tabs-panes] {
-  background-color: #fcfcfa;
+[dir=rtl] .is-selected .vertical-tabs__menu-link {
+  border-radius: 0 var(--tabs-base-border) var(--base-border-radius) 0;
 }
-.vertical-tabs__panes {
-  margin: 0 0 0 240px; /* LTR */
-  padding: 10px 15px 10px 15px;
-  border-left: 1px solid #a6a5a1; /* LTR */
+
+.is-selected .vertical-tabs__menu-link:hover {
+  background-color: var(--color-bgblue-hover);
+  color: var(--color-absolutezero-hover);
 }
-[dir="rtl"] .vertical-tabs__panes {
-  margin: 0 240px 0 0;
-  border-left: none;
-  border-right: 1px solid #a6a5a1;
+
+.is-selected .vertical-tabs__menu-link::before {
+  content: '';
+  position: absolute;
+  top: -1px;
+  right: 100%; /* LTR */
+  bottom: -1px;
+  border-left: 4px solid var(--color-absolutezero); /* LTR */
+  border-radius: var(--base-border-radius) 0 0 var(--base-border-radius); /* LTR */
 }
-.vertical-tabs__panes:after {
-  content: "";
-  display: table;
-  clear: both;
+[dir=rtl] .is-selected .vertical-tabs__menu-link::before {
+  right: auto;
+  left: 100%;
+  border-left: 0;
+  border-right: 4px solid var(--color-absolutezero);
+  border-radius: 0 var(--base-border-radius) var(--base-border-radius) 0;
 }
-.vertical-tabs__pane {
-  margin: 0;
-  padding: 0;
-  border: 0;
-  background: none;
-  color: #595959;
-  box-shadow: none;
+
+@media screen and (-ms-high-contrast: active) {
+  .vertical-tabs__menu {
+    border-color: transparent;
+  }
+
+  .vertical-tabs__menu-link {
+    border-color: transparent;
+  }
+
+  .is-selected .vertical-tabs__menu-link {
+    border-color: windowText transparent;
+  }
+
+  .vertical-tabs__menu-link:focus::after {
+    border-color: transparent;
+  }
+
+  .is-selected .vertical-tabs__menu-link::before {
+    border-color: windowText;
+  }
 }
-.vertical-tabs__menu-item-summary {
-  display: block;
-  padding-top: 0.4em;
-  color: #666;
+
+/**
+ * Tab panes.
+ */
+.vertical-tabs__items--processed {
+  border: var(--vtabs-trigger-border);
+  background-color: var(--color-white);
+  box-shadow: var(--shadow-trigger-active-vertical-tab);
+  flex: 1 0 60%;
+  z-index: 1;
+  margin-top: 0;
+  margin-bottom: 0;
 }
-.vertical-tabs__pane > summary {
-  display: none;
+
+@media screen and (min-width: 38em) {
+  .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__item,
+  .js body:not(.toolbar-tray-open) .vertical-tabs__item {
+    border: 0;
+    margin: 0;
+  }
+
+  .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__item > summary,
+  .js body:not(.toolbar-tray-open) .vertical-tabs__item > summary {
+    display: none;
+  }
+
+  .js .toolbar-tray-open:not(.toolbar-vertical) .claro-details__wrapper--vertical-tabs-item,
+  .js body:not(.toolbar-tray-open) .claro-details__wrapper--vertical-tabs-item {
+    border-top: 0;
+    background-color: transparent;
+  }
+
+  .js .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__items--processed,
+  .js body:not(.toolbar-tray-open) .vertical-tabs__items--processed {
+    border-radius: 0 var(--base-border-radius) var(--base-border-radius) var(--base-border-radius); /* LTR */
+  }
+
+  .js[dir="rtl"] .toolbar-tray-open:not(.toolbar-vertical) .vertical-tabs__items--processed,
+  .js[dir="rtl"] body:not(.toolbar-tray-open) .vertical-tabs__items--processed {
+    border-radius: var(--base-border-radius) 0 var(--base-border-radius) var(--base-border-radius);
+  }
 }
-.vertical-tabs__pane > .details-wrapper {
-  margin: 0;
+
+@media screen and (min-width: 60em) {
+  .js .vertical-tabs__item {
+    border: 0;
+    margin: 0;
+  }
+
+  .js .vertical-tabs__item > summary {
+    display: none;
+  }
+
+  .js .claro-details__wrapper--vertical-tabs-item {
+    border-top: 0;
+    background-color: transparent;
+  }
+
+  .js .vertical-tabs__items--processed {
+    border-radius: 0 var(--base-border-radius) var(--base-border-radius) var(--base-border-radius); /* LTR */
+  }
+
+  .js[dir="rtl"] .vertical-tabs__items--processed {
+    border-radius: var(--base-border-radius) 0 var(--base-border-radius) var(--base-border-radius);
+  }
+}
+
+/*
+ * Set width to 100% so an input's size attribute does not cause the tabs to
+ * exceed the width of the page.
+ */
+.claro-details__content--vertical-tabs-item .form-element {
+  max-width: 100%;
+}
+
+/*
+ * Widths are set to 100% in the above rule, so single line text inputs
+ * should get a max-width that resembles the width dictated by the default
+ * size attribute.
+ */
+.claro-details__content--vertical-tabs-item .form-element--type-text {
+  max-width: 31.25rem;
 }
diff --git a/js/claro.vertical-tabs.es6.js b/js/claro.vertical-tabs.es6.js
new file mode 100644
index 0000000..ff551b0
--- /dev/null
+++ b/js/claro.vertical-tabs.es6.js
@@ -0,0 +1,410 @@
+/**
+ * @file
+ * Define vertical tabs functionality.
+ */
+
+/**
+ * Triggers when form values inside a vertical tab changes.
+ *
+ * This is used to update the summary in vertical tabs in order to know what
+ * are the important fields' values.
+ *
+ * @event summaryUpdated
+ */
+
+(($, Drupal) => {
+  /**
+   * Show the parent vertical tab pane of a targeted page fragment.
+   *
+   * In order to make sure a targeted element inside a vertical tab pane is
+   * visible on a hash change or fragment link click, show all parent panes.
+   *
+   * @param {jQuery.Event} e
+   *   The event triggered.
+   * @param {jQuery} $target
+   *   The targeted node as a jQuery object.
+   */
+  const handleFragmentLinkClickOrHashChange = (e, $target) => {
+    $target.parents('.js-vertical-tabs-pane').each((index, pane) => {
+      $(pane)
+        .data('verticalTab')
+        .focus();
+    });
+  };
+
+  /**
+   * This script transforms a set of details into a stack of vertical tabs.
+   *
+   * Each tab may have a summary which can be updated by another
+   * script. For that to work, each details element has an associated
+   * 'verticalTabCallback' (with jQuery.data() attached to the details),
+   * which is called every time the user performs an update to a form
+   * element inside the tab pane.
+   *
+   * @type {Drupal~behavior}
+   *
+   * @prop {Drupal~behaviorAttach} attach
+   *   Attaches behaviors for vertical tabs.
+   */
+  Drupal.behaviors.claroVerticalTabs = {
+    attach(context, settings) {
+      const verticalTabsDefaults = {
+        paneClasses: ['vertical-tabs__pane'],
+        paneClassesFirst: ['first'],
+        paneClassesLast: ['last'],
+        paneClassesHidden: ['vertical-tab--hidden'],
+        paneWrapperClasses: ['vertical-tabs__panes'],
+        menuItemClassesHidden: [],
+      };
+      const verticalTabsSettings = $.extend({}, verticalTabsDefaults, settings.verticalTabs || {});
+
+      /**
+       * Binds a listener to handle fragment link clicks and URL hash changes.
+       */
+      $('body')
+        .once('vertical-tabs-fragments')
+        .on(
+          'formFragmentLinkClickOrHashChange.verticalTabs',
+          handleFragmentLinkClickOrHashChange,
+        );
+
+      $(context)
+        .find('[data-vertical-tabs-panes]')
+        .once('vertical-tabs')
+        .each(function initializeVerticalTabs() {
+          const $this = $(this).addClass(verticalTabsSettings.paneWrapperClasses.join(' '));
+          const focusID = $this.find(':hidden.vertical-tabs__active-tab').val();
+          let tabFocus;
+
+          // Check if there are some details that can be converted to
+          // vertical-tabs.
+          const $details = $this.find('> details');
+          if ($details.length === 0) {
+            return;
+          }
+
+          // Create the tab column.
+          const tabList = $(Drupal.theme.verticalTabListWrapper());
+          $this
+            .wrap(Drupal.theme.verticalTabsWrapper())
+            .before(tabList);
+
+          // Transform each details into a tab.
+          $details.each(function initializeVerticalTabItems() {
+            const $that = $(this);
+            /* eslint-disable new-cap */
+            const verticalTab = new Drupal.verticalTab({
+              title: $that.find('> summary').text(),
+              details: $that,
+              settings: verticalTabsSettings,
+            });
+            /* eslint-enable new-cap */
+            tabList.append(verticalTab.item);
+            $that
+              // prop() can't be used on browsers not supporting details
+              // element, the style won't apply to them if prop() is used.
+              .removeAttr('open')
+              .addClass(verticalTabsSettings.paneClasses.join(' '))
+              .addClass('js-vertical-tabs-pane')
+              .data('verticalTab', verticalTab);
+            if (this.id === focusID) {
+              tabFocus = $that;
+            }
+          });
+
+          if (!tabFocus) {
+            // If the current URL has a fragment and one of the tabs contains an
+            // element that matches the URL fragment, activate that tab.
+            const $locationHash = $this.find(window.location.hash);
+            if (window.location.hash && $locationHash.length) {
+              tabFocus = $locationHash.is('.js-vertical-tabs-pane') ? $locationHash : $locationHash.closest('.js-vertical-tabs-pane');
+            }
+            else {
+              tabFocus = $this.find('> .js-vertical-tabs-pane').eq(0);
+            }
+          }
+          if (tabFocus.length) {
+            tabFocus.data('verticalTab').focus(false);
+            // The core/misc/collapse.js won't be ready at this time, we have to
+            // open the details manually for non-upporting browsers.
+            // tabFocus.data('verticalTab').details.attr('open', true);
+          }
+        });
+    },
+  };
+
+  /**
+   * The vertical tab object represents a single tab within a tab group.
+   *
+   * @constructor
+   *
+   * @param {object} settings
+   *   Settings object.
+   * @param {string} settings.title
+   *   The name of the tab.
+   * @param {jQuery} settings.details
+   *   The jQuery object of the details element that is the tab pane.
+   * @param {jQuery} settings.settings
+   *   The jQuery object of vertical tab settings.
+   *
+   * @fires event:summaryUpdated
+   *
+   * @listens event:summaryUpdated
+   */
+  Drupal.verticalTab = function verticalTab(settings) {
+    const self = this;
+    this.settings = settings.settings;
+    $.extend(this, settings, Drupal.theme('verticalTab', settings));
+
+    this.item.addClass('js-vertical-tabs-menu-item');
+
+    this.link.attr('href', `#${settings.details.attr('id')}`);
+
+    this.detailsSummaryDescription = $(Drupal.theme.verticalTabDetailsDescription())
+      .appendTo(this.details.find('> summary'));
+
+    this.link.on('click', (event) => {
+      event.preventDefault();
+      self.focus();
+    });
+
+    this.details.on('toggle', (event) => {
+      // We will control this by summary clicks.
+      event.preventDefault();
+    });
+
+    // For every browser, with or without details support.
+    this.details.find('> summary').on('click', (event) => {
+      event.preventDefault();
+      self.details.attr('open', true);
+      if (self.details.hasClass('collapse-processed')) {
+        setTimeout(() => {
+          self.focus();
+        }, 10);
+      }
+      else {
+        self.focus();
+      }
+    });
+
+    // Keyboard events added:
+    // Pressing the Enter key will open the tab pane.
+    this.link.on('keydown', (event) => {
+      if (event.keyCode === 13) {
+        event.preventDefault();
+        self.focus();
+        // Set focus on the first input field of the visible details/tab pane.
+        $('.js-vertical-tabs-pane :input:visible:enabled')
+          .eq(0)
+          .trigger('focus');
+      }
+    });
+
+    this.details
+      .on('summaryUpdated', () => {
+        self.updateSummary();
+      }).trigger('summaryUpdated');
+  };
+
+  Drupal.verticalTab.prototype = {
+    /**
+     * Displays the tab's content pane.
+     *
+     * @param {bool} triggerFocus
+     *   Whether focus should be triggered for the summary element.
+     */
+    focus(triggerFocus = true) {
+      this.details
+        .siblings('.js-vertical-tabs-pane')
+        .each(function closeOtherTabs() {
+          const tab = $(this).data('verticalTab');
+          if (tab.details.attr('open')) {
+            tab.details
+              .removeAttr('open')
+              .find('> summary')
+              .attr({
+                'aria-expanded': 'false',
+                'aria-pressed': 'false',
+              });
+            tab.item.removeClass('is-selected');
+          }
+        })
+        .end()
+        .siblings(':hidden.vertical-tabs__active-tab')
+        .val(this.details.attr('id'));
+
+      this.details
+        .attr('open', true)
+        .find('> summary')
+        .attr({
+          'aria-expanded': 'true',
+          'aria-pressed': 'true',
+        });
+
+      if (triggerFocus) {
+        const $summary = this.details.find('> summary');
+        if ($summary.is(':visible')) {
+          $summary.trigger('focus');
+        }
+      }
+
+      this.item.addClass('is-selected');
+      // Mark the active tab for screen readers.
+      $('#active-vertical-tab').remove();
+      this.link.append($(Drupal.theme.verticalTabActiveTabIndicator())
+        .attr('id', 'active-vertical-tab'));
+    },
+
+    /**
+     * Updates the tab's summary.
+     */
+    updateSummary() {
+      const summary = this.details.drupalGetSummary();
+      this.detailsSummaryDescription.html(summary);
+      this.summary.html(summary);
+    },
+
+    /**
+     * Shows a vertical tab pane.
+     *
+     * @return {Drupal.verticalTab}
+     *   The verticalTab instance.
+     */
+    tabShow() {
+      // Display the tab.
+      this.item
+        .removeClass(this.settings.menuItemClassesHidden.join(' '))
+        .show();
+      // Show the vertical tabs.
+      this.item.closest('.js-form-type-vertical-tabs').show();
+      // Display the details element.
+      this.details
+        .removeClass(this.settings.paneClassesHidden.join(' '))
+        .removeClass('js-vertical-tab-hidden')
+        .show();
+      // Update first and last CSS classes for details.
+      this.details
+        .parent()
+        .children('.js-vertical-tabs-pane')
+        .removeClass(this.settings.paneClassesFirst.join(' '))
+        .removeClass(this.settings.paneClassesLast.join(' '))
+        .filter(':visible')
+        .eq(0)
+        .addClass(this.settings.paneClassesFirst.join(' '));
+      this.details
+        .parent()
+        .children('.js-vertical-tabs-pane')
+        .filter(':visible')
+        .eq(-1)
+        .addClass(this.settings.paneClassesLast.join(' '));
+      // Make tab active, but without triggering focus.
+      this.focus(false);
+      return this;
+    },
+
+    /**
+     * Hides a vertical tab pane.
+     *
+     * @return {Drupal.verticalTab}
+     *   The verticalTab instance.
+     */
+    tabHide() {
+      // Hide this tab.
+      this.item
+        .addClass(this.settings.menuItemClassesHidden.join(' '))
+        .hide();
+      // Hide the details element.
+      this.details
+        .addClass(this.settings.paneClassesHidden.join(' '))
+        .addClass('js-vertical-tab-hidden')
+        .hide();
+      // Update first and last CSS classes for details.
+      this.details
+        .parent()
+        .children('.js-vertical-tabs-pane')
+        .removeClass(this.settings.paneClassesFirst.join(' '))
+        .removeClass(this.settings.paneClassesLast.join(' '))
+        .filter(':visible')
+        .eq(0)
+        .addClass(this.settings.paneClassesFirst.join(' '));
+      this.details
+        .parent()
+        .children('.js-vertical-tabs-pane')
+        .filter(':visible')
+        .eq(-1)
+        .addClass(this.settings.paneClassesLast.join(' '));
+      // Focus the first visible tab (if there is one).
+      const $firstTab = this.details
+        .siblings('.js-vertical-tabs-pane:not(.js-vertical-tab-hidden)')
+        .eq(0);
+      if ($firstTab.length) {
+        $firstTab.data('verticalTab').focus(false);
+      }
+      // Hide the vertical tabs (if no tabs remain).
+      else {
+        this.item.closest('.js-form-type-vertical-tabs').hide();
+      }
+      return this;
+    },
+  };
+
+  /**
+   * Theme function for a vertical tab.
+   *
+   * @param {object} settings
+   *   An object with the following keys:
+   * @param {string} settings.title
+   *   The name of the tab.
+   *
+   * @return {object}
+   *   This function has to return an object with at least these keys:
+   *   - item: The root tab jQuery element
+   *   - link: The anchor tag that acts as the clickable area of the tab
+   *       (jQuery version)
+   *   - summary: The jQuery element that contains the tab summary
+   */
+  Drupal.theme.verticalTab = (settings) => {
+    const tab = {};
+    tab.item = $('<li class="vertical-tabs__menu-item" tabindex="-1"></li>')
+      .append((tab.link = $('<a href="#" class="vertical-tabs__menu-link"></a>')
+        .append((tab.title = $('<strong class="vertical-tabs__menu-item-title"></strong>').text(settings.title)))
+        .append((tab.summary = $('<span class="vertical-tabs__menu-item-summary"></span>')))));
+    return tab;
+  };
+
+  /**
+   * Wrapper of the menu and the panes.
+   *
+   * @return {string}
+   *   A string representing the DOM fragment.
+   */
+  Drupal.theme.verticalTabsWrapper = () =>
+    '<div class="vertical-tabs clearfix"></div>';
+
+  /**
+   * The wrapper of the vertical tab menu items.
+   *
+   * @return {string}
+   *   A string representing the DOM fragment.
+   */
+  Drupal.theme.verticalTabListWrapper = () =>
+    '<ul class="vertical-tabs__menu"></ul>';
+
+  /**
+   * The wrapper of the details summary message added to the summary element.
+   *
+   * @return {string}
+   *   A string representing the DOM fragment.
+   */
+  Drupal.theme.verticalTabDetailsDescription = () =>
+    '<span class="vertical-tabs__details-summary-summary"></span>';
+
+  /**
+   * Themes the active vertical tab menu item message.
+   *
+   * @return {string}
+   *   A string representing the DOM fragment.
+   */
+  Drupal.theme.verticalTabActiveTabIndicator = () =>
+    `<span id="active-vertical-tab" class="visually-hidden">${Drupal.t('(active tab)')}</span>`;
+})(jQuery, Drupal);
diff --git a/js/claro.vertical-tabs.js b/js/claro.vertical-tabs.js
new file mode 100644
index 0000000..61b947a
--- /dev/null
+++ b/js/claro.vertical-tabs.js
@@ -0,0 +1,208 @@
+/**
+* DO NOT EDIT THIS FILE.
+* See the following change record for more information,
+* https://www.drupal.org/node/2815083
+* @preserve
+**/
+
+(function ($, Drupal) {
+  var handleFragmentLinkClickOrHashChange = function handleFragmentLinkClickOrHashChange(e, $target) {
+    $target.parents('.js-vertical-tabs-pane').each(function (index, pane) {
+      $(pane).data('verticalTab').focus();
+    });
+  };
+
+  Drupal.behaviors.claroVerticalTabs = {
+    attach: function attach(context, settings) {
+      var verticalTabsDefaults = {
+        paneClasses: ['vertical-tabs__pane'],
+        paneClassesFirst: ['first'],
+        paneClassesLast: ['last'],
+        paneClassesHidden: ['vertical-tab--hidden'],
+        paneWrapperClasses: ['vertical-tabs__panes'],
+        menuItemClassesHidden: []
+      };
+      var verticalTabsSettings = $.extend({}, verticalTabsDefaults, settings.verticalTabs || {});
+
+      $('body').once('vertical-tabs-fragments').on('formFragmentLinkClickOrHashChange.verticalTabs', handleFragmentLinkClickOrHashChange);
+
+      $(context).find('[data-vertical-tabs-panes]').once('vertical-tabs').each(function initializeVerticalTabs() {
+        var $this = $(this).addClass(verticalTabsSettings.paneWrapperClasses.join(' '));
+        var focusID = $this.find(':hidden.vertical-tabs__active-tab').val();
+        var tabFocus = void 0;
+
+        var $details = $this.find('> details');
+        if ($details.length === 0) {
+          return;
+        }
+
+        var tabList = $(Drupal.theme.verticalTabListWrapper());
+        $this.wrap(Drupal.theme.verticalTabsWrapper()).before(tabList);
+
+        $details.each(function initializeVerticalTabItems() {
+          var $that = $(this);
+
+          var verticalTab = new Drupal.verticalTab({
+            title: $that.find('> summary').text(),
+            details: $that,
+            settings: verticalTabsSettings
+          });
+
+          tabList.append(verticalTab.item);
+          $that.removeAttr('open').addClass(verticalTabsSettings.paneClasses.join(' ')).addClass('js-vertical-tabs-pane').data('verticalTab', verticalTab);
+          if (this.id === focusID) {
+            tabFocus = $that;
+          }
+        });
+
+        if (!tabFocus) {
+          var $locationHash = $this.find(window.location.hash);
+          if (window.location.hash && $locationHash.length) {
+            tabFocus = $locationHash.is('.js-vertical-tabs-pane') ? $locationHash : $locationHash.closest('.js-vertical-tabs-pane');
+          } else {
+            tabFocus = $this.find('> .js-vertical-tabs-pane').eq(0);
+          }
+        }
+        if (tabFocus.length) {
+          tabFocus.data('verticalTab').focus(false);
+        }
+      });
+    }
+  };
+
+  Drupal.verticalTab = function verticalTab(settings) {
+    var self = this;
+    this.settings = settings.settings;
+    $.extend(this, settings, Drupal.theme('verticalTab', settings));
+
+    this.item.addClass('js-vertical-tabs-menu-item');
+
+    this.link.attr('href', '#' + settings.details.attr('id'));
+
+    this.detailsSummaryDescription = $(Drupal.theme.verticalTabDetailsDescription()).appendTo(this.details.find('> summary'));
+
+    this.link.on('click', function (event) {
+      event.preventDefault();
+      self.focus();
+    });
+
+    this.details.on('toggle', function (event) {
+      event.preventDefault();
+    });
+
+    this.details.find('> summary').on('click', function (event) {
+      event.preventDefault();
+      self.details.attr('open', true);
+      if (self.details.hasClass('collapse-processed')) {
+        setTimeout(function () {
+          self.focus();
+        }, 10);
+      } else {
+        self.focus();
+      }
+    });
+
+    this.link.on('keydown', function (event) {
+      if (event.keyCode === 13) {
+        event.preventDefault();
+        self.focus();
+
+        $('.js-vertical-tabs-pane :input:visible:enabled').eq(0).trigger('focus');
+      }
+    });
+
+    this.details.on('summaryUpdated', function () {
+      self.updateSummary();
+    }).trigger('summaryUpdated');
+  };
+
+  Drupal.verticalTab.prototype = {
+    focus: function focus() {
+      var triggerFocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
+
+      this.details.siblings('.js-vertical-tabs-pane').each(function closeOtherTabs() {
+        var tab = $(this).data('verticalTab');
+        if (tab.details.attr('open')) {
+          tab.details.removeAttr('open').find('> summary').attr({
+            'aria-expanded': 'false',
+            'aria-pressed': 'false'
+          });
+          tab.item.removeClass('is-selected');
+        }
+      }).end().siblings(':hidden.vertical-tabs__active-tab').val(this.details.attr('id'));
+
+      this.details.attr('open', true).find('> summary').attr({
+        'aria-expanded': 'true',
+        'aria-pressed': 'true'
+      });
+
+      if (triggerFocus) {
+        var $summary = this.details.find('> summary');
+        if ($summary.is(':visible')) {
+          $summary.trigger('focus');
+        }
+      }
+
+      this.item.addClass('is-selected');
+
+      $('#active-vertical-tab').remove();
+      this.link.append($(Drupal.theme.verticalTabActiveTabIndicator()).attr('id', 'active-vertical-tab'));
+    },
+    updateSummary: function updateSummary() {
+      var summary = this.details.drupalGetSummary();
+      this.detailsSummaryDescription.html(summary);
+      this.summary.html(summary);
+    },
+    tabShow: function tabShow() {
+      this.item.removeClass(this.settings.menuItemClassesHidden.join(' ')).show();
+
+      this.item.closest('.js-form-type-vertical-tabs').show();
+
+      this.details.removeClass(this.settings.paneClassesHidden.join(' ')).removeClass('js-vertical-tab-hidden').show();
+
+      this.details.parent().children('.js-vertical-tabs-pane').removeClass(this.settings.paneClassesFirst.join(' ')).removeClass(this.settings.paneClassesLast.join(' ')).filter(':visible').eq(0).addClass(this.settings.paneClassesFirst.join(' '));
+      this.details.parent().children('.js-vertical-tabs-pane').filter(':visible').eq(-1).addClass(this.settings.paneClassesLast.join(' '));
+
+      this.focus(false);
+      return this;
+    },
+    tabHide: function tabHide() {
+      this.item.addClass(this.settings.menuItemClassesHidden.join(' ')).hide();
+
+      this.details.addClass(this.settings.paneClassesHidden.join(' ')).addClass('js-vertical-tab-hidden').hide();
+
+      this.details.parent().children('.js-vertical-tabs-pane').removeClass(this.settings.paneClassesFirst.join(' ')).removeClass(this.settings.paneClassesLast.join(' ')).filter(':visible').eq(0).addClass(this.settings.paneClassesFirst.join(' '));
+      this.details.parent().children('.js-vertical-tabs-pane').filter(':visible').eq(-1).addClass(this.settings.paneClassesLast.join(' '));
+
+      var $firstTab = this.details.siblings('.js-vertical-tabs-pane:not(.js-vertical-tab-hidden)').eq(0);
+      if ($firstTab.length) {
+        $firstTab.data('verticalTab').focus(false);
+      } else {
+          this.item.closest('.js-form-type-vertical-tabs').hide();
+        }
+      return this;
+    }
+  };
+
+  Drupal.theme.verticalTab = function (settings) {
+    var tab = {};
+    tab.item = $('<li class="vertical-tabs__menu-item" tabindex="-1"></li>').append(tab.link = $('<a href="#" class="vertical-tabs__menu-link"></a>').append(tab.title = $('<strong class="vertical-tabs__menu-item-title"></strong>').text(settings.title)).append(tab.summary = $('<span class="vertical-tabs__menu-item-summary"></span>')));
+    return tab;
+  };
+
+  Drupal.theme.verticalTabsWrapper = function () {
+    return '<div class="vertical-tabs clearfix"></div>';
+  };
+
+  Drupal.theme.verticalTabListWrapper = function () {
+    return '<ul class="vertical-tabs__menu"></ul>';
+  };
+
+  Drupal.theme.verticalTabDetailsDescription = function () {
+    return '<span class="vertical-tabs__details-summary-summary"></span>';
+  };
+
+  Drupal.theme.verticalTabActiveTabIndicator = function () {
+    return '<span id="active-vertical-tab" class="visually-hidden">' + Drupal.t('(active tab)') + '</span>';
+  };
+})(jQuery, Drupal);
\ No newline at end of file
diff --git a/templates/navigation/details--vertical-tabs.html.twig b/templates/navigation/details--vertical-tabs.html.twig
new file mode 100644
index 0000000..3a3154b
--- /dev/null
+++ b/templates/navigation/details--vertical-tabs.html.twig
@@ -0,0 +1,77 @@
+{#
+/**
+ * @file
+ * Theme override for a details element.
+ *
+ * Available variables
+ * - attributes: A list of HTML attributes for the details element.
+ * - errors: (optional) Any errors for this details element, may not be set.
+ * - title: (optional) The title of the element, may not be set.
+ * - description: (optional) The description of the element, may not be set.
+ * - children: (optional) The children of the element, may not be set.
+ * - value: (optional) The value of the element, may not be set.
+ * - accordion: whether the details element should look as an accordion.
+ * - accordion_item: whether the details element is an item of an accordion
+ *   list.
+ *
+ * @see template_preprocess_details()
+ * @see claro_preprocess_details()
+ */
+#}
+{#
+  Prefix 'details' class to avoid collision with Modernizr.
+
+  @todo Remove prefix after https://www.drupal.org/node/2981732 has been solved.
+#}
+{%
+  set classes = [
+    'claro-details',
+    'claro-details--vertical-tabs-item',
+  ]
+%}
+{%
+  set content_wrapper_classes = [
+    'claro-details__wrapper',
+    'details-wrapper',
+    'claro-details__wrapper--vertical-tabs-item',
+  ]
+%}
+{%
+  set inner_wrapper_classes = [
+    'claro-details__content',
+    'claro-details__content--vertical-tabs-item',
+  ]
+%}
+<details{{ attributes.addClass(classes) }}>
+  {%- if title -%}
+    {%
+      set summary_classes = [
+        'claro-details__summary',
+        'claro-details__summary--vertical-tabs-item',
+        required ? 'js-form-required',
+        required ? 'form-required',
+      ]
+    %}
+    <summary{{ summary_attributes.addClass(summary_classes) }}>
+      {{- title -}}
+    </summary>
+  {%- endif -%}
+  <div{{ content_attributes.addClass(content_wrapper_classes) }}>
+    <div{{ create_attribute({class: inner_wrapper_classes}) }}>
+      {% if errors %}
+        <div class="form-item form-item--error-message">
+          {{ errors }}
+        </div>
+      {% endif %}
+      {%- if description -%}
+        <div class="claro-details__description">{{ description }}</div>
+      {%- endif -%}
+      {%- if children -%}
+        {{ children }}
+      {%- endif -%}
+      {%- if value -%}
+        {{ value }}
+      {%- endif -%}
+    </div>
+  </div>
+</details>
