diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index 323ed425f..5cf3bcacc 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -15,6 +15,7 @@
- **Grid** - `equal height` and `equal width` now work without `row` wrappers
- **Grid** - `equal height` rows can now be `stretched` as well as `middle aligned`, `bottom aligned` and `top aligned`!
- **Headers** - Added new header type `sub header`, useful for displaying small headers alongside text content. See examples [in the header docs](http://www.semantic-ui.com/elements/header.html#sub-headers)
+- **Label** - Labels now have `active` and `active hover` states
- **Menu** - Added `stackable` menu variation for simple responsive menus
- **Menu** - Added many new variables to menu
- **Menu** - Fixed several inheritance issues for `dropdown item` inside `menu` appearing as `menu item`.
diff --git a/src/definitions/elements/label.less b/src/definitions/elements/label.less
index 9e61d443c..43c1f4694 100755
--- a/src/definitions/elements/label.less
+++ b/src/definitions/elements/label.less
@@ -93,7 +93,8 @@ a.ui.label {
cursor: pointer;
margin-right: 0em;
margin-left: @deleteMargin;
- opacity: @linkOpacity;
+ font-size: @deleteSize;
+ opacity: @deleteOpacity;
transition: @deleteTransition;
}
.ui.label .delete.icon:hover {
@@ -472,6 +473,43 @@ a.ui.label:hover:before {
color: @labelHoverTextColor;
}
+/*-------------------
+ Active
+--------------------*/
+
+.ui.active.label {
+ background-color: @labelActiveBackgroundColor;
+ border-color: @labelActiveBackgroundColor;
+
+ background-image: @labelActiveBackgroundImage;
+ color: @labelActiveTextColor;
+}
+.ui.active.label:before {
+ background-color: @labelActiveBackgroundColor;
+ background-image: @labelActiveBackgroundImage;
+ color: @labelActiveTextColor;
+}
+
+/*-------------------
+ Active Hover
+--------------------*/
+
+a.ui.labels .active.label:hover,
+a.ui.active.label:hover {
+ background-color: @labelActiveHoverBackgroundColor;
+ border-color: @labelActiveHoverBackgroundColor;
+
+ background-image: @labelActiveHoverBackgroundImage;
+ color: @labelActiveHoverTextColor;
+}
+.ui.labels a.active.label:ActiveHover:before,
+a.ui.active.label:ActiveHover:before {
+ background-color: @labelActiveHoverBackgroundColor;
+ background-image: @labelActiveHoverBackgroundImage;
+ color: @labelActiveHoverTextColor;
+}
+
+
/*-------------------
Visible
--------------------*/
diff --git a/src/definitions/modules/dropdown.js b/src/definitions/modules/dropdown.js
index c96d9d20d..c8d9b5496 100644
--- a/src/definitions/modules/dropdown.js
+++ b/src/definitions/modules/dropdown.js
@@ -42,6 +42,7 @@ $.fn.dropdown = function(parameters) {
namespace = settings.namespace,
selector = settings.selector,
error = settings.error,
+ templates = settings.templates,
eventNamespace = '.' + namespace,
moduleNamespace = 'module-' + namespace,
@@ -207,7 +208,7 @@ $.fn.dropdown = function(parameters) {
.appendTo($module)
;
}
- $menu.html( settings.templates.menu( selectValues ));
+ $menu.html( templates.menu( selectValues ));
}
else {
module.debug('Creating entire dropdown from select');
@@ -215,7 +216,7 @@ $.fn.dropdown = function(parameters) {
.attr('class', $input.attr('class') )
.addClass(className.selection)
.addClass(className.dropdown)
- .html( settings.templates.dropdown(selectValues) )
+ .html( templates.dropdown(selectValues) )
.insertBefore($input)
;
$input
@@ -331,7 +332,7 @@ $.fn.dropdown = function(parameters) {
;
if( module.has.search() ) {
$module
- .on(module.get.inputEvent(), selector.search, module.event.input)
+ .on(module.get.inputEvent() + eventNamespace, selector.search, module.event.input)
;
}
},
@@ -500,7 +501,8 @@ $.fn.dropdown = function(parameters) {
: $activeItem,
hasSelected = ($selectedItem.size() > 0)
;
- if(hasSelected && !module.is.multiple()) {
+ if(hasSelected) {
+ module.debug('Forcing partial selection to selected item', $selectedItem);
module.event.item.click.call($selectedItem);
module.remove.filteredItem();
}
@@ -545,7 +547,10 @@ $.fn.dropdown = function(parameters) {
pageLostFocus = (document.activeElement === this)
;
if(!itemActivated && !pageLostFocus) {
- if(settings.forceSelection) {
+ if(module.is.multiple()) {
+ module.remove.activeLabel();
+ }
+ else if(settings.forceSelection) {
module.forceSelection();
}
else {
@@ -566,137 +571,207 @@ $.fn.dropdown = function(parameters) {
},
keydown: function(event) {
var
- $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
- $activeItem = $menu.children('.' + className.active).eq(0),
- $selectedItem = ($currentlySelected.length > 0)
- ? $currentlySelected
- : $activeItem,
- $visibleItems = ($selectedItem.length > 0)
- ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
- : $menu.children(':not(.' + className.filtered +')'),
- $subMenu = $selectedItem.children(selector.menu),
- $parentMenu = $selectedItem.closest(selector.menu),
- isSubMenuItem = $parentMenu[0] !== $menu[0],
- inVisibleMenu = $parentMenu.is(':visible'),
pressedKey = event.which,
- keys = {
- enter : 13,
- escape : 27,
- leftArrow : 37,
- upArrow : 38,
- rightArrow : 39,
- downArrow : 40
- },
- hasSubMenu = ($subMenu.length> 0),
- hasSelectedItem = ($selectedItem.length > 0),
- lastVisibleIndex = ($visibleItems.size() - 1),
- $nextItem,
- newIndex
+ keys = module.get.shortcutKeys(),
+ isShortcutKey = module.is.inObject(pressedKey, keys)
;
- // visible menu keyboard shortcuts
- if(module.is.visible()) {
- // enter (select or sub-menu)
- if(pressedKey == keys.enter && hasSelectedItem) {
- if(hasSubMenu && !settings.allowCategorySelection) {
- module.verbose('Pressed enter on unselectable category, opening sub menu');
- pressedKey = keys.rightArrow;
+ if(isShortcutKey) {
+ var
+ $currentlySelected = $item.not(className.filtered).filter('.' + className.selected).eq(0),
+ $activeItem = $menu.children('.' + className.active).eq(0),
+ $selectedItem = ($currentlySelected.length > 0)
+ ? $currentlySelected
+ : $activeItem,
+ $visibleItems = ($selectedItem.length > 0)
+ ? $selectedItem.siblings(':not(.' + className.filtered +')').andSelf()
+ : $menu.children(':not(.' + className.filtered +')'),
+ $subMenu = $selectedItem.children(selector.menu),
+ $parentMenu = $selectedItem.closest(selector.menu),
+ inVisibleMenu = ($parentMenu.hasClass(className.visible) || $parentMenu.hasClass(className.animating)),
+ hasSubMenu = ($subMenu.length> 0),
+ hasSelectedItem = ($selectedItem.length > 0),
+ $nextItem,
+ isSubMenuItem,
+ newIndex
+ ;
+
+ // visible menu keyboard shortcuts
+ if( module.is.visible() ) {
+
+ // enter (select or open sub-menu)
+ if(pressedKey == keys.enter && hasSelectedItem) {
+ if(hasSubMenu && !settings.allowCategorySelection) {
+ module.verbose('Pressed enter on unselectable category, opening sub menu');
+ pressedKey = keys.rightArrow;
+ }
+ else {
+ module.verbose('Enter key pressed, choosing selected item');
+ module.event.item.click.call($selectedItem, event);
+ }
}
- else {
- module.verbose('Enter key pressed, choosing selected item');
- module.event.item.click.call($selectedItem, event);
+
+ // left arrow (hide sub-menu)
+ if(pressedKey == keys.leftArrow) {
+
+ isSubMenuItem = ($parentMenu[0] !== $menu[0]);
+
+ if(isSubMenuItem) {
+ module.verbose('Left key pressed, closing sub-menu');
+ module.animate.hide(false, $parentMenu);
+ $selectedItem
+ .removeClass(className.selected)
+ ;
+ $parentMenu
+ .closest(selector.item)
+ .addClass(className.selected)
+ ;
+ event.preventDefault();
+ }
}
- }
- // left arrow (hide sub-menu)
- if(pressedKey == keys.leftArrow) {
- if(isSubMenuItem) {
- module.verbose('Left key pressed, closing sub-menu');
- module.animate.hide(false, $parentMenu);
- $selectedItem
- .removeClass(className.selected)
+
+ // right arrow (show sub-menu)
+ if(pressedKey == keys.rightArrow) {
+ if(hasSubMenu) {
+ module.verbose('Right key pressed, opening sub-menu');
+ module.animate.show(false, $subMenu);
+ $selectedItem
+ .removeClass(className.selected)
+ ;
+ $subMenu
+ .find(selector.item).eq(0)
+ .addClass(className.selected)
+ ;
+ event.preventDefault();
+ }
+ }
+
+ // up arrow (traverse menu up)
+ if(pressedKey == keys.upArrow) {
+ $nextItem = (hasSelectedItem && inVisibleMenu)
+ ? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
+ : $item.eq(0)
;
- $parentMenu
- .closest(selector.item)
+ if($visibleItems.index( $nextItem ) < 0) {
+ module.verbose('Up key pressed but reached top of current menu');
+ return;
+ }
+ else {
+ module.verbose('Up key pressed, changing active item');
+ $selectedItem
+ .removeClass(className.selected)
+ ;
+ $nextItem
.addClass(className.selected)
- ;
+ ;
+ module.set.scrollPosition($nextItem);
+ }
+ event.preventDefault();
}
- event.preventDefault();
- }
- // right arrow (show sub-menu)
- if(pressedKey == keys.rightArrow) {
- if(hasSubMenu) {
- module.verbose('Right key pressed, opening sub-menu');
- module.animate.show(false, $subMenu);
- $selectedItem
- .removeClass(className.selected)
+
+ // down arrow (traverse menu down)
+ if(pressedKey == keys.downArrow) {
+ $nextItem = (hasSelectedItem && inVisibleMenu)
+ ? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
+ : $item.eq(0)
;
- $subMenu
- .find(selector.item).eq(0)
+ if($nextItem.length === 0) {
+ module.verbose('Down key pressed but reached bottom of current menu');
+ return;
+ }
+ else {
+ module.verbose('Down key pressed, changing active item');
+ $item
+ .removeClass(className.selected)
+ ;
+ $nextItem
.addClass(className.selected)
- ;
+ ;
+ module.set.scrollPosition($nextItem);
+ }
+
+ event.preventDefault();
}
- event.preventDefault();
+
}
- // up arrow (traverse menu up)
- if(pressedKey == keys.upArrow) {
- $nextItem = (hasSelectedItem && inVisibleMenu)
- ? $selectedItem.prevAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
- : $item.eq(0)
- ;
- if($visibleItems.index( $nextItem ) < 0) {
- module.verbose('Up key pressed but reached top of current menu');
- return;
+ else {
+ // enter (open menu)
+ if(pressedKey == keys.enter) {
+ module.verbose('Enter key pressed, showing dropdown');
+ module.show();
}
- else {
- module.verbose('Up key pressed, changing active item');
- $selectedItem
- .removeClass(className.selected)
- ;
- $nextItem
- .addClass(className.selected)
- ;
- module.set.scrollPosition($nextItem);
+ // escape (close menu)
+ if(pressedKey == keys.escape) {
+ module.verbose('Escape key pressed, closing dropdown');
+ module.hide();
+ }
+ // down arrow (open menu)
+ if(pressedKey == keys.downArrow) {
+ module.verbose('Down key pressed, showing dropdown');
+ module.show();
}
- event.preventDefault();
}
- // down arrow (traverse menu down)
- if(pressedKey == keys.downArrow) {
- $nextItem = (hasSelectedItem && inVisibleMenu)
- ? $nextItem = $selectedItem.nextAll(selector.item + ':not(.' + className.filtered + ')').eq(0)
- : $item.eq(0)
+
+ // multiple selection shortcuts
+ if( module.is.multiple() ) {
+ var
+ $label = $module.find(selector.label),
+ $activeLabel = $label.filter('.' + className.active),
+ activeValue = $activeLabel.data('value'),
+ labelIndex = $label.index($activeLabel),
+ labelCount = $label.length,
+ hasActiveLabel = ($activeLabel.length > 0),
+ isFirstLabel = (labelIndex == 0),
+ isLastLabel = (labelIndex + 1 == labelCount),
+ caretAtStart = (module.get.caretPosition() == 0)
;
- if($nextItem.length === 0) {
- module.verbose('Down key pressed but reached bottom of current menu');
- return;
+ if(pressedKey == keys.delimiter) {
+ // tokenize on comma
+ }
+ else if(pressedKey == keys.leftArrow) {
+ // activate previous label
+ if(caretAtStart && !hasActiveLabel) {
+ $label.last().addClass(className.active);
+ }
+ else if(hasActiveLabel && !isFirstLabel) {
+ $activeLabel
+ .removeClass(className.active)
+ .prev()
+ .addClass(className.active)
+ .end()
+ ;
+ event.preventDefault();
+ }
+ }
+ else if(pressedKey == keys.rightArrow) {
+ // activate next label
+ if(hasActiveLabel) {
+ $activeLabel
+ .removeClass(className.active)
+ .next()
+ .addClass(className.active)
+ .end()
+ ;
+ event.preventDefault();
+ }
+ }
+ else if(pressedKey == keys.deleteKey || pressedKey == keys.backspace) {
+ if(caretAtStart && !hasActiveLabel) {
+ $activeLabel = $label.last().addClass(className.active);
+ activeValue = $activeLabel.data('value');
+ module.remove.selected(activeValue);
+ }
+ else if(hasActiveLabel) {
+ $activeLabel.next().addClass(className.active);
+ module.remove.selected(activeValue);
+ }
+ // delete tag if empty search and selected tag
}
else {
- module.verbose('Down key pressed, changing active item');
- $item
- .removeClass(className.selected)
- ;
- $nextItem
- .addClass(className.selected)
- ;
- module.set.scrollPosition($nextItem);
+ $activeLabel.removeClass(className.active);
}
- event.preventDefault();
- }
- }
- else {
- // enter (open menu)
- if(pressedKey == keys.enter) {
- module.verbose('Enter key pressed, showing dropdown');
- module.show();
- }
- // escape (close menu)
- if(pressedKey == keys.escape) {
- module.verbose('Escape key pressed, closing dropdown');
- module.hide();
- }
- // down arrow (open menu)
- if(pressedKey == keys.downArrow) {
- module.verbose('Down key pressed, showing dropdown');
- module.show();
+
}
+
}
},
test: {
@@ -889,6 +964,42 @@ $.fn.dropdown = function(parameters) {
return $.inArray(value, array) === index;
});
},
+ caretPosition: function() {
+ var
+ input = $search.get(0),
+ range,
+ rangeLength
+ ;
+ if ('selectionStart' in input) {
+ return input.selectionStart;
+ }
+ else if (document.selection) {
+ input.focus();
+ range = document.selection.createRange();
+ rangeLength = range.text.length;
+ range.moveStart('character', -input.value.length);
+ return range.text.length - rangeLength;
+ }
+ },
+ keyCode: function(letter) {
+ return (typeof letter == 'string')
+ ? letter.charCodeAt(0)
+ : false
+ ;
+ },
+ shortcutKeys: function() {
+ return {
+ backspace : 8,
+ delimiter : module.get.keyCode(settings.delimiter),
+ deleteKey : 46,
+ enter : 13,
+ escape : 27,
+ leftArrow : 37,
+ upArrow : 38,
+ rightArrow : 39,
+ downArrow : 40
+ };
+ },
value: function() {
return ($input.length > 0)
? $input.val()
@@ -899,9 +1010,12 @@ $.fn.dropdown = function(parameters) {
var
value = module.get.value()
;
- return $.isArray(value)
+ if(value == '') {
+ return '';
+ }
+ return ($input.is('select') || !module.is.multiple())
? value
- : [value]
+ : value.split(settings.delimiter)
;
},
choiceText: function($choice, preserveHTML) {
@@ -1001,8 +1115,8 @@ $.fn.dropdown = function(parameters) {
;
value = (value !== undefined)
? value
- : ( module.get.value() !== undefined)
- ? module.get.value()
+ : ( module.get.values() !== undefined)
+ ? module.get.values()
: module.get.text()
;
isMultiple = (module.is.multiple() && $.isArray(value));
@@ -1115,10 +1229,15 @@ $.fn.dropdown = function(parameters) {
filtered: function() {
var
searchValue = $search.val(),
+ searchWidth = ((searchValue.length) * settings.glyphWidth) + 'em',
hasSearchValue = (typeof searchValue === 'string' && searchValue.length > 0)
;
if(hasSearchValue) {
$text.addClass(className.filtered);
+ if(module.is.multiple()) {
+ module.verbose('Adjusting input width', searchWidth, settings.glyphWidth)
+ $search.css('width', searchWidth);
+ }
}
else {
$text.removeClass(className.filtered);
@@ -1247,9 +1366,9 @@ $.fn.dropdown = function(parameters) {
module.debug('Setting mutiple select values', values, $input);
}
else {
- values = values.join(',');
+ values = values.join(settings.delimiter);
$input.val(values);
- module.debug('Setting hidden input to comma separatd values', values, $input);
+ module.debug('Setting hidden input to delimited values', values, $input);
}
},
active: function() {
@@ -1306,12 +1425,12 @@ $.fn.dropdown = function(parameters) {
$label = $('')
.addClass(className.label)
.attr('data-value', value)
- .html(text + '')
+ .html(templates.label(value, text))
;
if(settings.label.variation) {
$label.addClass(settings.label.variation);
}
- if(shouldAnimate) {
+ if(shouldAnimate == true) {
module.debug('Animating in label', $label);
$label
.addClass(className.hidden)
@@ -1332,6 +1451,9 @@ $.fn.dropdown = function(parameters) {
active: function() {
$module.removeClass(className.active);
},
+ activeLabel: function() {
+ $module.find(selector.label).removeClass(className.active);
+ },
visible: function() {
$module.removeClass(className.visible);
},
@@ -1342,19 +1464,67 @@ $.fn.dropdown = function(parameters) {
$item.removeClass(className.filtered);
},
searchTerm: function() {
+ module.verbose('Cleared search term');
$search.val('');
},
+ selected: function(value) {
+ var
+ $selectedItem = module.get.item(value),
+ $option,
+ values = $input.val(),
+ selectedValue = module.get.choiceValue($selectedItem)
+ ;
+ if($selectedItem) {
+ if( $input.is('select') ) {
+ $input
+ .find('option[value="' + selectedValue + '"]')
+ .prop('selected', false)
+ ;
+ }
+ else {
+ values = module.remove.delimitedValue(selectedValue, values);
+ $input.val(values);
+ }
+ if(module.is.multiple()) {
+ module.remove.label(selectedValue);
+ }
+ $selectedItem
+ .removeClass(className.active)
+ ;
+ }
+ },
selectedItem: function() {
$item.removeClass(className.selected);
},
+ delimitedValue: function(removedValue, values) {
+ if(typeof values != 'string') {
+ return false;
+ }
+ values = values.split(settings.delimiter);
+ values = $.grep(values, function(value){
+ return (removedValue != value);
+ });
+ values = values.join(settings.delimiter);
+ module.verbose('Removed value from delimited string', removedValue, values);
+ return values;
+ },
label: function(value) {
- $module
- .find(selector.label)
- .filter('[data-value="' + value +'"]')
+ var
+ $labels = $module.find(selector.label),
+ $removedLabel = $labels.filter('[data-value="' + value +'"]'),
+ labelCount = $labels.length,
+ shouldAnimate = (labelCount == 1 || $labels.index($removedLabel) + 1 == labelCount)
+ ;
+ if(shouldAnimate) {
+ $removedLabel
.transition(settings.label.transition, settings.label.duration, function() {
- $(this).remove();
+ $removedLabel.remove();
})
- ;
+ ;
+ }
+ else {
+ $removedLabel.remove();
+ }
},
tabbable: function() {
if( module.has.search() ) {
@@ -1412,6 +1582,18 @@ $.fn.dropdown = function(parameters) {
: $menu.is(':hidden')
;
},
+ inObject: function(needle, object) {
+ var
+ found = false
+ ;
+ $.each(object, function(index, property) {
+ if(property == needle) {
+ found = true;
+ return true;
+ }
+ });
+ return found;
+ },
multiple: function() {
return $module.hasClass(className.multiple);
},
@@ -1850,10 +2032,14 @@ $.fn.dropdown.settings = {
touch : 50
},
- forceSelection : true,
+ forceSelection : true,
+
+ // widest glyph width in em (W is 1.0714 em)
+ glyphWidth : 1.0714,
- transition : 'auto',
- duration : 250,
+ transition : 'auto',
+ delimiter : ',',
+ duration : 250,
/* Callbacks */
onNoResults : function(searchTerm){},
@@ -1926,6 +2112,9 @@ $.fn.dropdown.settings.templates = {
});
return html;
},
+ label: function(value, text) {
+ return text + '';
+ },
dropdown: function(select) {
var
placeholder = select.placeholder || false,
diff --git a/src/definitions/modules/dropdown.less b/src/definitions/modules/dropdown.less
index ae3aa1778..d4f77297b 100755
--- a/src/definitions/modules/dropdown.less
+++ b/src/definitions/modules/dropdown.less
@@ -599,20 +599,18 @@ select.ui.dropdown {
}
/* Multiple Search Selection */
-.ui.multiple.search.dropdown {
+.ui.multiple.search.dropdown,
+.ui.multiple.search.dropdown > input.search {
cursor: text;
}
/* Selection Label */
.ui.multiple.dropdown > .label {
display: inline-block;
- vertical-align: middle;
+ vertical-align: baseline;
padding: @labelPadding;
margin: (@labelVerticalSpacing / 2) @labelHorizontalSpacing (@labelVerticalSpacing / 2) 0em;
}
-.ui.multiple.dropdown > .label .delete {
- opacity: 0.4;
-}
/* Prompt Text */
.ui.multiple.dropdown > .text {
@@ -626,7 +624,8 @@ select.ui.dropdown {
.ui.multiple.selection.dropdown > input.search {
position: static;
padding: 0;
- width: 5em;
+ width: @multipleSelectionSearchWidth;
+ max-width: 100%;
margin: @multipleSelectionSearchMargin;
}
diff --git a/src/themes/default/elements/label.variables b/src/themes/default/elements/label.variables
index b1c4292e1..872a88401 100644
--- a/src/themes/default/elements/label.variables
+++ b/src/themes/default/elements/label.variables
@@ -35,7 +35,7 @@
Parts
--------------------*/
-@linkOpacity: 0.8;
+@linkOpacity: 0.5;
@linkTransition: @labelTransitionDuration opacity @labelTransitionEasing;
@iconDistance: 0.75em;
@@ -45,6 +45,8 @@
@detailIconDistance: 0.25em;
@detailMargin: 1em;
+@deleteOpacity: @linkOpacity;
+@deleteSize: @relativeSmall;
@deleteMargin: 0.5em;
@deleteTransition: background @labelTransitionDuration @labelTransitionEasing;
@@ -78,12 +80,23 @@
@labelHoverBackgroundImage: none;
@labelHoverTextColor: @hoveredTextColor;
+/* Hover */
+@labelActiveBackgroundColor: #D0D0D0;
+@labelActiveBackgroundImage: none;
+@labelActiveTextColor: @selectedTextColor;
+
+/* Active Hover */
+@labelActiveHoverBackgroundColor: #C8C8C8;
+@labelActiveHoverBackgroundImage: none;
+@labelActiveHoverTextColor: @selectedTextColor;
+
+
/*-------------------
Variations
--------------------*/
/* Tag */
-@tagCircleColor: #FFFFFF;
+@tagCircleColor: @white;
@tagCircleSize: 0.5em;
@tagHorizontalPadding: 1.5em;
@tagCircleBoxShadow: 0 -1px 1px 0 rgba(0, 0, 0, 0.3);
diff --git a/src/themes/default/globals/site.variables b/src/themes/default/globals/site.variables
index ff977dfb8..e0844852a 100644
--- a/src/themes/default/globals/site.variables
+++ b/src/themes/default/globals/site.variables
@@ -386,6 +386,9 @@
/* Rendered Scrollbar Width */
@scrollBarWidth: 15px;
+/* Maximum Single Character Glyph Width, aka Capital "W" */
+@glyphWidth: 1.1em;
+
/* Used to match floats with text */
@lineHeightOffset : ((@lineHeight - 1em) / 2);
@headerLineHeightOffset : (@headerLineHeight - 1em) / 2;
diff --git a/src/themes/default/modules/dropdown.variables b/src/themes/default/modules/dropdown.variables
index d9ac5bc74..40b93a672 100644
--- a/src/themes/default/modules/dropdown.variables
+++ b/src/themes/default/modules/dropdown.variables
@@ -220,6 +220,7 @@
@multipleSelectionLeftPadding: (@selectionHorizontalPadding - @labelHorizontalPadding);
@multipleSelectionSearchMargin: 0.4em 0em 0.4em 0.5em;
+@multipleSelectionSearchWidth: (@glyphWidth * 2);
/* Inline */
@inlineIconMargin: 0em 0.5em 0em 0.25em;