diff --git a/core/themes/claro/claro.info.yml b/core/themes/claro/claro.info.yml
index 71412c9573..623a4602e2 100644
--- a/core/themes/claro/claro.info.yml
+++ b/core/themes/claro/claro.info.yml
@@ -120,6 +120,12 @@ libraries-override:
       theme:
         /core/themes/stable/css/views_ui/views_ui.admin.theme.css: css/theme/views_ui.admin.theme.css
 
+  # Drupal throws an IncompleteLibraryDefinitionException if a base theme
+  # defined library is set to false in a subtheme's libraries-override.
+  # We use 'claro/empty' for working around this behavior.
+  # @see https://www.drupal.org/node/3098375
+  classy/media_library: claro/empty
+
 libraries-extend:
   ckeditor/drupal.ckeditor:
     - claro/ckeditor-editor
@@ -153,6 +159,10 @@ libraries-extend:
     - claro/ajax
   views/views.module:
     - claro/views
+  media_library/view:
+    - claro/media_library.theme
+  media_library/widget:
+    - claro/media_library.theme
 
 quickedit_stylesheets:
   - css/components/quickedit.css
diff --git a/core/themes/claro/claro.libraries.yml b/core/themes/claro/claro.libraries.yml
index c6c2466a47..cc13092ffc 100644
--- a/core/themes/claro/claro.libraries.yml
+++ b/core/themes/claro/claro.libraries.yml
@@ -64,6 +64,14 @@ global-styling:
     # it has to be always attached.
     - core/modernizr
 
+# Drupal throws an IncompleteLibraryDefinitionException if a base theme defined
+# library is set to false in a subtheme's libraries-override.
+# We use this dummy library as workaround.
+# @see https://www.drupal.org/node/3098375
+empty:
+  version: VERSION
+  css: {}
+
 node-form:
   version: VERSION
   css:
@@ -247,3 +255,9 @@ file:
   css:
     component:
       css/components/file.css: {}
+
+media_library.theme:
+  version: VERSION
+  css:
+    theme:
+      css/theme/media-library.css: {}
diff --git a/core/themes/claro/claro.theme b/core/themes/claro/claro.theme
index df810f09b8..9324b3cf1f 100644
--- a/core/themes/claro/claro.theme
+++ b/core/themes/claro/claro.theme
@@ -17,6 +17,8 @@
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Url;
 use Drupal\media\MediaForm;
+use Drupal\views\ViewExecutable;
+use Drupal\file\FileInterface;
 
 /**
  * Implements hook_theme_suggestions_HOOK_alter() for form_element.
@@ -352,13 +354,22 @@ function claro_preprocess_details(&$variables) {
 /**
  * Implements hook_form_alter().
  */
-function claro_form_alter(&$form, FormStateInterface $form_state) {
+function claro_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
   $build_info = $form_state->getBuildInfo();
+  $form_object = $form_state->getFormObject();
 
   // Make entity forms delete link use the action-link component.
   if (isset($form['actions']['delete']['#type']) && $form['actions']['delete']['#type'] === 'link' && !empty($build_info['callback_object']) && $build_info['callback_object'] instanceof EntityForm) {
     $form['actions']['delete'] = _claro_convert_link_to_action_link($form['actions']['delete'], 'trash', 'default', 'danger');
   }
+
+  if ($form_object instanceof ViewsForm && strpos($form_object->getBaseFormId(), 'views_form_media_library') === 0) {
+    if (isset($form['header'])) {
+      $form['header']['#attributes']['class'][] = 'media-library-views-form__header';
+      $form['header']['media_bulk_form']['#attributes']['class'][] = 'media-library-views-form__bulk_form';
+    }
+    $form['actions']['submit']['#attributes']['class'] = ['media-library-select'];
+  }
 }
 
 /**
@@ -591,11 +602,10 @@ function claro_views_ui_display_tab_alter(&$element) {
 }
 
 /**
- * Implements hook_form_FORM_ID_alter() for views_exposed_form.
+ * Implements hook_preprocess_HOOK for views_exposed_form.
  */
