Feature: enhanced chips toolbar with sorting and load select

Chips toolbar improvements:
- Filter input now uses all available space (flex: 1)
- Added sort dropdown: Order added, Name A-Z, Name Z-A
- Changed "Show X more" button to select dropdown pattern
  - Load 20, 50, 100, or All
  - Shows remaining count
- Collapse button to return to default view

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 19:44:56 +00:00
parent b7054f11f9
commit acbcf55b1c
7 changed files with 230 additions and 58 deletions

View File

@@ -145,20 +145,27 @@
$toolbar.addClass('has-chips');
this.updateChipsToolbar($toolbar, totalCount, filteredCount, searchTerm);
// Update load more button
// Update load more select dropdown
var hiddenByPagination = filteredCount - visibleCount;
if (hiddenByPagination > 0 && !isExpanded) {
var moreText = (trans.show_more || 'Show {count} more').replace('{count}', hiddenByPagination);
$loadMore.html(
'<button type="button" class="btn-load-more">' +
'<i class="icon-chevron-down"></i> ' + moreText +
'</button>'
).show();
var loadText = trans.load || 'Load';
var remainingText = (trans.remaining || '{count} remaining').replace('{count}', hiddenByPagination);
var loadMoreHtml = '<span class="load-more-label">' + loadText + '</span>' +
'<select class="load-more-select">' +
'<option value="20">20</option>' +
'<option value="50">50</option>' +
'<option value="100">100</option>' +
'<option value="all">' + (trans.all || 'All') + ' (' + hiddenByPagination + ')</option>' +
'</select>' +
'<span class="load-more-remaining">' + remainingText + '</span>';
$loadMore.html(loadMoreHtml).show();
} else if (isExpanded && filteredCount > (this.maxVisibleChips || 12)) {
var lessText = trans.show_less || 'Show less';
var collapseText = trans.collapse || 'Collapse';
$loadMore.html(
'<button type="button" class="btn-load-more">' +
'<i class="icon-chevron-up"></i> ' + lessText +
'<button type="button" class="btn-collapse-chips" style="' +
'background:transparent;border:1px solid #dee2e6;border-radius:4px;' +
'padding:0.25rem 0.75rem;font-size:12px;color:#6c757d;cursor:pointer;">' +
'<i class="icon-chevron-up"></i> ' + collapseText +
'</button>'
).show();
} else {
@@ -175,13 +182,18 @@
var trans = this.config.trans || {};
var $picker = $chips.closest('.value-picker');
// Create wrapper structure - integrated filter toolbar
// Create wrapper structure - integrated filter toolbar with sort
var wrapperHtml = '<div class="chips-wrapper">' +
'<div class="chips-toolbar">' +
'<span class="chips-filter-group">' +
'<i class="icon-search"></i>' +
'<input type="text" class="chips-search-input" placeholder="' + (trans.filter || 'Filter') + '...">' +
'<input type="text" class="chips-search-input" placeholder="' + (trans.filter_selected || 'Filter selected') + '...">' +
'</span>' +
'<select class="chips-sort-select" title="' + (trans.sort || 'Sort') + '">' +
'<option value="added">' + (trans.sort_added || 'Order added') + '</option>' +
'<option value="name_asc">' + (trans.sort_name_asc || 'Name A-Z') + '</option>' +
'<option value="name_desc">' + (trans.sort_name_desc || 'Name Z-A') + '</option>' +
'</select>' +
'<span class="chips-count"></span>' +
'<button type="button" class="btn-chips-clear" title="' + (trans.clear_all || 'Clear all') + '">' +
'<i class="icon-trash"></i> <span class="clear-text">' + (trans.clear || 'Clear') + '</span>' +
@@ -216,6 +228,12 @@
}, 150);
});
// Sort select
$wrapper.on('change', '.chips-sort-select', function() {
var sortBy = $(this).val();
self.sortChips($chips, sortBy);
});
// Clear all button
$wrapper.on('click', '.btn-chips-clear', function() {
var searchTerm = $wrapper.find('.chips-search-input').val() || '';
@@ -238,15 +256,59 @@
self.updateChipsVisibility($chips);
});
// Load more / show less
$wrapper.on('click', '.btn-load-more', function() {
if ($chips.hasClass('chips-expanded')) {
$chips.removeClass('chips-expanded');
} else {
// Load more select dropdown
$wrapper.on('change', '.load-more-select', function() {
var loadCount = $(this).val();
if (loadCount === 'all') {
$chips.addClass('chips-expanded');
self.maxVisibleChips = 999999;
} else {
self.maxVisibleChips = (self.maxVisibleChips || 12) + parseInt(loadCount, 10);
}
self.updateChipsVisibility($chips);
});
// Collapse button
$wrapper.on('click', '.btn-collapse-chips', function() {
$chips.removeClass('chips-expanded');
self.maxVisibleChips = 12;
self.updateChipsVisibility($chips);
});
},
/**
* Sort chips by specified criteria
*/
sortChips: function($chips, sortBy) {
var $allChips = $chips.find('.entity-chip');
if ($allChips.length < 2) return;
var sorted = $allChips.toArray().sort(function(a, b) {
var $a = $(a);
var $b = $(b);
switch (sortBy) {
case 'name_asc':
var nameA = ($a.find('.chip-name').text() || '').toLowerCase();
var nameB = ($b.find('.chip-name').text() || '').toLowerCase();
return nameA.localeCompare(nameB);
case 'name_desc':
var nameA2 = ($a.find('.chip-name').text() || '').toLowerCase();
var nameB2 = ($b.find('.chip-name').text() || '').toLowerCase();
return nameB2.localeCompare(nameA2);
case 'added':
default:
// Keep original DOM order (order added)
return 0;
}
});
// Re-append in sorted order
$.each(sorted, function(i, chip) {
$chips.append(chip);
});
this.updateChipsVisibility($chips);
},
updateChipsToolbar: function($toolbar, totalCount, filteredCount, searchTerm) {

View File

@@ -34,11 +34,13 @@
}
}
// Filter input styled as a search chip
// Filter input styled as a search chip - takes available space
.chips-filter-group {
display: flex;
align-items: center;
gap: 0.25rem;
flex: 1; // Take available space
min-width: 0; // Allow shrinking
padding: 0.25rem 0.5rem;
background: $es-white;
border: 1px solid $es-border-color;
@@ -63,8 +65,8 @@
input.chips-search-input[type="text"] {
flex: 1 !important;
min-width: 60px !important;
max-width: 120px !important;
width: auto !important;
max-width: none !important; // No max - use available space
width: 100% !important;
height: auto !important;
padding: 0.125rem 0 !important;
border: none !important;
@@ -86,6 +88,34 @@
}
}
// Sort dropdown for chips
.chips-sort-select,
select.chips-sort-select {
appearance: none;
padding: 0.25rem 1.5rem 0.25rem 0.5rem !important;
border: 1px solid $es-border-color !important;
border-radius: $es-radius-full !important;
background: $es-white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath fill='%23666' d='M0 2l4 4 4-4z'/%3E%3C/svg%3E") no-repeat right 0.5rem center !important;
background-size: 8px !important;
font-size: 11px !important;
color: $es-text-secondary;
cursor: pointer;
transition: all $es-transition-fast;
height: auto !important;
min-height: 0 !important;
line-height: 1.2 !important;
&:hover {
border-color: $es-primary !important;
}
&:focus {
outline: none !important;
border-color: $es-primary !important;
box-shadow: 0 0 0 2px rgba($es-primary, 0.1) !important;
}
}
// Count badge - smaller, pill style
.chips-count {
display: inline-flex;
@@ -167,36 +197,54 @@
}
}
// Load more button
// Load more section with select dropdown
.chips-load-more {
display: flex;
align-items: center;
justify-content: center;
gap: $es-spacing-sm;
padding: $es-spacing-sm $es-spacing-md;
background: $es-white;
border-top: 1px solid $es-border-color;
background: transparent;
border-top: 1px dashed $es-border-color;
.btn-load-more {
@include button-reset;
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.5rem 1rem;
color: $es-white;
font-size: $es-font-size-sm;
font-weight: $es-font-weight-semibold;
background: $es-primary;
border-radius: $es-radius-sm;
.load-more-label {
font-size: $es-font-size-xs;
color: $es-text-muted;
}
.load-more-select,
select.load-more-select {
appearance: none;
padding: 0.25rem 1.75rem 0.25rem 0.5rem !important;
border: 1px solid $es-border-color !important;
border-radius: $es-radius-sm !important;
background: $es-white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cpath fill='%23666' d='M0 2l4 4 4-4z'/%3E%3C/svg%3E") no-repeat right 0.5rem center !important;
background-size: 8px !important;
font-size: $es-font-size-xs !important;
font-weight: $es-font-weight-medium;
color: $es-primary;
cursor: pointer;
transition: all $es-transition-fast;
height: auto !important;
min-height: 0 !important;
line-height: 1.3 !important;
&:hover {
background: $es-primary-hover;
border-color: $es-primary !important;
background-color: $es-primary-light !important;
}
i {
font-size: 12px;
&:focus {
outline: none !important;
border-color: $es-primary !important;
box-shadow: 0 0 0 2px rgba($es-primary, 0.1) !important;
}
}
.load-more-remaining {
font-size: $es-font-size-xs;
color: $es-text-muted;
}
}
// Individual chip