Commit 0d3f8d2e authored by effulgentsia's avatar effulgentsia

Issue #3066006 by bnjmnm, lauriii, katherined, KondratievaS, Lendude, ckrina,...

Issue #3066006 by bnjmnm, lauriii, katherined, KondratievaS, Lendude, ckrina, saschaeggi, phenaproxima: Convert Views UI to new design system
parent 5d0f5371
......@@ -81,6 +81,8 @@ libraries-override:
views_ui/admin.styling:
css:
component:
css/views_ui.admin.css: css/components/views_ui.admin.css
theme:
css/views_ui.admin.theme.css: css/theme/views_ui.admin.theme.css
......
......@@ -19,6 +19,7 @@
use Drupal\file\FileInterface;
use Drupal\views\Form\ViewsForm;
use Drupal\views\ViewExecutable;
use Drupal\views_ui\Form\Ajax\ViewsFormInterface;
/**
* Implements hook_theme_suggestions_HOOK_alter() for form_element.
......@@ -376,6 +377,12 @@ function claro_form_alter(array &$form, FormStateInterface $form_state, $form_id
$form['actions']['delete'] = _claro_convert_link_to_action_link($form['actions']['delete'], 'trash', 'default', 'danger');
}
if (($form_object instanceof ViewsForm || $form_object instanceof ViewsFormInterface) && isset($form['override']['#prefix'])) {
// Replace form--inline class so positioning of override form elements don't
// have to depend on floats.
$form['override']['#prefix'] = str_replace('form--inline', 'form--flex', $form['override']['#prefix']);
}
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';
......@@ -586,6 +593,31 @@ function claro_views_ui_display_top_alter(&$element) {
if (!empty($element['extra_actions'])) {
$element['extra_actions']['#dropbutton_type'] = 'small';
}
// Add a class to each item in the add display dropdown so they can be styled
// with a single selector.
if (isset($element['add_display'])) {
foreach ($element['add_display'] as &$display_item) {
if (isset($display_item['#type']) && in_array($display_item['#type'], ['submit', 'button'], TRUE)) {
$display_item['#attributes']['class'][] = 'views-tabs__action-list-button';
}
}
}
// Rearrange top bar contents so floats aren't necessary for positioning.
if (isset($element['extra_actions'], $element['tabs'], $element['add_display'])) {
$element['extra_actions']['#weight'] = 10;
$element['extra_actions']['#theme_wrappers'] = [
'container' => [
'#attributes' => [
'class' => ['views-display-top__extra-actions-wrapper'],
],
],
];
$element['#attributes']['class'] = array_diff($element['#attributes']['class'], ['clearfix']);
}
}
/**
......@@ -636,10 +668,18 @@ function claro_views_ui_display_tab_alter(&$element) {
$dummy_dropbutton['prefix']['#markup'] = preg_replace($prefix_regex, '$1$2 ' . $classes . '$3', $prefix);
}
}
// If the top details have both actions and title, the `actions` weights need
// to be adjusted so the DOM order matches the order of appearance.
if (isset($element['details']['top']['actions'], $element['details']['top']['display_title'])) {
$top = &$element['details']['top'];
$top['actions']['#weight'] = 10;
$top['#attributes']['class'] = array_diff($top['#attributes']['class'], ['clearfix']);
}
}
/**
* Implements hook_preprocess_HOOK for views_exposed_form.
* Implements hook_preprocess_HOOK() for views_exposed_form.
*/
function claro_preprocess_views_exposed_form(&$variables) {
$form = &$variables['form'];
......@@ -1413,3 +1453,111 @@ function claro_preprocess_links__media_library_menu(array &$variables) {
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for the Views UI rearrange filter form.
*/
function claro_preprocess_views_ui_rearrange_filter_form(array &$variables) {
foreach ($variables['table']['#rows'] as &$row) {
// Remove the container-inline class from the operator table cell.
if (isset($row['data'][0]['class'])) {
$row['data'][0]['class'] = array_diff($row['data'][0]['class'], ['container-inline']);
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for the Views UI config form.
*/
function claro_form_views_ui_config_item_form_alter(array &$form, FormStateInterface $form_state) {
$type = $form_state->get('type');
if ($type === 'filter') {
// Remove clearfix classes from several elements. They add unwanted
// whitespace and are no longer needed because uses of `float:` in this form
// have been removed.
// @todo Many of the changes to classes within this conditional may not be
// needed or require refactoring in https://drupal.org/node/3164890
unset($form['options']['clear_markup_start']);
unset($form['options']['clear_markup_end']);
$form['options']['expose_button']['#prefix'] = str_replace('clearfix', '', $form['options']['expose_button']['#prefix']);
if (isset($form['options']['group_button']['#prefix'])) {
$form['options']['group_button']['#prefix'] = str_replace('clearfix', '', $form['options']['group_button']['#prefix']);
}
// Remove `views-(direction)-(amount)` classes, replace with
// `views-group-box--operator`, and add a `views-config-group-region`
// wrapper.
if (isset($form['options']['operator']['#prefix'])) {
foreach (['views-left-30', 'views-left-40'] as $left_class) {
if (strpos($form['options']['operator']['#prefix'], $left_class) !== FALSE) {
$form['options']['operator']['#prefix'] = '<div class="views-config-group-region">' . str_replace($left_class, 'views-group-box--operator', $form['options']['operator']['#prefix']);
$form['options']['value']['#suffix'] = $form['options']['value']['#suffix'] . '</div>';
}
}
}
// Some instances of this form input have an added wrapper that needs to be
// removed in order to style these forms consistently.
// @see \Drupal\views\Plugin\views\filter\InOperator::valueForm
$wrapper_div_to_remove = '<div id="edit-options-value-wrapper">';
if (isset($form['options']['value']['#prefix']) && strpos($form['options']['value']['#prefix'], $wrapper_div_to_remove) !== FALSE) {
$form['options']['value']['#prefix'] = str_replace($wrapper_div_to_remove, '', $form['options']['value']['#prefix']);
$form['options']['value']['#suffix'] = preg_replace('/<\/div>/', '', $form['options']['value']['#suffix'], 1);
}
if (isset($form['options']['value']['#prefix'])) {
foreach (['views-right-70', 'views-right-60'] as $right_class) {
if (strpos($form['options']['value']['#prefix'], $right_class) !== FALSE) {
$form['options']['value']['#prefix'] = str_replace($right_class, 'views-group-box--value', $form['options']['value']['#prefix']);
}
}
}
// If the form includes a `value` field, the `.views-group-box--value` and
// `.views-group-box` classes must be present in a wrapper div. Add them
// here if it they are not yet present.
if (!isset($form['options']['value']['#prefix']) || strpos($form['options']['value']['#prefix'], 'views-group-box--value') === FALSE) {
$prefix = $form['options']['value']['#prefix'] ?? '';
$suffix = $form['options']['value']['#suffix'] ?? '';
$form['options']['value']['#prefix'] = '<div class="views-group-box views-group-box--value">' . $prefix;
$form['options']['value']['#suffix'] = $suffix . '</div>';
}
// If operator or value have no children, remove them from the render array
// so their prefixes and suffixes aren't added without any content.
foreach (['operator', 'value'] as $form_item) {
if (isset($form['options'][$form_item]) && count($form['options'][$form_item]) === 2 && isset($form['options'][$form_item]['#prefix']) && $form['options'][$form_item]['#suffix']) {
unset($form['options'][$form_item]);
}
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for Views UI add handler form.
*/
function claro_form_views_ui_add_handler_form_alter(array &$form, FormStateInterface $form_state) {
// Remove container-inline class to allow more control over styling.
if (isset($form['selected']['#attributes']['class'])) {
$form['selected']['#attributes']['class'] = array_diff($form['selected']['#attributes']['class'], ['container-inline']);
}
// Move all form elements in controls to its parent, this places them all in
// the same div, which makes it possible to position them with flex styling
// instead of floats.
if (isset($form['override']['controls'])) {
foreach (Element::children($form['override']['controls']) as $key) {
$form['override']["controls_$key"] = $form['override']['controls'][$key];
// The wrapper array for controls is removed after this loop completes.
// The wrapper ensured that its child elements were hidden in browsers
// without JavaScript. To replicate this functionality, the `.js-show`
// class is added to each item previously contained in the wrapper.
if (isset($form['override']['controls']['#id']) && $form['override']['controls']['#id'] === 'views-filterable-options-controls') {
$form['override']["controls_$key"]['#wrapper_attributes']['class'][] = 'js-show';
}
}
unset($form['override']['controls']);
}
}
......@@ -102,6 +102,10 @@
--input-padding-horizontal: calc(var(--space-m) - var(--input-border-size));
--input-font-size: var(--font-size-base);
--input-line-height: var(--space-l);
--input-padding-vertical--small: calc(var(--space-xs) - (var(--input-border-size) * 2));
--input-padding-horizontal--small: calc(var(--space-m) - var(--input-border-size));
--input-font-size--small: var(--font-size-xs);
--input-line-height--small: 1.3125rem;
--input--extrasmall-padding-vertical: calc(0.15rem - var(--input-border-size));
--input--extrasmall-padding-horizontal: calc(var(--space-xs) - var(--input-border-size));
--input--extrasmall-font-size: var(--font-size-s);
......
......@@ -93,22 +93,11 @@
.ui-dialog > .ui-dialog-content {
overflow: auto;
padding-right: 1.5rem;
padding-left: 1.5rem;
padding: 1rem 1.5rem;
color: #222330;
background: #fff;
}
/**
* @todo it should not be necessary to specify not(.views-ui-dialog) after
* https://drupal.org/node/3066006
*/
.ui-dialog:not(.views-ui-dialog) > .ui-dialog-content {
padding-top: 1rem;
padding-bottom: 1rem;
}
.ui-dialog > .ui-dialog-buttonpane {
color: #222330;
border-bottom-right-radius: 4px;
......
......@@ -86,21 +86,11 @@
.ui-dialog > .ui-dialog-content {
overflow: auto;
padding-right: var(--space-l);
padding-left: var(--space-l);
padding: var(--space-m) var(--space-l);
color: var(--color-text);
background: var(--color-white);
}
/**
* @todo it should not be necessary to specify not(.views-ui-dialog) after
* https://drupal.org/node/3066006
*/
.ui-dialog:not(.views-ui-dialog) > .ui-dialog-content {
padding-top: var(--space-m);
padding-bottom: var(--space-m);
}
.ui-dialog > .ui-dialog-buttonpane {
color: var(--color-text);
border-bottom-right-radius: var(--jui-dialog-border-radius);
......
......@@ -37,6 +37,10 @@
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.views-exposed-form--preview.views-exposed-form--preview {
margin-top: 0;
}
.views-exposed-form__item.views-exposed-form__item {
margin: 0.75rem 0.5rem 0 0; /* LTR */
}
......
......@@ -31,6 +31,9 @@
background-color: var(--color-white);
box-shadow: var(--details-box-shadow);
}
.views-exposed-form--preview.views-exposed-form--preview {
margin-top: 0;
}
.views-exposed-form__item.views-exposed-form__item {
margin: var(--space-s) var(--space-xs) 0 0; /* LTR */
......
/*
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/3084859
* @preserve
*/
/**
* @file
* The .admin.css file is intended to only contain positioning and size
* declarations. For example: display, position, float, clear, and overflow.
*/
.views-admin pre {
margin-top: 0;
margin-bottom: 0;
white-space: pre-wrap;
}
.views-display-deleted > details > summary,
.views-display-deleted .details-wrapper > .views-ui-display-tab-bucket > *,
.views-display-deleted .views-display-columns {
opacity: 0.25;
}
.views-display-disabled > details > summary,
.views-display-disabled .details-wrapper > .views-ui-display-tab-bucket > *,
.views-display-disabled .views-display-columns {
opacity: 0.5;
}
.views-display-tab .details-wrapper > .views-ui-display-tab-bucket .actions {
opacity: 1;
}
.views-display-column {
box-sizing: border-box;
}
.views-display-columns > * {
float: none;
width: auto;
margin: 0 0 var(--space-l) 0;
}
@media screen and (min-width: 60rem) { /* 960px */
.views-display-columns > * {
float: left; /* LTR */
width: 32%;
margin-bottom: 0;
margin-left: 2%; /* LTR */
}
[dir="rtl"] .views-display-columns > * {
float: right;
margin-right: 2%;
margin-left: 0;
}
.views-display-columns > *:first-child {
margin-left: 0; /* LTR */
}
[dir="rtl"] .views-display-columns > *:first-child {
margin-right: 0;
}
}
.views-ui-dialog .scroll {
overflow: auto;
padding: 1em;
}
/* Don't let the messages overwhelm the modal */
.views-ui-dialog .views-messages {
overflow: auto;
max-height: 200px;
}
.form-item--options-value-all {
display: none;
}
.js-only {
display: none;
}
html.js .js-only {
display: inherit;
}
html.js span.js-only {
display: inline;
}
/**
* @file
* The .admin.css file is intended to only contain positioning and size
* declarations. For example: display, position, float, clear, and overflow.
*/
.views-admin pre {
margin-top: 0;
margin-bottom: 0;
white-space: pre-wrap;
}
.views-display-deleted > details > summary,
.views-display-deleted .details-wrapper > .views-ui-display-tab-bucket > *,
.views-display-deleted .views-display-columns {
opacity: 0.25;
}
.views-display-disabled > details > summary,
.views-display-disabled .details-wrapper > .views-ui-display-tab-bucket > *,
.views-display-disabled .views-display-columns {
opacity: 0.5;
}
.views-display-tab .details-wrapper > .views-ui-display-tab-bucket .actions {
opacity: 1;
}
.views-display-column {
box-sizing: border-box;
}
.views-display-columns > * {
float: none;
width: auto;
margin: 0 0 var(--space-l) 0;
}
@media screen and (min-width: 60rem) { /* 960px */
.views-display-columns > * {
float: left; /* LTR */
width: 32%;
margin-bottom: 0;
margin-left: 2%; /* LTR */
}
[dir="rtl"] .views-display-columns > * {
float: right;
margin-right: 2%;
margin-left: 0;
}
.views-display-columns > *:first-child {
margin-left: 0; /* LTR */
}
[dir="rtl"] .views-display-columns > *:first-child {
margin-right: 0;
}
}
.views-ui-dialog .scroll {
overflow: auto;
padding: 1em;
}
/* Don't let the messages overwhelm the modal */
.views-ui-dialog .views-messages {
overflow: auto;
max-height: 200px;
}
.form-item--options-value-all {
display: none;
}
.js-only {
display: none;
}
html.js .js-only {
display: inherit;
}
html.js span.js-only {
display: inline;
}
{#
/**
* @file
* Theme override for Views UI build group filter form.
*
* Available variables:
* - form: A render element representing the form. Contains the following:
* - form_description: The exposed filter's description.
* - expose_button: The button to toggle the expose filter form.
* - group_button: Toggle options between single and grouped filters.
* - label: A filter label input field.
* - description: A filter description field.
* - value: The filters available values.
* - optional: A checkbox to require this filter or not.
* - remember: A checkbox to remember selected filter value(s) (per user).
* - widget: Radio Buttons to select the filter widget.
* - add_group: A button to add another row to the table.
* - more: A details element for additional field exposed filter fields.
* - table: A rendered table element of the group filter form.
*
* @see template_preprocess_views_ui_build_group_filter_form()
*
* @ingroup themeable
*/
#}
{{ form.form_description }}
{{ form.expose_button }}
{{ form.group_button }}
<div class="views-config-group-region">
<div class="views-group-box">
{{ form.optional }}
{{ form.remember }}
</div>
<div class="views-group-box">
{{ form.widget }}
{{ form.label }}
{{ form.description }}
</div>
</div>
{#
Render the rest of the form elements excluding elements that are rendered
elsewhere.
#}
{{ form|without(
'form_description',
'expose_button',
'group_button',
'optional',
'remember',
'widget',
'label',
'description',
'add_group',
'more'
)
}}
{{ table }}
{{ form.add_group }}
{{ form.more }}
{#
/**
* @file
* Theme override for each "box" on the display query edit screen.
*
* Available variables:
* - attributes: HTML attributes to apply to the container element.
* - actions: Action links such as "Add", "And/Or, Rearrange" for the content.
* - title: The title of the bucket, e.g. "Fields", "Filter Criteria", etc.
* - content: Content items such as fields or settings in this container.
* - name: The name of the bucket, e.g. "Fields", "Filter Criteria", etc.
* - overridden: A boolean indicating the setting has been overridden from the
* default.
*
* @see template_preprocess_views_ui_display_tab_bucket()
*
* @ingroup themeable
*/
#}
{%
set classes = [
'views-ui-display-tab-bucket',
name ? name|clean_class,
overridden ? 'overridden',
]
%}
<div{{ attributes.addClass(classes) }}>
{% if title or actions %}
<div class="views-ui-display-tab-bucket__header{% if actions %} views-ui-display-tab-bucket__header--actions{% endif %}">
{% if title -%}
<h3 class="views-ui-display-tab-bucket__title">{{ title }}</h3>
{%- endif %}
{% if actions -%}
<div class="views-ui-display-tab-bucket__actions">{{ actions }}</div>
{%- endif %}
</div>
{% endif %}
{{ content }}
</div>
{#
/**
* @file
* Theme override for Views UI display tab settings.
*
* Template for each row inside the "boxes" on the display query edit screen.
*
* Available variables:
* - attributes: HTML attributes such as class for the container.
* - description: The description or label for this setting.
* - settings_links: A list of links for this setting.
* - defaulted: A boolean indicating the setting is in its default state.
* - overridden: A boolean indicating the setting has been overridden from the
* default.
*
* @see template_preprocess_views_ui_display_tab_setting()
*
* @ingroup themeable
*/
#}
{%
set classes = [
'views-display-setting',
'views-ui-display-tab-setting',
defaulted ? 'defaulted',
overridden ? 'overridden',
]
%}
<div{{ attributes.addClass(classes) }}>
{% if description -%}
<span class="label">{{ description }}</span>
{%- endif %}
{% if settings_links %}
{{ settings_links|safe_join('<span class="label label--separator">&nbsp;|&nbsp;</span>') }}
{% endif %}
</div>
{#
/**
* @file
* Theme override for exposed filter form.
*
* Available variables:
* - form_description: The exposed filter's description.
* - expose_button: The button to toggle the expose filter form.
* - group_button: Toggle options between single and grouped filters.
* - required: A checkbox to require this filter or not.
* - label: A filter label input field.
* - description: A filter description field.
* - operator: The operators for how the filters value should be treated.
* - #type: The operator type.
* - value: The filters available values.
* - use_operator: Checkbox to allow the user to expose the operator.
* - more: A details element for additional field exposed filter fields.
*
* @ingroup themeable
*/
#}
{{ form.form_description }}
{{ form.expose_button }}
{{ form.required }}
{{ form.group_button }}
{{ form.label }}
{{ form.description }}
{{ form.operator }}