mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Merge pull request #11932 from dacook/buu-dropdown-tweaks-11518
[BUU] Dropdown UI tweaks (tom-select)
This commit is contained in:
@@ -5,10 +5,14 @@
|
||||
- if producer_options.many?
|
||||
.producers
|
||||
= label_tag :producer_id, t('.producers.label')
|
||||
= select_tag :producer_id, options_for_select(producer_options, producer_id), include_blank: t('.all_producers'), "data-controller": "tom-select", "data-tom-select-options-value": '{ "plugins": [] }', class: "fullwidth"
|
||||
= select_tag :producer_id, options_for_select(producer_options, producer_id),
|
||||
include_blank: t('.all_producers'), class: "fullwidth",
|
||||
data: { "controller": "tom-select", 'tom-select-placeholder-value': t('.search_for_producers')}
|
||||
.categories
|
||||
= label_tag :category_id, t('.categories.label')
|
||||
= select_tag :category_id, options_for_select(category_options, category_id), include_blank: t('.all_categories'), "data-controller": "tom-select", "data-tom-select-options-value": '{ "plugins": [] }', class: "fullwidth"
|
||||
= select_tag :category_id, options_for_select(category_options, category_id),
|
||||
include_blank: t('.all_categories'), class: "fullwidth",
|
||||
data: { "controller": "tom-select", 'tom-select-placeholder-value': t('.search_for_categories')}
|
||||
.submit
|
||||
.search-button
|
||||
= button_tag t(".search"), class: "secondary icon-search relaxed"
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
= t(".pagination.clear_search")
|
||||
%form.with-dropdown
|
||||
= t(".pagination.per_page.show")
|
||||
= select_tag :per_page, options_for_select([15, 25, 50, 100].collect{|i| [t('.pagination.per_page.per_page', num: i), i]}, pagy.items), data: { reflex: "change->products#change_per_page" }
|
||||
= select_tag :per_page, options_for_select([15, 25, 50, 100].collect{|i| [t('.pagination.per_page.per_page', num: i), i]}, pagy.items), class: "no-input per-page", data: { reflex: "change->products#change_per_page", controller: "tom-select", "tom-select-options-value": '{ "plugins": [] }'}
|
||||
|
||||
@@ -2,26 +2,20 @@ import { Controller } from "stimulus";
|
||||
import TomSelect from "tom-select/dist/esm/tom-select.complete";
|
||||
|
||||
export default class extends Controller {
|
||||
static values = { options: Object };
|
||||
static defaults = {
|
||||
maxItems: 1,
|
||||
maxOptions: null,
|
||||
plugins: ["dropdown_input"],
|
||||
allowEmptyOption: true,
|
||||
closeAfterSelect: true,
|
||||
onItemAdd: function () {
|
||||
this.setTextboxValue("");
|
||||
},
|
||||
};
|
||||
static values = { options: Object, placeholder: String };
|
||||
|
||||
connect(options = {}) {
|
||||
if (this.#placeholder()) {
|
||||
options.allowEmptyOption = false;
|
||||
options.placeholder = this.#placeholder();
|
||||
}
|
||||
|
||||
console.log(this.element, this.placeholderValue);
|
||||
this.control = new TomSelect(this.element, {
|
||||
...this.constructor.defaults,
|
||||
maxItems: 1,
|
||||
maxOptions: null,
|
||||
plugins: ["dropdown_input"],
|
||||
allowEmptyOption: true, // Show blank option (option with empty value)
|
||||
closeAfterSelect: true,
|
||||
placeholder: this.placeholderValue || this.#emptyOption(),
|
||||
onItemAdd: function () {
|
||||
this.setTextboxValue("");
|
||||
},
|
||||
...this.optionsValue,
|
||||
...options,
|
||||
});
|
||||
@@ -33,7 +27,7 @@ export default class extends Controller {
|
||||
|
||||
// private
|
||||
|
||||
#placeholder() {
|
||||
#emptyOption() {
|
||||
const optionsArray = [...this.element.options];
|
||||
return optionsArray.find((option) => [null, ""].includes(option.value))?.text;
|
||||
}
|
||||
|
||||
@@ -198,9 +198,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#sort {
|
||||
line-height: $btn-relaxed-height;
|
||||
height: $btn-relaxed-height;
|
||||
|
||||
@@ -214,29 +212,21 @@
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.per-page {
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
#filters {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
grid-template-rows: 1fr;
|
||||
grid-column-gap: 20px;
|
||||
display: flex;
|
||||
column-gap: 20px;
|
||||
align-items: end;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
.query {
|
||||
grid-column: 1 / span 3;
|
||||
}
|
||||
flex-grow: 1;
|
||||
min-width: 15em;
|
||||
|
||||
.producers,
|
||||
.categories {
|
||||
}
|
||||
|
||||
.submit {
|
||||
grid-column: 6 / span 1;
|
||||
}
|
||||
|
||||
.query {
|
||||
.search-input {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
@@ -270,10 +260,7 @@
|
||||
|
||||
.producers,
|
||||
.categories {
|
||||
select {
|
||||
width: 150px;
|
||||
height: $btn-relaxed-height;
|
||||
}
|
||||
width: 15em;
|
||||
}
|
||||
|
||||
.submit {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
box-shadow: none !important;
|
||||
@include border-radius($border-radius);
|
||||
color: $color-1 !important;
|
||||
font-size: 90%;
|
||||
height: 31px;
|
||||
line-height: inherit !important;
|
||||
padding: 5px 15px 7px;
|
||||
@@ -23,7 +22,6 @@
|
||||
|
||||
.select2-search-choice-close {
|
||||
background-image: none !important;
|
||||
font-size: 100% !important;
|
||||
@extend .icon-remove;
|
||||
@extend [class^="icon-"], :before;
|
||||
margin-top: 2px;
|
||||
@@ -54,7 +52,6 @@
|
||||
.select2-search {
|
||||
@extend .icon-search;
|
||||
|
||||
font-size: 100%;
|
||||
color: darken($color-border, 15);
|
||||
padding: 0 9px 0 0;
|
||||
|
||||
@@ -72,7 +69,6 @@
|
||||
padding: 6px 0 6px 25px;
|
||||
margin: 5px 0 0 5px;
|
||||
font-family: $base-font-family;
|
||||
font-size: 90%;
|
||||
box-shadow: none;
|
||||
background-image: none;
|
||||
}
|
||||
@@ -102,8 +98,6 @@
|
||||
padding-left: 0 !important;
|
||||
|
||||
li {
|
||||
font-size: 85% !important;
|
||||
|
||||
&.select2-highlighted {
|
||||
.select2-result-label {
|
||||
&,
|
||||
@@ -117,7 +111,6 @@
|
||||
color: $color-body-text;
|
||||
min-height: 22px;
|
||||
clear: both;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
&.select2-no-results,
|
||||
@@ -160,7 +153,6 @@
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
color: $color-1 !important;
|
||||
font-size: 85%;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-btn-hover-bg;
|
||||
@@ -168,7 +160,6 @@
|
||||
|
||||
.select2-search-choice-close {
|
||||
background-image: none !important;
|
||||
font-size: 85% !important;
|
||||
@extend .icon-remove;
|
||||
@extend [class^="icon-"], :before;
|
||||
margin-left: 2px;
|
||||
@@ -248,7 +239,6 @@ label .select2-container {
|
||||
top: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
|
||||
&.input-active {
|
||||
.ts-control {
|
||||
border-color: $lighter-grey;
|
||||
border-color: $orient;
|
||||
background-color: $lighter-grey;
|
||||
|
||||
input {
|
||||
&::placeholder {
|
||||
color: $light-grey;
|
||||
color: $medium-light-grey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,24 +23,42 @@
|
||||
@include border-radius($border-radius);
|
||||
|
||||
input {
|
||||
font-size: $body-font-size;
|
||||
height: auto;
|
||||
|
||||
&::placeholder {
|
||||
color: $near-black;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: 2px; // Ensure it lines up with the input. I have no idea why it's necessary.
|
||||
}
|
||||
}
|
||||
|
||||
.ts-dropdown {
|
||||
@include border-radius($border-radius);
|
||||
// Unstyled, we style the dropdown-content instead
|
||||
margin: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.ts-dropdown-content {
|
||||
margin-top: 4px;
|
||||
color: $near-black;
|
||||
background-color: $color-body-bg;
|
||||
@include border-radius($border-radius);
|
||||
box-shadow: $shadow-dropdown;
|
||||
|
||||
.option {
|
||||
&.selected {
|
||||
border-left: 2px solid $orient;
|
||||
}
|
||||
padding: 8px;
|
||||
border-left: 3px solid transparent;
|
||||
line-height: 20px;
|
||||
|
||||
&.selected,
|
||||
&.active {
|
||||
border-left: 3px solid $orient;
|
||||
background-color: $lighter-grey;
|
||||
color: $near-black;
|
||||
}
|
||||
@@ -47,21 +66,80 @@
|
||||
}
|
||||
}
|
||||
|
||||
.plugin-dropdown_input .dropdown-input {
|
||||
border-color: $lighter-grey;
|
||||
.plugin-dropdown_input {
|
||||
.ts-dropdown {
|
||||
// Cover up the control with the input
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: $orient;
|
||||
.dropdown-input-wrap::after {
|
||||
position: absolute;
|
||||
content: "\f077"; // chevron-up
|
||||
font-family: FontAwesome;
|
||||
border: none;
|
||||
top: 0.7rem;
|
||||
right: 0.7rem;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.dropdown-input {
|
||||
background-color: $color-body-bg;
|
||||
border: 1px solid $lighter-grey;
|
||||
box-shadow: none;
|
||||
padding: 0.6rem 0.75rem;
|
||||
|
||||
&:focus {
|
||||
border: 1px solid $orient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For the "single" tom_select, be as clause as native select boxes
|
||||
// For the "single" tom_select, be as close as possible to native select boxes
|
||||
// without too many options
|
||||
.ts-wrapper.single {
|
||||
max-height: 40px;
|
||||
max-width: 100%;
|
||||
|
||||
&.input-active .ts-control {
|
||||
cursor: pointer;
|
||||
.ts-control {
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding-right: 1rem !important; // ts has a clever variable-based rule here, but it doesn't seem to work right.
|
||||
overflow: hidden;
|
||||
|
||||
// Icon: Override TS icon with icon-chevron-down
|
||||
&::after {
|
||||
content: "\f078";
|
||||
font-family: FontAwesome;
|
||||
border: none;
|
||||
top: 1em;
|
||||
}
|
||||
&:not(.rtl)::after {
|
||||
right: 1.5rem;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-right: 1rem;
|
||||
// Hide overflow with an ellipsis if a width has been set
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&.dropdown-active .ts-control {
|
||||
&::after {
|
||||
content: "\f077"; // chevron-up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 'no-input' mode, like a native select (hide text input).
|
||||
.ts-wrapper.single.no-input {
|
||||
.ts-dropdown {
|
||||
position: absolute;
|
||||
top: 0; // we don't need to see the currently selected option, because it's visible in the dropdown
|
||||
}
|
||||
|
||||
.ts-dropdown-content {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ $yellow: #ff9300 !default; // Yellow
|
||||
$mystic: #d9e8eb !default; // Mystic
|
||||
$lighter-grey: #f8f9fa !default; // Lighter grey
|
||||
$light-grey: #eff1f2 !default; // Light grey (Porcelain)
|
||||
$medium-light-grey: #babdbe !default; // Silver Sand
|
||||
$medium-grey: #919191 !default; // Medium grey
|
||||
$dark-grey: #2e3132 !default; // Dark Grey
|
||||
$near-black: #191c1d !default; // Near-black (Shark)
|
||||
|
||||
@@ -74,6 +74,9 @@ $color-action-save-brd: very-light($color-success, 20 ) !default;
|
||||
$color-action-mail-bg: very-light($color-success, 5 ) !default;
|
||||
$color-action-mail-brd: very-light($color-success, 20 ) !default;
|
||||
|
||||
// Dropdown styles
|
||||
$shadow-dropdown: 0px 0px 8px 0px rgba($near-black, 0.25);
|
||||
|
||||
// Select2 select field colors
|
||||
$color-sel-bg: $lighter-grey !default;
|
||||
$color-sel-hover-bg: $lighter-grey !default;
|
||||
|
||||
@@ -19,7 +19,6 @@ fieldset {
|
||||
padding: $vpadding-txt $hpadding-txt;
|
||||
border: 1px solid $lighter-grey;
|
||||
color: $color-txt-text;
|
||||
font-size: 90%;
|
||||
background-color: $lighter-grey;
|
||||
|
||||
&:focus {
|
||||
|
||||
@@ -839,7 +839,9 @@ en:
|
||||
clear_search: Clear search
|
||||
filters:
|
||||
search_products: Search for products
|
||||
search_for_producers: Search for producers
|
||||
all_producers: All producers
|
||||
search_for_categories: Search for categories
|
||||
all_categories: All categories
|
||||
producers:
|
||||
label: Producers
|
||||
|
||||
Reference in New Issue
Block a user