Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make slim_select work for single-value select elements #265

Open
donquixote opened this issue Apr 16, 2024 · 2 comments
Open

Make slim_select work for single-value select elements #265

donquixote opened this issue Apr 16, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@donquixote
Copy link
Contributor

donquixote commented Apr 16, 2024

Currently, oe_whitelabel adds slim_select for multiple-value select elements.

See _oe_whitelabel_process_element_select().

function _oe_whitelabel_process_element_select(array &$element): array {
if (!$element['#multiple']) {
return $element;
}
$element['#attributes']['class'][] = 'multi-select';
// Config is empty so that it uses the defaults.
$element += ['#slim_select' => []];
return $element;
}

The slim_select library can also be useful for single-value selects with many options.

Currently there is one obstacle:
The BCL targets a class 'placeholder' which is also used in slim_select, causing an undesirable side effect.

Other than that, we need to decide if it is safe to apply it to all single-value selects, or if we need to decide it case by case.

@donquixote
Copy link
Contributor Author

A custom code solution can look like this:

This should be done on theme level, in a sub-theme of oe_whitelabel, if the slim-select library is not available in other themes.

/**
 * Implements hook_element_info_alter().
 *
 * Replaces a '#process' callback on the 'select' element type.
 *
 * @see oe_whitelabel_element_info_alter()
 */
function MYTHEME_element_info_alter(array &$info): void {
  if (isset($info['select']['#process'])) {
    // Find the callback added by oe_whitelabel.
    $key = array_search(
      '_oe_whitelabel_process_element_select',
      $info['select']['#process'],
      TRUE,
    );
    if ($key !== FALSE) {
      // Replace this callback added by oe_whitelabel.
      $info['select']['#process'][$key] = '_MYTHEME_process_element_select';
    }
  }
}

/**
 * Element '#process' callback for 'select' elements.
 *
 * This replaces a similar function from oe_whitelabel.
 * It adds slim_select also to single-value select elements with sufficient
 * number of options.
 *
 * See https://github.com/openeuropa/oe_whitelabel/issues/265
 *
 * @param array $element
 *   Original form element with '#type' => 'select'.
 *
 * @return array
 *   Processed form element.
 *
 * @see _oe_whitelabel_process_element_select()
 */
function _MYTHEME_process_element_select(array &$element): array {
  if ($element['#multiple']) {
    // This is a multiple-value select element.
    // Delegate to oe_whitelabel, to benefit from upstream changes.
    _oe_whitelabel_process_element_select($element);
  }
  elseif (count($element['#options']) > 5) {
    // This is a single-value select element with more than 5 options.
    // Trick oe_whitelabel into adding slim_select.
    $multiple_orig = $element['#multiple'];
    $element['#multiple'] = TRUE;
    // Delegate to oe_whitelabel, to benefit from upstream changes.
    _oe_whitelabel_process_element_select($element);
    // The original value of '#multiple' should always be boolean FALSE, if the
    // element type is used correctly.
    // However, to avoid any kind of side effect, we restore the original value,
    // which technically might be something like '' or 0 or NULL.
    $element['#multiple'] = $multiple_orig;
  }

  return $element;
}

Then to fix the CSS conflict:

/*
 * Styles to prevent a side effect of BCL styles on a placeholder element
 * created by slim_select.
 *
 * See https://github.com/openeuropa/oe_whitelabel/issues/265.
 */
:is(.ss-single-selected) > .placeholder {
  background-color: unset;
  cursor: inherit;
  display: unset;
  min-height: unset;
  opacity: unset;
  vertical-align: unset;
}

The :is(*) helps to reduce the selector weight, keeping it on the same level as the .placeholder style from BCL. This CSS needs to be included after the BCL css.

The inherit on cursor: inherit could probably be replaced with unset. In the end it does not matter because it is overridden by slim-select style.

For the .ss-single-selected I am not sure. It works for us, but perhaps we need a more general selector to cover other cases.

@donquixote donquixote added enhancement New feature or request and removed enhancement New feature or request labels Apr 16, 2024
@brummbar brummbar added the enhancement New feature or request label Jun 28, 2024
@brummbar
Copy link
Contributor

We could add a configuration in the theme to enable slim select for all selects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants