Commit fdcb412a authored by Andreas Fernandez's avatar Andreas Fernandez Committed by Benjamin Franzke
Browse files

[BUGFIX] Use `form-select` class for <select> fields

With Bootstrap 5, <select> fields make use of the class `form-select`.
This patch aims to replace every occurrence of `form-control` used with
select fields. Since Bootstrap finally brings proper styling for select
boxes, the custom implementation rendering chevrons can be removed.

In the same run, the `input-$size` classes are migrated to its new class
names and some obsolete classes have been removed.

Resolves: #93135
Releases: master
Change-Id: I0044127cc380bddfbaec0b9f730123959f7288bd
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/67247

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: default avatarMartin Kutschker <mkutschker-typo3@yahoo.com>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Reviewed-by: default avatarMartin Kutschker <mkutschker-typo3@yahoo.com>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
parent 6ed3053c
......@@ -52,11 +52,9 @@ span.typo3-moduleHeader img {
// Input group additions
//
.input-group-icon {
width: 32px;
vertical-align: middle;
img {
width: 100%;
max-height: 18px;
}
}
......@@ -185,47 +183,14 @@ fieldset[disabled] .form-control {
}
}
@mixin select-chevron {
background-image: url('#{$path-sysext}/core/Resources/Public/Icons/T3Icons/svgs/actions/actions-chevron-down.svg');
background-position: right 4px center;
background-repeat: no-repeat;
background-size: 16px 16px;
padding-right: 24px;
}
//
// Select
//
select {
&.form-control {
&.form-select {
&[multiple],
&[size] {
&[size]:not([size="1"]) {
min-height: 156px;
width: 100% !important;
}
&[size="1"] {
height: $input-height-base;
min-height: 0;
}
&[size="1"],
&:not([multiple]):not([size]),
&:not([size]) {
appearance: none;
&::-ms-expand {
display: none;
}
&:not(.form-select-no-siblings) {
@include select-chevron;
}
&.input-sm,
.form-group-sm & {
line-height: 16px;
}
}
> optgroup {
......@@ -483,8 +448,8 @@ select {
.form-multigroup-item-wizard {
margin-bottom: 5px;
+ select.form-control[multiple],
+ select.form-control[size] {
+ select.form-select[multiple],
+ select.form-select[size] {
min-height: 125px;
}
}
......
......@@ -374,7 +374,7 @@ class DragUploaderPlugin {
).format('YYYY-MM-DD HH:mm'),
),
$('<td />').append(
$('<select />', {class: 'form-control t3js-actions', 'data-override': i}).append(
$('<select />', {class: 'form-select t3js-actions', 'data-override': i}).append(
(this.irreObjectUid ? $('<option/>').val(Action.USE_EXISTING).text(TYPO3.lang['file_upload.actions.use_existing']) : ''),
$('<option />', {'selected': this.defaultAction === Action.SKIP})
.val(Action.SKIP).text(TYPO3.lang['file_upload.actions.skip']),
......@@ -410,7 +410,7 @@ class DragUploaderPlugin {
$modal.find('.modal-footer').prepend(
$('<span/>').addClass('form-inline').append(
$('<label/>').text(TYPO3.lang['file_upload.actions.all.label']),
$('<select/>', {class: 'form-control t3js-actions-all'}).append(
$('<select/>', {class: 'form-select t3js-actions-all'}).append(
$('<option/>').val('').text(TYPO3.lang['file_upload.actions.all.empty']),
(this.irreObjectUid ? $('<option/>').val(Action.USE_EXISTING).text(TYPO3.lang['file_upload.actions.all.use_existing']) : ''),
$('<option/>', {'selected': this.defaultAction === Action.SKIP})
......
......@@ -1070,7 +1070,7 @@ class PageLayoutController
}
$searchLevelLabel = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.title.search_levels');
$searchStringLabel = $lang->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.label.searchString');
$lMenu = '<select class="form-control" name="search_levels" title="' . htmlspecialchars($searchLevelLabel) . '" id="search_levels">' . implode('', $opt) . '</select>';
$lMenu = '<select class="form-select" name="search_levels" title="' . htmlspecialchars($searchLevelLabel) . '" id="search_levels">' . implode('', $opt) . '</select>';
return '<div class="db_list-searchbox-form db_list-searchbox-toolbar module-docheader-bar module-docheader-bar-search t3js-module-docheader-bar t3js-module-docheader-bar-search" id="db_list-searchbox-toolbar" style="display: none;">
<form action="' . htmlspecialchars((string)$listModule) . '" method="post">
<div id="typo3-dblist-search">
......
......@@ -618,7 +618,7 @@ class InlineControlContainer extends AbstractContainer
$size = (int)$config['size'];
$size = $config['autoSizeMax'] ? MathUtility::forceIntegerInRange(count($possibleRecords) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']) : $size;
$item = '
<select id="' . $nameObject . '-' . $config['foreign_table'] . '_selector" class="form-control t3js-create-new-selector"' . ($size ? ' size="' . $size . '"' : '') . '>
<select id="' . $nameObject . '-' . $config['foreign_table'] . '_selector" class="form-select t3js-create-new-selector"' . ($size ? ' size="' . $size . '"' : '') . '>
' . implode('', $opt) . '
</select>';
......
......@@ -177,7 +177,7 @@ class GroupElement extends AbstractFormElement
$html[] = '<select';
$html[] = ' size="' . $size . '"';
$html[] = ' disabled="disabled"';
$html[] = ' class="form-control tceforms-multiselect"';
$html[] = ' class="form-select"';
$html[] = ($maxItems !== 1 && $size !== 1) ? ' multiple="multiple"' : '';
$html[] = '>';
$html[] = implode(LF, $selectorOptionsHtml);
......@@ -250,14 +250,7 @@ class GroupElement extends AbstractFormElement
'data-maxitems' => (string)$maxItems,
'size' => (string)$size,
];
$selectorClasses = [
'form-control',
'tceforms-multiselect',
];
if ($maxItems === 1) {
$selectorClasses[] = 'form-select-no-siblings';
}
$selectorAttributes['class'] = implode(' ', $selectorClasses);
$selectorAttributes['class'] = 'form-select';
if ($maxItems !== 1 && $size !== 1) {
$selectorAttributes['multiple'] = 'multiple';
}
......
......@@ -160,7 +160,7 @@ class InputColorPickerElement extends AbstractFormElement
$valuePickerHtml = [];
if (isset($config['valuePicker']['items']) && is_array($config['valuePicker']['items'])) {
$valuePickerHtml[] = '<select class="t3js-colorpicker-value-trigger form-control tceforms-select tceforms-wizardselect">';
$valuePickerHtml[] = '<select class="t3js-colorpicker-value-trigger form-select">';
$valuePickerHtml[] = '<option></option>';
foreach ($config['valuePicker']['items'] as $item) {
$valuePickerHtml[] = '<option value="' . htmlspecialchars($item[1]) . '">' . htmlspecialchars($languageService->sL($item[0])) . '</option>';
......
......@@ -195,7 +195,7 @@ class InputLinkElement extends AbstractFormElement
. '.value=this.options[this.selectedIndex].value';
}
$valuePickerHtml[] = '<select';
$valuePickerHtml[] = ' class="form-control tceforms-select tceforms-wizardselect"';
$valuePickerHtml[] = ' class="form-select"';
$valuePickerHtml[] = ' onchange="' . htmlspecialchars($assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc)) . '"';
$valuePickerHtml[] = '>';
$valuePickerHtml[] = '<option></option>';
......
......@@ -185,7 +185,7 @@ class InputTextElement extends AbstractFormElement
. '.value=this.options[this.selectedIndex].value';
}
$valuePickerHtml[] = '<select';
$valuePickerHtml[] = ' class="form-control tceforms-select tceforms-wizardselect"';
$valuePickerHtml[] = ' class="form-select form-control-adapt"';
$valuePickerHtml[] = ' onchange="' . htmlspecialchars($assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc)) . '"';
$valuePickerHtml[] = '>';
$valuePickerHtml[] = '<option></option>';
......
......@@ -207,7 +207,7 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
if (!empty($filterDropDownOptions)) {
$filterHtml[] = '<div class="t3js-formengine-multiselect-filter-container form-multigroup-wrap">';
$filterHtml[] = '<div class="form-multigroup-item form-multigroup-element">';
$filterHtml[] = '<select class="form-control input-sm t3js-formengine-multiselect-filter-dropdown">';
$filterHtml[] = '<select class="form-select form-select-sm t3js-formengine-multiselect-filter-dropdown">';
$filterHtml[] = implode(LF, $filterDropDownOptions);
$filterHtml[] = '</select>';
$filterHtml[] = '</div>';
......@@ -220,12 +220,6 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
}
$filterHtml[] = '</div>';
$classes = [];
$classes[] = 'form-control';
$classes[] = 'tceforms-multiselect';
if ($maxItems === 1) {
$classes[] = 'form-select-no-siblings';
}
$multipleAttribute = '';
if ($maxItems !== 1 && $size !== 1) {
$multipleAttribute = ' multiple="multiple"';
......@@ -264,7 +258,7 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
$html[] = '<select';
$html[] = ' id="' . $selectedOptionsFieldId . '"';
$html[] = ' size="' . $size . '"';
$html[] = ' class="' . implode(' ', $classes) . '"';
$html[] = ' class="form-select"';
$html[] = $multipleAttribute;
$html[] = ' data-formengine-input-name="' . htmlspecialchars($elementName) . '"';
$html[] = '>';
......@@ -331,7 +325,7 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
$html[] = ' data-exclusivevalues="' . htmlspecialchars($config['exclusiveKeys']) . '"';
$html[] = ' id="' . $availableOptionsFieldId . '"';
$html[] = ' data-formengine-input-name="' . htmlspecialchars($elementName) . '"';
$html[] = ' class="form-control t3js-formengine-select-itemstoselect"';
$html[] = ' class="form-select t3js-formengine-select-itemstoselect"';
$html[] = ' size="' . $size . '"';
$html[] = ' onchange="' . htmlspecialchars(implode('', $parameterArray['fieldChangeFunc'])) . '"';
$html[] = ' data-formengine-validation-rules="' . htmlspecialchars($this->getValidationDataAsJsonString($config)) . '"';
......@@ -434,7 +428,7 @@ class SelectMultipleSideBySideElement extends AbstractFormElement
$html[] = '<select';
$html[] = ' id="' . StringUtility::getUniqueId('tceforms-multiselect-') . '"';
$html[] = ' size="' . $size . '"';
$html[] = ' class="form-control tceforms-multiselect"';
$html[] = ' class="form-select"';
$html[] = $multiple;
$html[] = ' data-formengine-input-name="' . htmlspecialchars($fieldName) . '"';
$html[] = ' disabled="disabled">';
......
......@@ -169,7 +169,7 @@ class SelectSingleBoxElement extends AbstractFormElement
{
$selectItems = $parameterArray['fieldConf']['config']['items'];
$size = (int)$config['size'];
$cssPrefix = $size === 1 ? 'tceforms-select' : 'tceforms-multiselect';
$prefix = $size === 1 ? 'tceforms-select' : 'tceforms-multiselect';
if ($config['autoSizeMax']) {
$size = MathUtility::forceIntegerInRange(
......@@ -183,8 +183,8 @@ class SelectSingleBoxElement extends AbstractFormElement
'name' => $parameterArray['itemFormElName'] . '[]',
'multiple' => 'multiple',
'onchange' => implode('', $parameterArray['fieldChangeFunc']),
'id' => StringUtility::getUniqueId($cssPrefix),
'class' => 'form-control ' . $cssPrefix,
'id' => StringUtility::getUniqueId($prefix),
'class' => 'form-select ',
'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config),
];
if ($size) {
......
......@@ -80,7 +80,7 @@ class SelectSingleElement extends AbstractFormElement
$config = $parameterArray['fieldConf']['config'];
$selectItems = $parameterArray['fieldConf']['config']['items'];
$classList = ['form-control', 'form-control-adapt'];
$classList = ['form-select', 'form-control-adapt'];
// Check against inline uniqueness
/** @var InlineStackProcessor $inlineStackProcessor */
......
......@@ -198,7 +198,7 @@ class TextElement extends AbstractFormElement
. '.value=this.options[this.selectedIndex].value';
}
$valuePickerHtml[] = '<select';
$valuePickerHtml[] = ' class="form-control tceforms-select tceforms-wizardselect"';
$valuePickerHtml[] = ' class="form-select form-control-adapt"';
$valuePickerHtml[] = ' onchange="' . htmlspecialchars($assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc)) . '"';
$valuePickerHtml[] = '>';
$valuePickerHtml[] = '<option></option>';
......
......@@ -2434,7 +2434,7 @@ class BackendUtility
// relies on module 'TYPO3/CMS/Backend/ActionDispatcher'
$attributes = GeneralUtility::implodeAttributes([
'name' => $elementName,
'class' => 'form-control mb-3',
'class' => 'form-select mb-3',
'data-menu-identifier' => $dataMenuIdentifier,
'data-global-event' => 'change',
'data-action-navigate' => '$data=~s/$value/',
......@@ -2496,7 +2496,7 @@ class BackendUtility
return '
<div class="form-group">
<!-- Function Menu of module -->
<select class="form-control input-sm" ' . $attributes . '>
<select class="form-select form-select-sm" ' . $attributes . '>
' . implode(LF, $options) . '
</select>
</div>
......
......@@ -1610,7 +1610,7 @@ class PageLayoutView implements LoggerAwareInterface
return '<div class="row-cols-auto row form-inline-spaced">'
. '<div class="col">'
. '<select class="form-control input-sm" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">'
. '<select class="form-select form-select-sm" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">'
. $output
. '</select></div></div>';
}
......
......@@ -4,7 +4,7 @@
<div class="form-control-wrap">
<div class="form-control-holder">
<label for="t3-interfaces"><f:translate key="login.interface" /></label>
<f:form.select id="t3-interfaces" class="form-control" name="interface" options="{interfaces}" optionValueField="interface" optionLabelField="label" />
<f:form.select id="t3-interfaces" class="form-select" name="interface" options="{interfaces}" optionValueField="interface" optionLabelField="label" />
</div>
</div>
</div>
......
<f:if condition="{menu.menuItems -> f:count()} > 1">
{menu.label} <select class="form-control form-control-sm t3-js-jumpMenuBox"
{menu.label} <select class="form-select form-select-sm t3-js-jumpMenuBox"
name="{menu.identifier}"
data-menu-identifier="{menu.dataIdentifier}"
data-global-event="change" data-action-navigate="$value">
......
<f:if condition="{context.newLanguageOptions}">
<div class="row-cols-auto row form-inline-spaced">
<div class="col">
<select class="form-control input-sm" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">
<select class="form-select form-select-sm" name="createNewLanguage" data-global-event="change" data-action-navigate="$value">
<f:for each="{context.newLanguageOptions}" as="languageName" key="url">
<option value="{url}">{languageName}</option>
</f:for>
......
......@@ -133,7 +133,7 @@
<div id="page_new_icon_{line.index}" class="input-group-addon input-group-icon">
<core:iconForRecord table="pages" row="{id: '0'}" />
</div>
<select id="page_new_select_{line.index}" class="form-control form-control-adapt t3js-newmultiplepages-select-doktype" name="pages[NEW{line.index}][doktype]" data-bs-target="#page_new_icon_{line.index}">
<select id="page_new_select_{line.index}" class="form-select t3js-newmultiplepages-select-doktype" name="pages[NEW{line.index}][doktype]" data-bs-target="#page_new_icon_{line.index}">
<f:for each="{line.pageTypes}" as="typegroup" key="group">
<optgroup label="{f:translate(key: '{group}')}">
<f:for each="{typegroup}" as="type">
......
......@@ -7,7 +7,7 @@
<input type="text" class="form-control" name="shortcut-title" value="{selectedShortcut.label}"/>
</div>
<div class="form-group">
<select class="form-control" name="shortcut-group">
<select class="form-select" name="shortcut-group">
<f:for each="{shortcutGroups}" key="shortcutGroupId" as="shortcutGroupTitle">
<option value="{shortcutGroupId}" {f:if(condition: '{selectedShortcutGroupId} == {shortcutGroupId}', then: 'selected="selected"')}>{shortcutGroupTitle}</option>
</f:for>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment