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'] = '

{{ text }}

'; + } + 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 . 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 . 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', ] %} - +
- {{ element|without('display', 'description')}} + {{ main_items.filename }} + {{ main_items|without('filename') }}
- {% if has_meta %} -
-
+ {% if has_meta or data.preview %} +
+
+ {% if data.preview %} +
+
+ {{ data.preview }} +
+
+ {% endif %} + + {% if data.description or display or data.alt or data.title %}
- {{ element.description }} + {{ data.description }} {% if display %} - {{ element.display }} + {{ data.display }} {% endif %} + {{ data.alt }} + {{ data.title }}
-
+ {% endif %}
+
{% endif %} + + {# Every third-party addition will be rendered here. #} + {{ data|without('preview', 'alt', 'title', 'description', 'display') }}
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', - ] -%} - -
- {{ data|without('preview', 'alt', 'title')}} -
- {% if has_meta or data.preview %} -
-
- {% if data.preview %} -
-
- {{ data.preview }} -
-
- {% endif %} +{% extends '@claro/content-edit/file-managed-file.html.twig' %} - {% if data.alt or data.title %} -
- {% endif %} - - {{ data.alt }} - {{ data.title }} - - {% if data.alt or data.title %} -
- {% endif %} -
-
- {% endif %} - +{% 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 %} +

{{ prefix }}

+ {% 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 -%} +

{{ title }}

+ {%- endif -%} + <{{ list_type }}{{ attributes.addClass('media-library-add-form__added-media') }}> + {%- for item in items -%} + {{ item.value }} + {%- endfor -%} + +{%- 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, + ] +%} + + {{ title_prefix }} + {% if title %} + {{ title }} + {% endif %} + {{ title_suffix }} + {% if exposed %} +
+ {{ exposed }} +
+ {% endif %} + {% if header %} +
+ {{ header }} +
+ {% endif %} + {% if attachment_before %} +
+ {{ attachment_before }} +
+ {% endif %} + + {% if rows %} +
+ {{ rows }} +
+ {% elseif empty %} +
+ {{ empty }} +
+ {% endif %} + + {% if pager %} + {{ pager }} + {% endif %} + {% if attachment_after %} +
+ {{ attachment_after }} +
+ {% endif %} + {% if more %} + {{ more }} + {% endif %} + {% if footer %} + + {% endif %} + {% if feed_icons %} +
+ {{ feed_icons }} +
+ {% endif %} + 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 %} +

{{ title }}

+{% endif %} +
+ {% for row in rows %} + {% + set row_classes = [ + default_row_class ? 'views-row', + 'media-library-item', + 'media-library-item--grid', + ] + %} + + {{- row.content -}} +
+ {% endfor %} +