-function claro_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) {
-  $view = $form_state->getStorage()['view'];
-  $view_title = $view->getTitle();
+function claro_preprocess_views_exposed_form(&$variables) {
+  $form = &$variables['form'];
 
   // Add BEM classes for items in the form.
   // Sorted keys.
@@ -623,6 +633,14 @@ function claro_form_views_exposed_form_alter(&$form, FormStateInterface $form_st
     // Add a modifier class to the item that precedes the form actions.
     $form[$child_before_actions_key]['#wrapper_attributes']['class'][] = 'views-exposed-form__item--preceding-actions';
   }
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter() for views_exposed_form.
+ */
+function claro_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) {
+  $view = $form_state->getStorage()['view'];
+  $view_title = $view->getTitle();
 
   // Add a label so screenreaders can identify the purpose of the exposed form
   // without having to scan content that appears further down the page.
@@ -1083,23 +1101,13 @@ function claro_preprocess_links__action_links(&$variables) {
  * Implements hook_preprocess_HOOK() for file_managed_file.
  */
 function claro_preprocess_file_managed_file(&$variables) {
-  $element = $variables['element'];
-
-  // Calculate helper values for the template.
-  $upload_is_accessible = !isset($element['upload']['#access']) || $element['upload']['#access'] !== FALSE;
-  $is_multiple = !empty($element['#cardinality']) && $element['#cardinality'] !== 1;
-  $has_value = isset($element['#value']['fids']) && !empty($element['#value']['fids']);
-  $display_can_be_displayed = !empty($element['#display_field']);
-  // Display is rendered in a separate table cell for multiple value widgets.
-  $display_is_visible = $display_can_be_displayed && !$is_multiple && isset($element['display']['#type']) && $element['display']['#type'] !== 'hidden';
-  $description_can_be_displayed = !empty($element['#description_field']);
-  $description_is_visible = $description_can_be_displayed && isset($element['description']);
+  // Produce the same renderable element structure as image widget has.
+  $child_keys = Element::children($variables['element']);
+  foreach ($child_keys as $child_key) {
+    $variables['data'][$child_key] = $variables['element'][$child_key];
+  }
 
-  $variables['multiple'] = $is_multiple;
-  $variables['upload'] = $upload_is_accessible;
-  $variables['has_value'] = $has_value;
-  $variables['has_meta'] = $display_is_visible || $description_is_visible;
-  $variables['display'] = $display_is_visible;
+  _claro_preprocess_file_and_image_widget($variables);
 }
 
 /**
@@ -1178,8 +1186,6 @@ function claro_preprocess_file_widget_multiple(&$variables) {
  * Implements hook_preprocess_HOOK() for image_widget.
  */
 function claro_preprocess_image_widget(&$variables) {
-  $element = $variables['element'];
-
   // Stable adds the file size as #suffix for image file_link renderable array.
   // We have to remove that because we will render it in our file_link template
   // for every kind of files, and not just for images.
@@ -1188,10 +1194,39 @@ function claro_preprocess_image_widget(&$variables) {
     unset($variables['data']['file_' . $file->id()]['filename']['#suffix']);
   }
 
+  _claro_preprocess_file_and_image_widget($variables);
+}
+
+/**
+ * Helper pre-process callback for file_managed_file and image_widget.
+ *
+ * Performs the common preprocess tasks.
+ *
+ * @param array $variables
+ *   The renderable array of image and file widgets, with 'element' and 'data'
+ *   keys.
+ */
+function _claro_preprocess_file_and_image_widget(array &$variables) {
+  $element = $variables['element'];
+  $main_item_keys = [
+    'upload',
+    'upload_button',
+    'remove_button',
+  ];
+
   // Calculate helper values for the template.
   $upload_is_accessible = !isset($element['upload']['#access']) || $element['upload']['#access'] !== FALSE;
   $is_multiple = !empty($element['#cardinality']) && $element['#cardinality'] !== 1;
   $has_value = isset($element['#value']['fids']) && !empty($element['#value']['fids']);
+
+  // File widget properties.
+  $display_can_be_displayed = !empty($element['#display_field']);
+  // Display is rendered in a separate table cell for multiple value widgets.
+  $display_is_visible = $display_can_be_displayed && !$is_multiple && isset($element['display']['#type']) && $element['display']['#type'] !== 'hidden';
+  $description_can_be_displayed = !empty($element['#description_field']);
+  $description_is_visible = $description_can_be_displayed && isset($element['description']);
+
+  // Image widget properties.
   $alt_can_be_displayed = !empty($element['#alt_field']);
   $alt_is_visible = $alt_can_be_displayed && (!isset($element['alt']['#access']) || $element['alt']['#access'] !== FALSE);
   $title_can_be_displayed = !empty($element['#title_field']);
@@ -1200,5 +1235,206 @@ function claro_preprocess_image_widget(&$variables) {
   $variables['multiple'] = $is_multiple;
   $variables['upload'] = $upload_is_accessible;
   $variables['has_value'] = $has_value;
-  $variables['has_meta'] = $alt_is_visible || $title_is_visible;
+  $variables['has_meta'] = $alt_is_visible || $title_is_visible || $display_is_visible || $description_is_visible;
+  $variables['display'] = $display_is_visible;
+
+  // Restructure widget items.
+  //
+  // At file or image widgets, Claro renders the file upload input and the
+  // upload button (or the file name and the remove button, if the field is not
+  // empty) in an emphasized div. Every other component and property input are
+  // displayede below these components.
+  //
+  // Since contrib modules may add another components for image or file widgets,
+  // and because of the filename component's key varies, we inspect all the
+  // avalialbe renderable components.
+  // We move the file name, the upload input, the upload and the remove buttons
+  // under the 'main_items', and we also change the key of the file name
+  // component.
+  foreach ($variables['data'] as $key => $item) {
+    $item_type_is_hidden = isset($item['#type']) && $item['#type'] === 'hidden';
+    $item_is_printed = !empty($item['#printed']);
+    $item_is_filename = isset($item['filename']['#file']) && $item['filename']['#file'] instanceof FileInterface;
+
+    // Move filename to main items.
+    if ($item_is_filename) {
+      $variables['main_items']['filename'] = $item;
+      unset($variables['data'][$key]);
+      continue;
+    }
+
+    // Move buttons, upload input and hidden items to main items.
+    if (in_array($key, $main_item_keys)) {
+      $variables['main_items'][$key] = $item;
+      unset($variables['data'][$key]);
+    }
+  }
+}
+
+/**
+ * Implements hook_preprocess_views_view_fields().
+ *
+ * This targets each rendered media item in the grid display of the media
+ * library's modal dialog.
+ */
+function claro_preprocess_views_view_fields__media_library(array &$variables) {
+  // Add classes to media rendered entity field so it can be targeted for
+  // styling. Adding this class in a template is very difficult to do.
+  if (isset($variables['fields']['rendered_entity']->wrapper_attributes)) {
+    $variables['fields']['rendered_entity']->wrapper_attributes->addClass('media-library-item__click-to-select-trigger');
+  }
+}
+
+/**
+ * Implements hook_form_BASE_FORM_ID_alter().
+ */
+function claro_form_media_library_add_form_alter(array &$form, FormStateInterface $form_state) {
+  $form['#attributes']['class'][] = 'media-library-add-form';
+  $form['#attached']['library'][] = 'claro/media_library.theme';
+
+  // If there are unsaved media items, apply styling classes to various parts
+  // of the form.
+  if (isset($form['media'])) {
+    $form['#attributes']['class'][] = 'media-library-add-form--with-input';
+
+    // Put a wrapper around the informational message above the unsaved media
+    // items.
+    $form['description']['#template'] = '<p class="media-library-add-form__description">{{ text }}</p>';
+  }
+  else {
+    $form['#attributes']['class'][] = 'media-library-add-form--without-input';
+  }
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function claro_form_media_library_add_form_upload_alter(array &$form, FormStateInterface $form_state) {
+  $form['#attributes']['class'][] = 'media-library-add-form--upload';
+
+  if (isset($form['container'])) {
+    $form['container']['#attributes']['class'][] = 'media-library-add-form__input-wrapper';
+  }
+}
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function claro_form_media_library_add_form_oembed_alter(array &$form, FormStateInterface $form_state) {
+  $form['attributes']['class'][] = 'media-library-add-form--oembed';
+
+  // If no media items have been added yet, add a couple of styling classes
+  // to the initial URL form.
+  if (isset($form['container'])) {
+    $form['container']['#attributes']['class'][] = 'media-library-add-form__input-wrapper';
+    $form['container']['url']['#attributes']['class'][] = 'media-library-add-form-oembed-url';
+    $form['container']['submit']['#attributes']['class'][] = 'media-library-add-form-oembed-submit';
+  }
+}
+
+/**
+ * Implements hook_preprocess_item_list__media_library_add_form_media_list().
+ *
+ * This targets each new, unsaved media item added to the media library, before
+ * they are saved.
+ */
+function claro_preprocess_item_list__media_library_add_form_media_list(array &$variables) {
+  foreach ($variables['items'] as &$item) {
+    $item['value']['preview']['#attributes']['class'][] = 'media-library-add-form__preview';
+    $item['value']['fields']['#attributes']['class'][] = 'media-library-add-form__fields';
+    $item['value']['remove_button']['#attributes']['class'][] = 'media-library-add-form__remove-button';
+
+    // #source_field_name is set by AddFormBase::buildEntityFormElement()
+    // to help themes and form_alter hooks identify the source field.
+    $fields = &$item['value']['fields'];
+    $source_field_name = $fields['#source_field_name'];
+    if (isset($fields[$source_field_name])) {
+      $fields[$source_field_name]['#attributes']['class'][] = 'media-library-add-form__source-field';
+    }
+  }
+}
+
+/**
+ * Implements hook_preprocess_media_library_item__widget().
+ *
+ * This targets each media item selected in an entity reference field.
+ */
+function claro_preprocess_media_library_item__widget(array &$variables) {
+  $variables['content']['remove_button']['#attributes']['class'][] = 'media-library-item__remove';
+}
+
+/**
+ * Implements hook_preprocess_media_library_item__small().
+ *
+ * This targets each pre-selected media item selected when adding new media in
+ * the modal media library dialog.
+ */
+function claro_preprocess_media_library_item__small(array &$variables) {
+  $variables['content']['select']['#attributes']['class'][] = 'media-library-item__click-to-select-checkbox';
+}
+
+/**
+ * @todo Remove this when https://www.drupal.org/project/drupal/issues/2999549
+ * lands.
+ *
+ * @see \Drupal\media_library\Plugin\Field\FieldWidget\MediaLibraryWidget::formElement()
+ */
+function claro_preprocess_fieldset__media_library_widget(array &$variables) {
+  if (isset($variables['prefix']['weight_toggle'])) {
+    $variables['prefix']['weight_toggle']['#attributes']['class'][] = 'media-library-widget__toggle-weight';
+  }
+  if (isset($variables['suffix']['open_button'])) {
+    $variables['suffix']['open_button']['#attributes']['class'][] = 'media-library-open-button';
+  }
+}
+
+/**
+ * Implements hook_views_pre_render().
+ */
+function claro_views_pre_render(ViewExecutable $view) {
+  $add_classes = function (&$option, array $classes_to_add) {
+    $classes = preg_split('/\s+/', $option);
+    $classes = array_filter($classes);
+    $classes = array_merge($classes, $classes_to_add);
+    $option = implode(' ', array_unique($classes));
+  };
+
+  if ($view->id() === 'media_library') {
+    if ($view->display_handler->options['defaults']['css_class']) {
+      $add_classes($view->displayHandlers->get('default')->options['css_class'], ['media-library-view']);
+    }
+    else {
+      $add_classes($view->display_handler->options['css_class'], ['media-library-view']);
+    }
+
+    if ($view->current_display === 'page') {
+      if (array_key_exists('media_bulk_form', $view->field)) {
+        $add_classes($view->field['media_bulk_form']->options['element_class'], ['media-library-item__click-to-select-checkbox']);
+      }
+      if (array_key_exists('rendered_entity', $view->field)) {
+        $add_classes($view->field['rendered_entity']->options['element_class'], ['media-library-item__content']);
+      }
+      if (array_key_exists('edit_media', $view->field)) {
+        $add_classes($view->field['edit_media']->options['alter']['link_class'], ['media-library-item__edit']);
+      }
+      if (array_key_exists('delete_media', $view->field)) {
+        $add_classes($view->field['delete_media']->options['alter']['link_class'], ['media-library-item__remove']);
+      }
+    }
+    elseif (strpos($view->current_display, 'widget') === 0) {
+      if (array_key_exists('rendered_entity', $view->field)) {
+        $add_classes($view->field['rendered_entity']->options['element_class'], ['media-library-item__content']);
+      }
+      if (array_key_exists('media_library_select_form', $view->field)) {
+        $add_classes($view->field['media_library_select_form']->options['element_wrapper_class'], ['media-library-item__click-to-select-checkbox']);
+      }
+
+      if ($view->display_handler->options['defaults']['css_class']) {
+        $add_classes($view->displayHandlers->get('default')->options['css_class'], ['media-library-view--widget']);
+      }
+      else {
+        $add_classes($view->display_handler->options['css_class'], ['media-library-view--widget']);
+      }
+    }
+  }
 }
diff --git a/core/themes/claro/css/components/form--managed-file.css b/core/themes/claro/css/components/form--managed-file.css
index 698ce0b739..929e10ea90 100644
--- a/core/themes/claro/css/components/form--managed-file.css
+++ b/core/themes/claro/css/components/form--managed-file.css
@@ -266,15 +266,6 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
   }
 }
 
-/**
- * Remove the default margins of buttons.
- * The '.button' selector is doubled for RTL layouts.
- */
-
-.form-managed-file .button.button {
-  margin: 0;
-}
-
 /**
  * The file upload input.
  */
@@ -285,12 +276,14 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
 }
 
 /**
+ * Remove the default margins of buttons and prevent these to be shrinked.
  * This applies both on the 'no-js' upload button and the remove button.
- * We don't want to let these to be shrinked.
+ * The '.button' selector is doubled for RTL layouts.
  */
 
-.form-managed-file__main .button {
+.form-managed-file__main .button.button {
   flex: 0 0 auto;
+  margin: 0;
 }
 
 /**
diff --git a/core/themes/claro/css/components/form--managed-file.pcss.css b/core/themes/claro/css/components/form--managed-file.pcss.css
index dfd0f8c34e..6c7012dab0 100644
--- a/core/themes/claro/css/components/form--managed-file.pcss.css
+++ b/core/themes/claro/css/components/form--managed-file.pcss.css
@@ -203,14 +203,6 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
   }
 }
 
-/**
- * Remove the default margins of buttons.
- * The '.button' selector is doubled for RTL layouts.
- */
-.form-managed-file .button.button {
-  margin: 0;
-}
-
 /**
  * The file upload input.
  */
@@ -220,11 +212,13 @@ td .form-managed-file.no-meta .form-managed-file__image-preview {
 }
 
 /**
+ * Remove the default margins of buttons and prevent these to be shrinked.
  * This applies both on the 'no-js' upload button and the remove button.
- * We don't want to let these to be shrinked.
+ * The '.button' selector is doubled for RTL layouts.
  */
-.form-managed-file__main .button {
+.form-managed-file__main .button.button {
   flex: 0 0 auto;
+  margin: 0;
 }
 
 /**
diff --git a/core/themes/claro/css/components/table--file-multiple-widget.css b/core/themes/claro/css/components/table--file-multiple-widget.css
index e24cb0185a..4f3f3558b6 100644
--- a/core/themes/claro/css/components/table--file-multiple-widget.css
+++ b/core/themes/claro/css/components/table--file-multiple-widget.css
@@ -101,7 +101,7 @@
   margin-bottom: 0;
 }
 
-.table-file-multiple-widget .button.button {
+.table-file-multiple-widget .button.button:only-child {
   margin: 0;
 }
 
diff --git a/core/themes/claro/css/components/table--file-multiple-widget.pcss.css b/core/themes/claro/css/components/table--file-multiple-widget.pcss.css
index 436719ec60..d01cabc057 100644
--- a/core/themes/claro/css/components/table--file-multiple-widget.pcss.css
+++ b/core/themes/claro/css/components/table--file-multiple-widget.pcss.css
@@ -49,7 +49,7 @@
   margin-bottom: 0;
 }
 
-.table-file-multiple-widget .button.button {
+.table-file-multiple-widget .button.button:only-child {
   margin: 0;
 }
 
diff --git a/core/themes/claro/css/components/views-exposed-form.css b/core/themes/claro/css/components/views-exposed-form.css
index ca10ce2db8..1ba2cc82a0 100644
--- a/core/themes/claro/css/components/views-exposed-form.css
+++ b/core/themes/claro/css/components/views-exposed-form.css
@@ -6,6 +6,7 @@
  */
 
 /**
+ * @file
  * Visual styles for views exposed form.
  */
 
@@ -54,10 +55,20 @@
 }
 
 /**
- * Use flexbox and some margin resets to make the fields + actions go inline
+ * Use flexbox and some margin resets to make the fields + actions go inline.
+ *
+ * For (at least) Media Library, this file is typically inserted by AJAX add_css
+ * command when the dialog is opened. The AJAX add_css command always adds the
+ * missing-but-required CSS assets to the beginning of the HTML <head>. Because
+ * of this, we cannot rely on the expected loading order of the CSS assets.
+ * This is why we have to double these selectors: we have to get the expected
+ * output even for the Media Library modal.
+ *
+ * @todo Remove double selectors after https://www.drupal.org/node/1461322
+ * has been resolved.
  */
 
-.views-exposed-form {
+.views-exposed-form.views-exposed-form {
   display: flex;
   flex-wrap: wrap;
   align-items: flex-end;
@@ -73,32 +84,32 @@
 rgba(0, 0, 0, 0.1);
 }
 
-.views-exposed-form__item {
+.views-exposed-form__item.views-exposed-form__item {
   margin: 0.75rem 0.5rem 0 0; /* LTR */
 }
 
-[dir="rtl"] .views-exposed-form__item {
+[dir="rtl"] .views-exposed-form__item.views-exposed-form__item {
   margin-right: 0;
   margin-left: 0.5rem;
 }
 
-.views-exposed-form__item--preceding-actions {
+.views-exposed-form__item--preceding-actions.views-exposed-form__item--preceding-actions {
   margin-right: 1rem; /* LTR */
 }
 
-[dir="rtl"] .views-exposed-form__item--preceding-actions {
+[dir="rtl"] .views-exposed-form__item--preceding-actions.views-exposed-form__item--preceding-actions {
   margin-right: 0;
   margin-left: 1rem;
 }
 
-.views-exposed-form__item--actions .button {
+.views-exposed-form__item--actions.views-exposed-form__item--actions .button {
   margin-bottom: 0;
 }
 
-.views-exposed-form__item--actions .button:last-child {
+.views-exposed-form__item--actions.views-exposed-form__item--actions .button:last-child {
   margin-right: 0;
 }
 
-[dir="rtl"] .views-exposed-form__item--actions:last-child {
+[dir="rtl"] .views-exposed-form__item--actions.views-exposed-form__item--actions:last-child {
   margin-left: 0;
 }
diff --git a/core/themes/claro/css/components/views-exposed-form.pcss.css b/core/themes/claro/css/components/views-exposed-form.pcss.css
index 9baeb63b56..994163730d 100644
--- a/core/themes/claro/css/components/views-exposed-form.pcss.css
+++ b/core/themes/claro/css/components/views-exposed-form.pcss.css
@@ -1,14 +1,25 @@
 /**
+ * @file
  * Visual styles for views exposed form.
  */
 
 @import "../base/variables.pcss.css";
 
 /**
- * Use flexbox and some margin resets to make the fields + actions go inline
+ * Use flexbox and some margin resets to make the fields + actions go inline.
+ *
+ * For (at least) Media Library, this file is typically inserted by AJAX add_css
+ * command when the dialog is opened. The AJAX add_css command always adds the
+ * missing-but-required CSS assets to the beginning of the HTML <head>. Because
+ * of this, we cannot rely on the expected loading order of the CSS assets.
+ * This is why we have to double these selectors: we have to get the expected
+ * output even for the Media Library modal.
+ *
+ * @todo Remove double selectors after https://www.drupal.org/node/1461322
+ * has been resolved.
  */
 
-.views-exposed-form {
+.views-exposed-form.views-exposed-form {
   display: flex;
   flex-wrap: wrap;
   align-items: flex-end;
@@ -21,29 +32,29 @@
   box-shadow: var(--details-box-shadow);
 }
 
-.views-exposed-form__item {
+.views-exposed-form__item.views-exposed-form__item {
   margin: var(--space-s) var(--space-xs) 0 0; /* LTR */
 }
-[dir="rtl"] .views-exposed-form__item {
+[dir="rtl"] .views-exposed-form__item.views-exposed-form__item {
   margin-right: 0;
   margin-left: var(--space-xs);
 }
 
-.views-exposed-form__item--preceding-actions {
+.views-exposed-form__item--preceding-actions.views-exposed-form__item--preceding-actions {
   margin-right: var(--space-m); /* LTR */
 }
-[dir="rtl"] .views-exposed-form__item--preceding-actions {
+[dir="rtl"] .views-exposed-form__item--preceding-actions.views-exposed-form__item--preceding-actions {
   margin-right: 0;
   margin-left: var(--space-m);
 }
 
-.views-exposed-form__item--actions .button {
+.views-exposed-form__item--actions.views-exposed-form__item--actions .button {
   margin-bottom: 0;
 }
 
-.views-exposed-form__item--actions .button:last-child {
+.views-exposed-form__item--actions.views-exposed-form__item--actions .button:last-child {
   margin-right: 0;
 }
-[dir="rtl"] .views-exposed-form__item--actions:last-child {
+[dir="rtl"] .views-exposed-form__item--actions.views-exposed-form__item--actions:last-child {
   margin-left: 0;
 }
diff --git a/core/themes/claro/css/theme/media-library.css b/core/themes/claro/css/theme/media-library.css
new file mode 100644
index 0000000000..d4f7b2a7ec
--- /dev/null
+++ b/core/themes/claro/css/theme/media-library.css
@@ -0,0 +1,773 @@
+/*
+ * DO NOT EDIT THIS FILE.
+ * See the following change record for more information,
+ * https://www.drupal.org/node/2815083
+ * @preserve
+ */
+
+/**
+ * @file media-library.pcss.css
+
+ * Styling for Media Library.
+ */
+
+.media-library-wrapper {
+  display: flex;
+  margin: -1em;
+}
+
+/**
+ * @todo Reuse or build on vertical tabs styling for the media library menu.
+ *   https://www.drupal.org/project/drupal/issues/3023767
+ */
+
+.media-library-menu {
+  display: block;
+  width: 600px;
+  max-width: 20%;
+  margin: 0; /* LTR */
+  padding: 0;
+  border-bottom: 1px solid #ccc;
+  background-color: #e6e5e1;
+  line-height: 1;
+}
+
+[dir="rtl"] .media-library-menu {
+  margin: 0;
+}
+
+/**
+ * @todo Use a class instead of the li element.
+ *   https://www.drupal.org/project/drupal/issues/3029227
+ */
+
+.media-library-menu li {
+  display: block;
+  padding: 0;
+  list-style: none;
+}
+
+.media-library-menu__link {
+  position: relative;
+  display: block;
+  box-sizing: border-box;
+  padding: 15px;
+  text-decoration: none;
+  border-bottom: 1px solid #b3b2ad;
+  background-color: #f2f2f0;
+  text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
+}
+
+.media-library-menu__link:active,
+.media-library-menu__link:hover,
+.media-library-menu__link:focus {
+  background: #fcfcfa;
+  text-shadow: none;
+}
+
+.media-library-menu__link:focus,
+.media-library-menu__link:active {
+  outline: none;
+}
+
+.media-library-menu__link.active {
+  z-index: 1;
+  margin-right: -1px; /* LTR */
+  color: #000;
+  border-right: 1px solid #fcfcfa; /* LTR */
+  border-bottom: 1px solid #b3b2ad;
+  background-color: #fff;
+  box-shadow: 0 5px 5px -5px hsla(0, 0%, 0%, 0.3);
+}
+
+[dir="rtl"] .media-library-menu__link.active {
+  margin-right: 0;
+  margin-left: -1px;
+  border-right: 0;
+  border-left: 1px solid #fcfcfa;
+}
+
+.media-library-content {
+  width: 100%;
+  padding: 1em;
+  border-left: 1px solid #b3b2ad; /* LTR */
+  outline: none;
+}
+
+[dir="rtl"] .media-library-content {
+  border-right: 1px solid #b3b2ad;
+  border-left: 0;
+}
+
+/* Generic media add form styles. */
+
+.media-library-add-form--without-input .form-item {
+  margin: 0 0 1em;
+}
+
+/**
+ * Remove outline from added media list.
+ *
+ * The added media list receives focus after adding new media, but since it is
+ * not an interactive element, it does not need an outline.
+ */
+
+.media-library-add-form__added-media {
+  margin: 0;
+  padding: 0;
+  outline: none;
+}
+
+.media-library-add-form__input-wrapper {
+  padding: 16px;
+  border: 1px solid #bfbfbf;
+  border-radius: 2px;
+  background: #fcfcfa;
+}
+
+/* Style the media add upload form. */
+
+.media-library-add-form--upload.media-library-add-form--without-input .form-item-upload {
+  margin-bottom: 0;
+}
+
+.media-library-add-form .file-upload-help {
+  margin: 8px 0 0;
+}
+
+/* Style the media add oEmbed form. */
+
+.media-library-add-form--oembed .media-library-add-form__input-wrapper {
+  display: flex;
+}
+
+@media screen and (max-width: 37.5em) {
+  .media-library-add-form--oembed .media-library-add-form__input-wrapper {
+    display: block;
+  }
+}
+
+.media-library-add-form--oembed.media-library-add-form--without-input .form-item-url {
+  margin-bottom: 0;
+}
+
+.media-library-add-form-oembed-url {
+  width: 100%;
+}
+
+/**
+ * @todo Remove .button when styles are moved to the seven theme in
+ *   https://www.drupal.org/project/drupal/issues/2980769
+ */
+
+.button.media-library-add-form-oembed-submit {
+  align-self: center;
+}
+
+/* Media add form selection styles. */
+
+.media-library-add-form__selected-media {
+  margin-top: 1em;
+}
+
+/* Change to padding to account for the negative margin for flex grid. */
+
+.media-library-add-form__selected-media .details-wrapper {
+  padding: 0 10px 1em 10px;
+}
+
+.media-library-add-form__selected-media .media-library-item .field--name-thumbnail img {
+  height: 100px;
+}
+
+/* Generic media library view styles. */
+
+.media-library-select-all {
+  flex-basis: 100%;
+  width: 100%;
+  margin: 10px 8px;
+}
+
+.media-library-select-all input {
+  margin-right: 10px;
+}
+
+[dir="rtl"] .media-library-select-all input {
+  margin-left: 10px;
+}
+
+.media-library-views-form,
+.media-library-selection,
+.media-library-add-form__selected-media .details-wrapper,
+.media-library-views-form__bulk_form,
+.media-library-view .form--inline {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.media-library-views-form > .form-actions {
+  flex-basis: 100%;
+}
+
+.media-library-views-form__header {
+  flex-basis: 100%;
+}
+
+.media-library-views-form__header .form-item {
+  margin-right: 8px; /* @TODO RTL? */
+}
+
+.media-library-views-form__rows {
+  display: flex;
+  flex-wrap: wrap;
+  flex-basis: 100%;
+  margin: 0 -8px;
+}
+
+/**
+ * Override the table display of the visually hidden labels.
+ *
+ * The width, height and overflow properties in the styles for the
+ * .visually-hidden class do not work correctly if the element has a table
+ * display.
+ */
+
+.media-library-item label {
+  display: inline-block;
+}
+
+/* Media library widget view styles. */
+
+.media-library-wrapper .media-library-view {
+  position: relative;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+
+.media-library-wrapper .view-header {
+  align-self: flex-end;
+  margin: 1em 0;
+  text-align: right; /* LTR */
+}
+
+[dir="rtl"] .media-library-wrapper .view-header {
+  text-align: left;
+}
+
+.media-library-wrapper .media-library-view .view-filters,
+.media-library-wrapper .media-library-view .view-content {
+  flex: 0 0 100%;
+}
+
+.media-library-wrapper .views-display-link {
+  margin: 0;
+  padding-left: 22px; /* LTR */
+  color: #333;
+  font-size: 15px;
+  line-height: 16px;
+}
+
+[dir="rtl"] .media-library-wrapper .views-display-link {
+  padding-right: 22px;
+  padding-left: 0;
+}
+
+.media-library-wrapper .views-display-link.is-active {
+  font-weight: bold;
+}
+
+.media-library-wrapper .views-display-link-widget {
+  margin-right: 15px;
+  background: url(../../../../misc/icons/333333/grid.svg) left 0 no-repeat; /* LTR */
+}
+
+[dir="rtl"] .media-library-wrapper .views-display-link-widget {
+  background-position: right 0;
+}
+
+.media-library-wrapper .views-display-link-widget_table {
+  background: url(../../../../misc/icons/333333/table.svg) left 0 no-repeat; /* LTR */
+}
+
+[dir="rtl"] .media-library-wrapper .views-display-link-widget_table {
+  background-position: right 0;
+}
+
+/**
+ * Style the media library grid items.
+ */
+
+.media-library-item {
+  position: relative;
+}
+
+/**
+* The media library item container receives screen reader focus when items are
+* removed. Since it is not an interactive element, it does not need an
+* outline.
+*/
+
+.media-library-item--grid {
+  justify-content: center;
+  box-sizing: border-box;
+  width: 50%;
+  padding: 8px;
+  vertical-align: top;
+  outline: none;
+  background: #fff;
+}
+
+.media-library-item--grid:before {
+  position: absolute;
+  top: 7px;
+  left: 7px;
+  width: calc(100% - 16px);
+  height: calc(100% - 16px);
+  content: "";
+  transition: border-color 0.2s, color 0.2s, background 0.2s;
+  pointer-events: none;
+  border: 1px solid #dbdbdb;
+}
+
+/* Media library widget weight field styles. */
+
+.media-library-item--grid .form-item {
+  margin: 0.75em;
+}
+
+/* The selected items in the add form should be shown a bit smaller. */
+
+.media-library-add-form__selected-media .media-library-item--small {
+  width: 33.3%;
+}
+
+.media-library-widget-modal .ui-dialog-buttonpane {
+  display: flex;
+  align-items: center;
+}
+
+.media-library-widget-modal .ui-dialog-buttonpane .form-actions {
+  flex: 1;
+}
+
+/**
+ * By default, the dialog is too narrow to be usable.
+ * @see Drupal.ckeditor.openDialog()
+ */
+
+.ui-dialog--narrow.media-library-widget-modal {
+  max-width: 75%;
+}
+
+@media screen and (min-width: 45em) {
+  .media-library-item--grid {
+    width: 33.3%;
+  }
+
+  /* Change the width for the modal and widget since there is less space. */
+  .media-library-widget-modal .media-library-item--grid,
+  .media-library-selection .media-library-item--grid {
+    width: 50%;
+  }
+
+  /* The selected items in the add form should be shown a bit smaller. */
+  .media-library-add-form__selected-media .media-library-item--small {
+    width: 25%;
+  }
+}
+
+@media screen and (min-width: 60em) {
+  .media-library-item--grid {
+    width: 25%;
+  }
+
+  /* Change the width for the modal and widget since there is less space. */
+  .media-library-widget-modal .media-library-item--grid,
+  .media-library-selection .media-library-item--grid {
+    width: 33.3%;
+  }
+
+  /* The selected items in the add form should be shown a bit smaller. */
+  .media-library-add-form__selected-media .media-library-item--small {
+    width: 16.6%;
+  }
+}
+
+@media screen and (min-width: 77em) {
+  .media-library-item--grid {
+    width: 16.6%;
+  }
+
+  /* Change the width for the modal and widget since there is less space. */
+  .media-library-widget-modal .media-library-item--grid,
+  .media-library-selection .media-library-item--grid {
+    width: 25%;
+  }
+
+  /* The selected items in the add form should be shown a bit smaller. */
+  .media-library-add-form__selected-media .media-library-item--small {
+    width: 16.6%;
+  }
+}
+
+.media-library-item--grid .field--name-thumbnail {
+  overflow: hidden;
+  text-align: center;
+  background-color: #ebebeb;
+}
+
+.media-library-item--grid .field--name-thumbnail img {
+  height: 180px;
+  -o-object-fit: contain;
+  object-fit: contain;
+  -o-object-position: center center;
+  object-position: center center;
+}
+
+.media-library-item--grid.is-hover:before,
+.media-library-item--grid.checked:before,
+.media-library-item--grid.is-focus:before {
+  top: 5px;
+  left: 5px;
+  border-width: 3px;
+  border-color: #40b6ff;
+  border-radius: 3px;
+}
+
+.media-library-item--grid.checked:before {
+  border-color: #0076c0;
+}
+
+.media-library-item__click-to-select-checkbox {
+  position: absolute;
+  z-index: 1;
+  top: 16px;
+  left: 16px; /* LTR */
+  display: block;
+}
+
+[dir="rtl"] .media-library-item__click-to-select-checkbox {
+  right: 16px;
+  left: auto;
+}
+
+.media-library-item__click-to-select-checkbox input {
+  width: 20px;
+  height: 20px;
+}
+
+.media-library-item__click-to-select-checkbox .form-item {
+  margin: 0;
+}
+
+.media-library-item__click-to-select-trigger {
+  overflow: hidden;
+  height: 100%;
+  cursor: pointer;
+}
+
+/* Media library item table styles. */
+
+.media-library-item--table img {
+  max-width: 100px;
+  height: auto;
+}
+
+/* Media library entity view display styles. */
+
+.media-library-item__preview {
+  padding-bottom: 34px;
+  cursor: move;
+}
+
+.media-library-item__status {
+  position: absolute;
+  top: 40px;
+  left: 5px; /* LTR */
+  padding: 5px 10px;
+  pointer-events: none;
+  color: #e4e4e4;
+  background: #666;
+  font-size: 12px;
+  font-style: italic;
+}
+
+[dir="rtl"] .media-library-item__status {
+  right: 5px;
+  left: auto;
+}
+
+.media-library-item__attributes {
+  position: absolute;
+  bottom: 0;
+  display: block;
+  overflow: hidden;
+  max-width: calc(100% - 10px);
+  max-height: calc(100% - 50px);
+  padding: 5px;
+  background: white;
+}
+
+.media-library-item__name {
+  font-size: 14px;
+}
+
+.media-library-item__name {
+  display: block;
+  overflow: hidden;
+  margin: 2px;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+.media-library-item__attributes:hover .media-library-item__name,
+.media-library-item--grid.is-focus .media-library-item__name,
+.media-library-item--grid.checked .media-library-item__name {
+  white-space: normal;
+}
+
+.media-library-item__type {
+  color: #696969;
+  font-size: 12px;
+}
+
+.media-library-item--disabled {
+  pointer-events: none;
+  opacity: 0.5;
+}
+
+/* Media library widget styles. */
+
+.media-library-widget {
+  position: relative;
+}
+
+/**
+ * @todo Change to .media-library-open-button when styles are moved to the
+ *   seven theme in https://www.drupal.org/project/drupal/issues/2980769
+ */
+
+.button.media-library-open-button {
+  margin-bottom: 1em;
+  margin-left: 0; /* LTR */
+}
+
+[dir="rtl"] .button.media-library-open-button {
+  margin-right: 0;
+  margin-left: 1em;
+}
+
+.media-library-widget__toggle-weight {
+  position: absolute;
+  top: 5px;
+  right: 5px; /* LTR */
+}
+
+[dir="rtl"] .media-library-widget__toggle-weight {
+  right: auto;
+  left: 5px;
+}
+
+/* Add negative margin for flex grid. */
+
+.media-library-selection {
+  margin: 1em -8px;
+}
+
+/**
+ * Media library widget edit and delete button styles.
+ *
+ * We have to override the .button styles since buttons make heavy use of
+ * background and border property changes.
+ */
+
+.media-library-item__edit,
+.media-library-item__edit:hover,
+.media-library-item__edit:focus,
+.media-library-item__remove,
+.media-library-item__remove:hover,
+.media-library-item__remove:focus,
+.media-library-item__remove.button,
+.media-library-item__remove.button:first-child,
+.media-library-item__remove.button:disabled,
+.media-library-item__remove.button:disabled:active,
+.media-library-item__remove.button:hover,
+.media-library-item__remove.button:focus {
+  position: absolute;
+  z-index: 1;
+  top: 10px;
+  overflow: hidden;
+  width: 21px;
+  height: 21px;
+  margin: 5px;
+  padding: 0;
+  transition: 0.2s border-color;
+  color: transparent;
+  border: 2px solid #ccc;
+  border-radius: 20px;
+  background-size: 13px;
+  text-shadow: none;
+  font-size: 0;
+}
+
+.media-library-item__edit {
+  right: 40px; /* LTR */
+}
+
+[dir="rtl"] .media-library-item__edit {
+  right: auto;
+  left: 40px;
+}
+
+.media-library-item__remove {
+  right: 10px; /* LTR */
+}
+
+[dir="rtl"] .media-library-item__remove {
+  right: auto;
+  left: 10px;
+}
+
+.media-library-item__edit {
+  background: url("../../../../misc/icons/787878/pencil.svg") #fff center no-repeat;
+  background-size: 13px;
+}
+
+.media-library-item__remove,
+.media-library-item__remove.button,
+.media-library-item__remove.button:first-child,
+.media-library-item__remove.button:disabled,
+.media-library-item__remove.button:disabled:active,
+.media-library-item__remove.button:hover,
+.media-library-item__remove.button:focus {
+  background: url("../../../../misc/icons/787878/ex.svg") #fff center no-repeat;
+  background-size: 13px;
+}
+
+.media-library-item__edit:hover,
+.media-library-item__edit:focus,
+.media-library-item__remove:hover,
+.media-library-item__remove:focus,
+.media-library-item__remove.button:hover,
+.media-library-item__remove.button:focus,
+.media-library-item__remove.button:disabled:active {
+  border-color: #40b6ff;
+}
+
+/**
+ * Style the added media item container.
+ *
+ * The added media container receives screen reader focus since it is has the
+ * role 'listitem'. Since it is not an interactive element, it does not need
+ * an outline.
+ */
+
+.media-library-add-form__media {
+  position: relative;
+  display: flex;
+  padding: 1em 0;
+  border-bottom: 1px solid #c0c0c0;
+  outline: none;
+}
+
+/* Do not show the top padding for the first item. */
+
+.media-library-add-form__media:first-child {
+  padding-top: 0;
+}
+
+/**
+ * Change the position of the remove button for the first item.
+ *
+ * The first item doesn't have a top padding, change the location of the remove
+ * button as well.
+ */
+
+.media-library-add-form__media:first-child .media-library-add-form__remove-button[type="submit"] {
+  top: 5px;
+}
+
+/* Do not show the bottom border and padding for the last item. */
+
+.media-library-add-form__media:last-child {
+  padding-bottom: 0;
+  border-bottom: 0;
+}
+
+.media-library-add-form__preview {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 220px;
+  margin-right: 20px; /* LTR */
+  background: #ebebeb;
+}
+
+[dir="rtl"] .media-library-add-form__preview {
+  margin-right: 0;
+  margin-left: 20px;
+}
+
+/**
+ * @todo Remove [type="submit"] when styles are moved to the seven theme in
+ *   https://www.drupal.org/project/drupal/issues/2980769
+ */
+
+.media-library-add-form__remove-button[type="submit"] {
+  position: absolute;
+  top: 25px;
+  right: 6px; /* LTR */
+  width: auto;
+  margin: 0;
+  padding: 2px 20px 2px 2px; /* LTR */
+  text-transform: lowercase;
+  color: transparent;
+  border: 0;
+  border-radius: 0;
+  background: transparent url(../../../../misc/icons/787878/ex.svg) right 2px no-repeat; /* LTR */
+  font-weight: normal;
+  line-height: 16px;
+}
+
+[dir="rtl"] .media-library-add-form__remove-button[type="submit"] {
+  right: auto;
+  left: 13px;
+  padding: 2px 2px 2px 20px;
+  background-position: left 2px;
+}
+
+.media-library-add-form__remove-button:focus,
+.media-library-add-form__remove-button.button:disabled,
+.media-library-add-form__remove-button.button:disabled:active,
+.media-library-add-form__remove-button.button:focus {
+  color: #787878;
+  border: 0;
+  background: transparent url(../../../../misc/icons/787878/ex.svg) right 2px no-repeat; /* LTR */
+}
+
+[dir="rtl"] .media-library-add-form__remove-button:focus,
+[dir="rtl"] .media-library-add-form__remove-button.button:disabled,
+[dir="rtl"] .media-library-add-form__remove-button.button:disabled:active,
+[dir="rtl"] .media-library-add-form__remove-button.button:focus {
+  background-position: left 2px;
+}
+
+.media-library-add-form__remove-button:hover,
+.media-library-add-form__remove-button.button:hover {
+  color: #e00;
+  border: 0;
+  background: transparent url(../../../../misc/icons/ee0000/ex.svg) right 2px no-repeat; /* LTR */
+  box-shadow: none;
+}
+
+[dir="rtl"] .media-library-add-form__remove-button:hover,
+[dir="rtl"] .media-library-add-form__remove-button.button:hover {
+  background-position: left 2px;
+}
+
+/* @todo Remove in https://www.drupal.org/project/drupal/issues/3064914 */
+
+.views-live-preview .media-library-view div.views-row + div.views-row {
+  margin-top: 0;
+}
diff --git a/core/themes/claro/css/theme/media-library.pcss.css b/core/themes/claro/css/theme/media-library.pcss.css
new file mode 100644
index 0000000000..6af72d7a1a
--- /dev/null
+++ b/core/themes/claro/css/theme/media-library.pcss.css
@@ -0,0 +1,714 @@
+/**
+ * @file media-library.pcss.css
+
+ * Styling for Media Library.
+ */
+
+.media-library-wrapper {
+  display: flex;
+  margin: -1em;
+}
+
+/**
+ * @todo Reuse or build on vertical tabs styling for the media library menu.
+ *   https://www.drupal.org/project/drupal/issues/3023767
+ */
+.media-library-menu {
+  display: block;
+  width: 600px;
+  max-width: 20%;
+  margin: 0; /* LTR */
+  padding: 0;
+  border-bottom: 1px solid #ccc;
+  background-color: #e6e5e1;
+  line-height: 1;
+}
+[dir="rtl"] .media-library-menu {
+  margin: 0;
+}
+
+/**
+ * @todo Use a class instead of the li element.
+ *   https://www.drupal.org/project/drupal/issues/3029227
+ */
+.media-library-menu li {
+  display: block;
+  padding: 0;
+  list-style: none;
+}
+
+.media-library-menu__link {
+  position: relative;
+  display: block;
+  box-sizing: border-box;
+  padding: 15px;
+  text-decoration: none;
+  border-bottom: 1px solid #b3b2ad;
+  background-color: #f2f2f0;
+  text-shadow: 0 1px hsla(0, 0%, 100%, 0.6);
+}
+
+.media-library-menu__link:active,
+.media-library-menu__link:hover,
+.media-library-menu__link:focus {
+  background: #fcfcfa;
+  text-shadow: none;
+}
+
+.media-library-menu__link:focus,
+.media-library-menu__link:active {
+  outline: none;
+}
+
+.media-library-menu__link.active {
+  z-index: 1;
+  margin-right: -1px; /* LTR */
+  color: #000;
+  border-right: 1px solid #fcfcfa; /* LTR */
+  border-bottom: 1px solid #b3b2ad;
+  background-color: #fff;
+  box-shadow: 0 5px 5px -5px hsla(0, 0%, 0%, 0.3);
+}
+[dir="rtl"] .media-library-menu__link.active {
+  margin-right: 0;
+  margin-left: -1px;
+  border-right: 0;
+  border-left: 1px solid #fcfcfa;
+}
+
+.media-library-content {
+  width: 100%;
+  padding: 1em;
+  border-left: 1px solid #b3b2ad; /* LTR */
+  outline: none;
+}
+[dir="rtl"] .media-library-content {
+  border-right: 1px solid #b3b2ad;
+  border-left: 0;
+}
+
+/* Generic media add form styles. */
+.media-library-add-form--without-input .form-item {
+  margin: 0 0 1em;
+}
+
+/**
+ * Remove outline from added media list.
+ *
+ * The added media list receives focus after adding new media, but since it is
+ * not an interactive element, it does not need an outline.
+ */
+.media-library-add-form__added-media {
+  margin: 0;
+  padding: 0;
+  outline: none;
+}
+
+.media-library-add-form__input-wrapper {
+  padding: 16px;
+  border: 1px solid #bfbfbf;
+  border-radius: 2px;
+  background: #fcfcfa;
+}
+
+/* Style the media add upload form. */
+.media-library-add-form--upload.media-library-add-form--without-input .form-item-upload {
+  margin-bottom: 0;
+}
+
+.media-library-add-form .file-upload-help {
+  margin: 8px 0 0;
+}
+
+/* Style the media add oEmbed form. */
+.media-library-add-form--oembed .media-library-add-form__input-wrapper {
+  display: flex;
+}
+
+@media screen and (max-width: 37.5em) {
+  .media-library-add-form--oembed .media-library-add-form__input-wrapper {
+    display: block;
+  }
+}
+
+.media-library-add-form--oembed.media-library-add-form--without-input .form-item-url {
+  margin-bottom: 0;
+}
+
+.media-library-add-form-oembed-url {
+  width: 100%;
+}
+
+/**
+ * @todo Remove .button when styles are moved to the seven theme in
+ *   https://www.drupal.org/project/drupal/issues/2980769
+ */
+.button.media-library-add-form-oembed-submit {
+  align-self: center;
+}
+
+/* Media add form selection styles. */
+.media-library-add-form__selected-media {
+  margin-top: 1em;
+}
+
+/* Change to padding to account for the negative margin for flex grid. */
+.media-library-add-form__selected-media .details-wrapper {
+  padding: 0 10px 1em 10px;
+}
+
+.media-library-add-form__selected-media .media-library-item .field--name-thumbnail img {
+  height: 100px;
+}
+
+/* Generic media library view styles. */
+.media-library-select-all {
+  flex-basis: 100%;
+  width: 100%;
+  margin: 10px 8px;
+}
+.media-library-select-all input {
+  margin-right: 10px;
+}
+[dir="rtl"] .media-library-select-all input {
+  margin-left: 10px;
+}
+
+.media-library-views-form,
+.media-library-selection,
+.media-library-add-form__selected-media .details-wrapper,
+.media-library-views-form__bulk_form,
+.media-library-view .form--inline {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.media-library-views-form > .form-actions {
+  flex-basis: 100%;
+}
+
+.media-library-views-form__header {
+  flex-basis: 100%;
+}
+
+.media-library-views-form__header .form-item {
+  margin-right: 8px; /* @TODO RTL? */
+}
+
+.media-library-views-form__rows {
+  display: flex;
+  flex-wrap: wrap;
+  flex-basis: 100%;
+  margin: 0 -8px;
+}
+
+/**
+ * Override the table display of the visually hidden labels.
+ *
+ * The width, height and overflow properties in the styles for the
+ * .visually-hidden class do not work correctly if the element has a table
+ * display.
+ */
+.media-library-item label {
+  display: inline-block;
+}
+
+/* Media library widget view styles. */
+.media-library-wrapper .media-library-view {
+  position: relative;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+
+.media-library-wrapper .view-header {
+  align-self: flex-end;
+  margin: 1em 0;
+  text-align: right; /* LTR */
+}
+[dir="rtl"] .media-library-wrapper .view-header {
+  text-align: left;
+}
+
+.media-library-wrapper .media-library-view .view-filters,
+.media-library-wrapper .media-library-view .view-content {
+  flex: 0 0 100%;
+}
+
+.media-library-wrapper .views-display-link {
+  margin: 0;
+  padding-left: 22px; /* LTR */
+  color: #333;
+  font-size: 15px;
+  line-height: 16px;
+}
+[dir="rtl"] .media-library-wrapper .views-display-link {
+  padding-right: 22px;
+  padding-left: 0;
+}
+
+.media-library-wrapper .views-display-link.is-active {
+  font-weight: bold;
+}
+
+.media-library-wrapper .views-display-link-widget {
+  margin-right: 15px;
+  background: url(../../../../misc/icons/333333/grid.svg) left 0 no-repeat; /* LTR */
+}
+[dir="rtl"] .media-library-wrapper .views-display-link-widget {
+  background-position: right 0;
+}
+
+.media-library-wrapper .views-display-link-widget_table {
+  background: url(../../../../misc/icons/333333/table.svg) left 0 no-repeat; /* LTR */
+}
+[dir="rtl"] .media-library-wrapper .views-display-link-widget_table {
+  background-position: right 0;
+}
+
+/**
+ * Style the media library grid items.
+ */
+.media-library-item {
+  position: relative;
+}
+
+/**
+* The media library item container receives screen reader focus when items are
+* removed. Since it is not an interactive element, it does not need an
+* outline.
+*/
+.media-library-item--grid {
+  justify-content: center;
+  box-sizing: border-box;
+  width: 50%;
+  padding: 8px;
+  vertical-align: top;
+  outline: none;
+  background: #fff;
+}
+
+.media-library-item--grid:before {
+  position: absolute;
+  top: 7px;
+  left: 7px;
+  width: calc(100% - 16px);
+  height: calc(100% - 16px);
+  content: "";
+  transition: border-color 0.2s, color 0.2s, background 0.2s;
+  pointer-events: none;
+  border: 1px solid #dbdbdb;
+}
+
+/* Media library widget weight field styles. */
+.media-library-item--grid .form-item {
+  margin: 0.75em;
+}
+
+/* The selected items in the add form should be shown a bit smaller. */
+.media-library-add-form__selected-media .media-library-item--small {
+  width: 33.3%;
+}
+
+.media-library-widget-modal .ui-dialog-buttonpane {
+  display: flex;
+  align-items: center;
+}
+
+.media-library-widget-modal .ui-dialog-buttonpane .form-actions {
+  flex: 1;
+}
+
+/**
+ * By default, the dialog is too narrow to be usable.
+ * @see Drupal.ckeditor.openDialog()
+ */
+.ui-dialog--narrow.media-library-widget-modal {
+  max-width: 75%;
+}
+
+@media screen and (min-width: 45em) {
+  .media-library-item--grid {
+    width: 33.3%;
+  }
+
+  /* Change the width for the modal and widget since there is less space. */
+  .media-library-widget-modal .media-library-item--grid,
+  .media-library-selection .media-library-item--grid {
+    width: 50%;
+  }
+
+  /* The selected items in the add form should be shown a bit smaller. */
+  .media-library-add-form__selected-media .media-library-item--small {
+    width: 25%;
+  }
+}
+
+@media screen and (min-width: 60em) {
+  .media-library-item--grid {
+    width: 25%;
+  }
+
+  /* Change the width for the modal and widget since there is less space. */
+  .media-library-widget-modal .media-library-item--grid,
+  .media-library-selection .media-library-item--grid {
+    width: 33.3%;
+  }
+
+  /* The selected items in the add form should be shown a bit smaller. */
+  .media-library-add-form__selected-media .media-library-item--small {
+    width: 16.6%;
+  }
+}
+
+@media screen and (min-width: 77em) {
+  .media-library-item--grid {
+    width: 16.6%;
+  }
+
+  /* Change the width for the modal and widget since there is less space. */
+  .media-library-widget-modal .media-library-item--grid,
+  .media-library-selection .media-library-item--grid {
+    width: 25%;
+  }
+
+  /* The selected items in the add form should be shown a bit smaller. */
+  .media-library-add-form__selected-media .media-library-item--small {
+    width: 16.6%;
+  }
+}
+
+.media-library-item--grid .field--name-thumbnail {
+  overflow: hidden;
+  text-align: center;
+  background-color: #ebebeb;
+}
+
+.media-library-item--grid .field--name-thumbnail img {
+  height: 180px;
+  object-fit: contain;
+  object-position: center center;
+}
+
+.media-library-item--grid.is-hover:before,
+.media-library-item--grid.checked:before,
+.media-library-item--grid.is-focus:before {
+  top: 5px;
+  left: 5px;
+  border-width: 3px;
+  border-color: #40b6ff;
+  border-radius: 3px;
+}
+
+.media-library-item--grid.checked:before {
+  border-color: #0076c0;
+}
+
+.media-library-item__click-to-select-checkbox {
+  position: absolute;
+  z-index: 1;
+  top: 16px;
+  left: 16px; /* LTR */
+  display: block;
+}
+[dir="rtl"] .media-library-item__click-to-select-checkbox {
+  right: 16px;
+  left: auto;
+}
+
+.media-library-item__click-to-select-checkbox input {
+  width: 20px;
+  height: 20px;
+}
+
+.media-library-item__click-to-select-checkbox .form-item {
+  margin: 0;
+}
+
+.media-library-item__click-to-select-trigger {
+  overflow: hidden;
+  height: 100%;
+  cursor: pointer;
+}
+
+/* Media library item table styles. */
+.media-library-item--table img {
+  max-width: 100px;
+  height: auto;
+}
+
+/* Media library entity view display styles. */
+.media-library-item__preview {
+  padding-bottom: 34px;
+  cursor: move;
+}
+
+.media-library-item__status {
+  position: absolute;
+  top: 40px;
+  left: 5px; /* LTR */
+  padding: 5px 10px;
+  pointer-events: none;
+  color: #e4e4e4;
+  background: #666;
+  font-size: 12px;
+  font-style: italic;
+}
+[dir="rtl"] .media-library-item__status {
+  right: 5px;
+  left: auto;
+}
+
+.media-library-item__attributes {
+  position: absolute;
+  bottom: 0;
+  display: block;
+  overflow: hidden;
+  max-width: calc(100% - 10px);
+  max-height: calc(100% - 50px);
+  padding: 5px;
+  background: white;
+}
+
+.media-library-item__name {
+  font-size: 14px;
+}
+
+.media-library-item__name {
+  display: block;
+  overflow: hidden;
+  margin: 2px;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+
+.media-library-item__attributes:hover .media-library-item__name,
+.media-library-item--grid.is-focus .media-library-item__name,
+.media-library-item--grid.checked .media-library-item__name {
+  white-space: normal;
+}
+
+.media-library-item__type {
+  color: #696969;
+  font-size: 12px;
+}
+
+.media-library-item--disabled {
+  pointer-events: none;
+  opacity: 0.5;
+}
+
+/* Media library widget styles. */
+.media-library-widget {
+  position: relative;
+}
+
+/**
+ * @todo Change to .media-library-open-button when styles are moved to the
+ *   seven theme in https://www.drupal.org/project/drupal/issues/2980769
+ */
+.button.media-library-open-button {
+  margin-bottom: 1em;
+  margin-left: 0; /* LTR */
+}
+[dir="rtl"] .button.media-library-open-button {
+  margin-right: 0;
+  margin-left: 1em;
+}
+
+.media-library-widget__toggle-weight {
+  position: absolute;
+  top: 5px;
+  right: 5px; /* LTR */
+}
+[dir="rtl"] .media-library-widget__toggle-weight {
+  right: auto;
+  left: 5px;
+}
+
+/* Add negative margin for flex grid. */
+.media-library-selection {
+  margin: 1em -8px;
+}
+
+/**
+ * Media library widget edit and delete button styles.
+ *
+ * We have to override the .button styles since buttons make heavy use of
+ * background and border property changes.
+ */
+.media-library-item__edit,
+.media-library-item__edit:hover,
+.media-library-item__edit:focus,
+.media-library-item__remove,
+.media-library-item__remove:hover,
+.media-library-item__remove:focus,
+.media-library-item__remove.button,
+.media-library-item__remove.button:first-child,
+.media-library-item__remove.button:disabled,
+.media-library-item__remove.button:disabled:active,
+.media-library-item__remove.button:hover,
+.media-library-item__remove.button:focus {
+  position: absolute;
+  z-index: 1;
+  top: 10px;
+  overflow: hidden;
+  width: 21px;
+  height: 21px;
+  margin: 5px;
+  padding: 0;
+  transition: 0.2s border-color;
+  color: transparent;
+  border: 2px solid #ccc;
+  border-radius: 20px;
+  background-size: 13px;
+  text-shadow: none;
+  font-size: 0;
+}
+
+.media-library-item__edit {
+  right: 40px; /* LTR */
+}
+[dir="rtl"] .media-library-item__edit {
+  right: auto;
+  left: 40px;
+}
+
+.media-library-item__remove {
+  right: 10px; /* LTR */
+}
+[dir="rtl"] .media-library-item__remove {
+  right: auto;
+  left: 10px;
+}
+
+.media-library-item__edit {
+  background: url("../../../../misc/icons/787878/pencil.svg") #fff center no-repeat;
+  background-size: 13px;
+}
+.media-library-item__remove,
+.media-library-item__remove.button,
+.media-library-item__remove.button:first-child,
+.media-library-item__remove.button:disabled,
+.media-library-item__remove.button:disabled:active,
+.media-library-item__remove.button:hover,
+.media-library-item__remove.button:focus {
+  background: url("../../../../misc/icons/787878/ex.svg") #fff center no-repeat;
+  background-size: 13px;
+}
+.media-library-item__edit:hover,
+.media-library-item__edit:focus,
+.media-library-item__remove:hover,
+.media-library-item__remove:focus,
+.media-library-item__remove.button:hover,
+.media-library-item__remove.button:focus,
+.media-library-item__remove.button:disabled:active {
+  border-color: #40b6ff;
+}
+
+/**
+ * Style the added media item container.
+ *
+ * The added media container receives screen reader focus since it is has the
+ * role 'listitem'. Since it is not an interactive element, it does not need
+ * an outline.
+ */
+.media-library-add-form__media {
+  position: relative;
+  display: flex;
+  padding: 1em 0;
+  border-bottom: 1px solid #c0c0c0;
+  outline: none;
+}
+
+/* Do not show the top padding for the first item. */
+.media-library-add-form__media:first-child {
+  padding-top: 0;
+}
+
+/**
+ * Change the position of the remove button for the first item.
+ *
+ * The first item doesn't have a top padding, change the location of the remove
+ * button as well.
+ */
+.media-library-add-form__media:first-child .media-library-add-form__remove-button[type="submit"] {
+  top: 5px;
+}
+
+/* Do not show the bottom border and padding for the last item. */
+.media-library-add-form__media:last-child {
+  padding-bottom: 0;
+  border-bottom: 0;
+}
+
+.media-library-add-form__preview {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 220px;
+  margin-right: 20px; /* LTR */
+  background: #ebebeb;
+}
+[dir="rtl"] .media-library-add-form__preview {
+  margin-right: 0;
+  margin-left: 20px;
+}
+
+/**
+ * @todo Remove [type="submit"] when styles are moved to the seven theme in
+ *   https://www.drupal.org/project/drupal/issues/2980769
+ */
+.media-library-add-form__remove-button[type="submit"] {
+  position: absolute;
+  top: 25px;
+  right: 6px; /* LTR */
+  width: auto;
+  margin: 0;
+  padding: 2px 20px 2px 2px; /* LTR */
+  text-transform: lowercase;
+  color: transparent;
+  border: 0;
+  border-radius: 0;
+  background: transparent url(../../../../misc/icons/787878/ex.svg) right 2px no-repeat; /* LTR */
+  font-weight: normal;
+  line-height: 16px;
+}
+[dir="rtl"] .media-library-add-form__remove-button[type="submit"] {
+  right: auto;
+  left: 13px;
+  padding: 2px 2px 2px 20px;
+  background-position: left 2px;
+}
+
+.media-library-add-form__remove-button:focus,
+.media-library-add-form__remove-button.button:disabled,
+.media-library-add-form__remove-button.button:disabled:active,
+.media-library-add-form__remove-button.button:focus {
+  color: #787878;
+  border: 0;
+  background: transparent url(../../../../misc/icons/787878/ex.svg) right 2px no-repeat; /* LTR */
+}
+[dir="rtl"] .media-library-add-form__remove-button:focus,
+[dir="rtl"] .media-library-add-form__remove-button.button:disabled,
+[dir="rtl"] .media-library-add-form__remove-button.button:disabled:active,
+[dir="rtl"] .media-library-add-form__remove-button.button:focus {
+  background-position: left 2px;
+}
+
+.media-library-add-form__remove-button:hover,
+.media-library-add-form__remove-button.button:hover {
+  color: #e00;
+  border: 0;
+  background: transparent url(../../../../misc/icons/ee0000/ex.svg) right 2px no-repeat; /* LTR */
+  box-shadow: none;
+}
+[dir="rtl"] .media-library-add-form__remove-button:hover,
+[dir="rtl"] .media-library-add-form__remove-button.button:hover {
+  background-position: left 2px;
+}
+
+/* @todo Remove in https://www.drupal.org/project/drupal/issues/3064914 */
+.views-live-preview .media-library-view div.views-row + div.views-row {
+  margin-top: 0;
+}
diff --git a/core/themes/claro/templates/content-edit/file-managed-file.html.twig b/core/themes/claro/templates/content-edit/file-managed-file.html.twig
index c8341156ee..775a534724 100644
--- a/core/themes/claro/templates/content-edit/file-managed-file.html.twig
+++ b/core/themes/claro/templates/content-edit/file-managed-file.html.twig
@@ -4,14 +4,17 @@
  * Theme override to display a file form widget.
  *
  * Available variables:
- * - element: Form element for the file upload.
+ * - main_items: Main render elements of the file or image widget:
+ *   file name, upload input, upload and remove buttons and hidden inputs.
+ * - data: Other render elements of the image widget like preview, alt or title,
+ *   or the description input and the display checkbox of the file widget.
  * - attributes: HTML attributes for the containing element.
  * - multiple: Whether this widget is the part of a multi-value file widget or
  *   not.
  * - upload: Whether the file upload input is displayed or not.
  * - has_value: true if the widget already contains a file.
- * - has_meta: true when the display checkbox or the description input are
- *   enabled and and are visible.
+ * - has_meta: true when the display checkbox or the description, alt or title
+ *   inputs are enabled and at least one of them is visible.
  *
  * @see template_preprocess_file_managed_file()
  * @see claro_preprocess_file_managed_file()
@@ -27,21 +30,37 @@
     has_meta ? 'has-meta' : 'no-meta',
   ]
 %}
-<div{{ attributes.addClass(classes) }}>
+<div{{ attributes.addClass(classes).removeClass('clearfix') }}>
   <div class="form-managed-file__main">
-    {{ element|without('display', 'description')}}
+    {{ main_items.filename }}
+    {{ main_items|without('filename') }}
   </div>
 
-  {% if has_meta %}
-    <div class="form-managed-file__meta-wrapper">
-      <div class="form-managed-file__meta">
+  {% if has_meta or data.preview %}
+  <div class="form-managed-file__meta-wrapper">
+    <div class="form-managed-file__meta">
+      {% if data.preview %}
+        <div class="form-managed-file__image-preview image-preview">
+          <div class="image-preview__img-wrapper">
+            {{ data.preview }}
+          </div>
+        </div>
+      {% endif %}
+
+      {% if data.description or display or data.alt or data.title %}
         <div class="form-managed-file__meta-items">
-          {{ element.description }}
+          {{ data.description }}
           {% if display %}
-            {{ element.display }}
+            {{ data.display }}
           {% endif %}
+          {{ data.alt }}
+          {{ data.title }}
         </div>
-      </div>
+      {% endif %}
     </div>
+  </div>
   {% endif %}
+
+  {# Every third-party addition will be rendered here. #}
+  {{ data|without('preview', 'alt', 'title', 'description', 'display') }}
 </div>
diff --git a/core/themes/claro/templates/content-edit/image-widget.html.twig b/core/themes/claro/templates/content-edit/image-widget.html.twig
index 87fa3b4a21..3b3bded032 100644
--- a/core/themes/claro/templates/content-edit/image-widget.html.twig
+++ b/core/themes/claro/templates/content-edit/image-widget.html.twig
@@ -4,56 +4,23 @@
  * Theme override for an image field widget.
  *
  * Available variables:
+ * - main_items: Main render elements of the image widget:
+ *   file name, upload input, upload and remove buttons and hidden inputs.
+ * - data: Other render elements of the image widget like preview, alt or title.
  * - attributes: HTML attributes for the containing element.
- * - data: Render elements of the image widget.
  * - multiple: Whether this widget is the part of a multi-value file widget or
  *   not.
  * - upload: Whether the file upload input is displayed or not.
- * - has_value: true if the widget already contains an image.
- * - has_meta: true when one of the title or alt inputs are enabled and visible.
+ * - has_value: true if the widget already contains a file.
+ * - has_meta: true when at least one of the alt or title inputs is enabled and
+ *   visible.
  *
  * @see template_preprocess_image_widget()
  * @see stable_preprocess_image_widget()
  * @see claro_preprocess_image_widget()
  */
 #}
-{%
-  set classes = [
-    'form-managed-file--image',
-    multiple ? 'is-multiple' : 'is-single',
-    upload ? 'has-upload' : 'no-upload',
-    has_value ? 'has-value' : 'no-value',
-    has_meta ? 'has-meta' : 'no-meta',
-    data.preview ? 'has-preview' : 'no-preview',
-  ]
-%}
-<div{{ attributes.addClass(classes).removeClass('clearfix') }}>
-  <div class="form-managed-file__main">
-    {{ data|without('preview', 'alt', 'title')}}
-  </div>
 
-  {% if has_meta or data.preview %}
-  <div class="form-managed-file__meta-wrapper">
-    <div class="form-managed-file__meta">
-      {% if data.preview %}
-        <div class="form-managed-file__image-preview image-preview">
-          <div class="image-preview__img-wrapper">
-            {{ data.preview }}
-          </div>
-        </div>
-      {% endif %}
+{% extends '@claro/content-edit/file-managed-file.html.twig' %}
 
-      {% if data.alt or data.title %}
-        <div class="form-managed-file__meta-items">
-      {% endif %}
-
-      {{ data.alt }}
-      {{ data.title }}
-
-      {% if data.alt or data.title %}
-        </div>
-      {% endif %}
-    </div>
-  </div>
-  {% endif %}
-</div>
+{% set attributes = attributes.addClass('form-managed-file--image') %}
diff --git a/core/themes/claro/templates/media-library/details--media-library-add-form-selected-media.html.twig b/core/themes/claro/templates/media-library/details--media-library-add-form-selected-media.html.twig
new file mode 100644
index 0000000000..2c3637bde9
--- /dev/null
+++ b/core/themes/claro/templates/media-library/details--media-library-add-form-selected-media.html.twig
@@ -0,0 +1,11 @@
+{% extends "details.html.twig" %}
+{#
+/**
+ * @file
+ * Theme override for the "Additional selected media" area of the modal media
+ * library dialog.
+ *
+ * @see template_preprocess_details()
+ */
+#}
+{% set attributes = attributes.addClass('media-library-add-form__selected-media') %}
diff --git a/core/themes/claro/templates/media-library/fieldset--media-library-widget.html.twig b/core/themes/claro/templates/media-library/fieldset--media-library-widget.html.twig
new file mode 100644
index 0000000000..11cc330d86
--- /dev/null
+++ b/core/themes/claro/templates/media-library/fieldset--media-library-widget.html.twig
@@ -0,0 +1,24 @@
+{% extends 'fieldset.html.twig' %}
+{#
+/**
+ * @file
+ * Theme override for the media library widget.
+ *
+ * @see claro_preprocess_fieldset__media_library_widget()
+ * @see claro_preprocess_fieldset()
+ * @see template_preprocess_fieldset()
+ */
+#}
+{% macro media_library_prefix(prefix) %}
+  {% if prefix.empty_selection %}
+    <p class="media-library-widget-empty-text">{{ prefix }}</p>
+  {% else %}
+    {{ prefix }}
+  {% endif %}
+{% endmacro %}
+{%
+  set attributes = attributes.addClass('media-library-widget')
+%}
+{%
+  set prefix = _self.media_library_prefix(prefix)
+%}
diff --git a/core/themes/claro/templates/media-library/item-list--media-library-add-form-media-list.html.twig b/core/themes/claro/templates/media-library/item-list--media-library-add-form-media-list.html.twig
new file mode 100644
index 0000000000..d7931e16b1
--- /dev/null
+++ b/core/themes/claro/templates/media-library/item-list--media-library-add-form-media-list.html.twig
@@ -0,0 +1,35 @@
+{#
+/**
+ * @file
+ * Theme override for a list of new, unsaved media items being added in the
+ * modal media library dialog.
+ *
+ * Renders the item list without a wrapper div.
+ *
+ * Available variables:
+ * - items: A list of items. Each item contains:
+ *   - attributes: HTML attributes to be applied to each list item.
+ *   - value: The content of the list element.
+ * - title: The title of the list.
+ * - list_type: The tag for list element ("ul" or "ol").
+ * - wrapper_attributes: HTML attributes to be applied to the list wrapper.
+ * - attributes: HTML attributes to be applied to the list.
+ * - empty: A message to display when there are no items. Allowed value is a
+ *   string or render array.
+ * - context: A list of contextual data associated with the list. May contain:
+ *   - list_style: The custom list style.
+ *
+ * @see claro_preprocess_item_list__media_library_add_form_media_list()
+ * @see template_preprocess_item_list()
+ */
+#}
+{% if items -%}
+  {%- if title is not empty -%}
+    <h3>{{ title }}</h3>
+  {%- endif -%}
+  <{{ list_type }}{{ attributes.addClass('media-library-add-form__added-media') }}>
+  {%- for item in items -%}
+    <li{{ item.attributes.addClass('media-library-add-form__media') }}>{{ item.value }}</li>
+  {%- endfor -%}
+  </{{ list_type }}>
+{%- endif %}
diff --git a/core/themes/claro/templates/media-library/views-view--media-library.html.twig b/core/themes/claro/templates/media-library/views-view--media-library.html.twig
new file mode 100644
index 0000000000..6d73182af2
--- /dev/null
+++ b/core/themes/claro/templates/media-library/views-view--media-library.html.twig
@@ -0,0 +1,97 @@
+{#
+/**
+ * @file
+ * Theme override for the media_library view template.
+ *
+ * Exposed filters precede views header.
+ *
+ * Available variables:
+ * - attributes: Remaining HTML attributes for the element.
+ * - css_name: A css-safe version of the view name.
+ * - css_class: The user-specified classes names, if any.
+ * - header: The optional header.
+ * - footer: The optional footer.
+ * - rows: The results of the view query, if any.
+ * - empty: The content to display if there are no rows.
+ * - pager: The optional pager next/prev links to display.
+ * - exposed: Exposed widget form/info to display.
+ * - feed_icons: Optional feed icons to display.
+ * - more: An optional link to the next page of results.
+ * - title: Title of the view, only used when displaying in the admin preview.
+ * - title_prefix: Additional output populated by modules, intended to be
+ *   displayed in front of the view title.
+ * - title_suffix: Additional output populated by modules, intended to be
+ *   displayed after the view title.
+ * - attachment_before: An optional attachment view to be displayed before the
+ *   view content.
+ * - attachment_after: An optional attachment view to be displayed after the
+ *   view content.
+ * - dom_id: Unique id for every view being printed to give unique class for
+ *   Javascript.
+ *
+ * @see template_preprocess_views_view()
+ */
+#}
+{%
+  set classes = [
+    'view',
+    'view-' ~ id|clean_class,
+    'view-id-' ~ id,
+    'view-display-id-' ~ display_id,
+    dom_id ? 'js-view-dom-id-' ~ dom_id,
+  ]
+%}
+<div{{ attributes.addClass(classes) }}>
+  {{ title_prefix }}
+  {% if title %}
+    {{ title }}
+  {% endif %}
+  {{ title_suffix }}
+  {% if exposed %}
+    <div class="view-filters">
+      {{ exposed }}
+    </div>
+  {% endif %}
+  {% if header %}
+    <div class="view-header">
+      {{ header }}
+    </div>
+  {% endif %}
+  {% if attachment_before %}
+    <div class="attachment attachment-before">
+      {{ attachment_before }}
+    </div>
+  {% endif %}
+
+  {% if rows %}
+    <div class="view-content">
+      {{ rows }}
+    </div>
+  {% elseif empty %}
+    <div class="view-empty">
+      {{ empty }}
+    </div>
+  {% endif %}
+
+  {% if pager %}
+    {{ pager }}
+  {% endif %}
+  {% if attachment_after %}
+    <div class="attachment attachment-after">
+      {{ attachment_after }}
+    </div>
+  {% endif %}
+  {% if more %}
+    {{ more }}
+  {% endif %}
+  {% if footer %}
+    <div class="view-footer">
+      {{ footer }}
+    </div>
+  {% endif %}
+  {% if feed_icons %}
+    <div class="feed-icons">
+      {{ feed_icons }}
+    </div>
+  {% endif %}
+</div>
diff --git a/core/themes/claro/templates/media-library/views-view-unformatted--media-library.html.twig b/core/themes/claro/templates/media-library/views-view-unformatted--media-library.html.twig
new file mode 100644
index 0000000000..4bc33e0e86
--- /dev/null
+++ b/core/themes/claro/templates/media-library/views-view-unformatted--media-library.html.twig
@@ -0,0 +1,34 @@
+{#
+/**
+ * @file
+ * Theme override for the media_library display of unformatted rows.
+ *
+ * Available variables:
+ * - title: The title of this group of rows. May be empty.
+ * - rows: A list of the view's row items.
+ *   - attributes: The row's HTML attributes.
+ *   - content: The row's content.
+ * - view: The view object.
+ * - default_row_class: A flag indicating whether default classes should be
+ *   used on rows.
+ *
+ * @see template_preprocess_views_view_unformatted()
+ */
+#}
+{% if title %}
+  <h3>{{ title }}</h3>
+{% endif %}
+<div class="media-library-views-form__rows">
+  {% for row in rows %}
+    {%
+      set row_classes = [
+        default_row_class ? 'views-row',
+        'media-library-item',
+        'media-library-item--grid',
+      ]
+    %}
+    <div{{ row.attributes.addClass(row_classes) }}>
+      {{- row.content -}}
+    </div>
+  {% endfor %}
+</div>
