From 1215626473efbe08facd21658a1c31da346d085e Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 10 Jun 2022 14:11:57 -0600 Subject: [PATCH] Select / Search CSS: - Promote image styling from Et2LinkAppSelect to all Selects - fix double scrollbar if there are a lot of options - different cursor for editable tags - align +# right to make it stand out a little more --- api/js/etemplate/Et2Link/Et2LinkAppSelect.ts | 6 -- api/js/etemplate/Et2Select/Et2Select.ts | 35 +++----- api/js/etemplate/Et2Select/Et2SelectEmail.ts | 40 +--------- api/js/etemplate/Et2Select/SearchMixin.ts | 84 +++++++++++++------- 4 files changed, 68 insertions(+), 97 deletions(-) diff --git a/api/js/etemplate/Et2Link/Et2LinkAppSelect.ts b/api/js/etemplate/Et2Link/Et2LinkAppSelect.ts index e6bb64a9e8..9e7e28e9b6 100644 --- a/api/js/etemplate/Et2Link/Et2LinkAppSelect.ts +++ b/api/js/etemplate/Et2Link/Et2LinkAppSelect.ts @@ -25,12 +25,6 @@ export class Et2LinkAppSelect extends SlotMixin(Et2Select) border: none; box-shadow: initial; } - et2-image { - width: var(--icon-width); - } - ::slotted(img), img { - vertical-align: middle; - } ` ] } diff --git a/api/js/etemplate/Et2Select/Et2Select.ts b/api/js/etemplate/Et2Select/Et2Select.ts index d7ed44c5dc..150bb34ce0 100644 --- a/api/js/etemplate/Et2Select/Et2Select.ts +++ b/api/js/etemplate/Et2Select/Et2Select.ts @@ -9,7 +9,6 @@ import {css, html, PropertyValues, TemplateResult} from "@lion/core"; -import {cssImage} from "../Et2Widget/Et2Widget"; import {StaticOptions} from "./StaticOptions"; import {Et2widgetWithSelectMixin} from "./Et2WidgetWithSelectMixin"; import {SelectOption} from "./FindSelectOptions"; @@ -36,26 +35,7 @@ export class Et2Select extends Et2WithSearchMixin(Et2InvokerMixin(Et2WidgetWithS css` :host { display: block; - } - select { - width: 100% - color: var(--input-text-color, #26537c); - border-radius: 3px; - flex: 1 0 auto; - padding-top: 4px; - padding-bottom: 4px; - padding-right: 20px; - border-width: 1px; - border-style: solid; - border-color: #e6e6e6; - -webkit-appearance: none; - -moz-appearance: none; - margin: 0; - background: #fff no-repeat center right; - background-image: ${cssImage('arrow_down')}; - background-size: 8px auto; - background-position-x: calc(100% - 8px); - text-indent: 5px; + --icon-width: 20px; } /* This is the drop-down arrow on the right */ @@ -64,6 +44,16 @@ export class Et2Select extends Et2WithSearchMixin(Et2InvokerMixin(Et2WidgetWithS font-weight: bold; color: gray !important; } + + ::slotted(img), img { + vertical-align: middle; + } + + /* Avoid double scrollbar if there are a lot of options */ + .select__menu + { + max-height: initial; + } select:hover { box-shadow: 1px 1px 1px rgb(0 0 0 / 60%); @@ -278,7 +268,8 @@ export class Et2Select extends Et2WithSearchMixin(Et2InvokerMixin(Et2WidgetWithS _optionTemplate(option : SelectOption) : TemplateResult { let icon = option.icon ? html` - ` : ""; + ` : ""; return html` diff --git a/api/js/etemplate/Et2Select/Et2SelectEmail.ts b/api/js/etemplate/Et2Select/Et2SelectEmail.ts index 9902cdf91b..e91f28e9b3 100644 --- a/api/js/etemplate/Et2Select/Et2SelectEmail.ts +++ b/api/js/etemplate/Et2Select/Et2SelectEmail.ts @@ -8,7 +8,7 @@ */ import {Et2Select} from "./Et2Select"; -import {css, html} from "@lion/core"; +import {css} from "@lion/core"; import {IsEmail} from "../Validators/IsEmail"; export class Et2SelectEmail extends Et2Select @@ -88,44 +88,6 @@ export class Et2SelectEmail extends Et2Select results.forEach(r => r.value = r.id); super.processRemoteResults(results); } - - - /** - * Customise how tags are rendered. This overrides what SlSelect - * does in syncItemsFromValue(). - * This is a copy+paste from SlSelect.syncItemsFromValue(). - * - * @param item - * @protected - */ - protected _tagTemplate(item) - { - let image = item.querySelector("et2-image"); - if(image) - { - image = image.clone(); - image.slot = "prefix"; - } - return html` - - { - event.stopPropagation(); - if(!this.disabled) - { - item.checked = false; - this.syncValueFromItems(); - } - }} - > - ${image} - ${this.getItemLabel(item)} - - `; - } } // @ts-ignore TypeScript is not recognizing that this widget is a LitElement diff --git a/api/js/etemplate/Et2Select/SearchMixin.ts b/api/js/etemplate/Et2Select/SearchMixin.ts index 82f8be3f52..ab8dab43da 100644 --- a/api/js/etemplate/Et2Select/SearchMixin.ts +++ b/api/js/etemplate/Et2Select/SearchMixin.ts @@ -153,6 +153,14 @@ export const Et2WithSearchMixin = >(superclass display: none; } + /* Different cursor for editable tags */ + :host([allowfreeentries]) .search_tag::part(base) { + cursor: text; + } + /* styling for icon inside tag (not option) */ + .tag_image { + margin-right: var(--sl-spacing-x-small); + } /* Keep overflow tag right-aligned. It's the only sl-tag. */ .select__tags sl-tag { margin-left: auto; @@ -220,6 +228,17 @@ export const Et2WithSearchMixin = >(superclass this._unbindListeners(); } + willUpdate(changedProperties) + { + super.willUpdate(changedProperties); + + // If searchURL is set, turn on search + if(changedProperties.has("searchUrl") && this.searchUrl) + { + this.search = true; + } + } + /** * Add the nodes we need to search * @@ -270,9 +289,19 @@ export const Et2WithSearchMixin = >(superclass return this.querySelector(".search_input"); } + /** + * Tag used for rendering options + * Used for finding & filtering options, they're created by the mixed-in class + * @returns {string} + */ + public get optionTag() + { + return "sl-menu-item"; + } + protected get menuItems() { - return this.querySelectorAll("sl-menu-item"); + return this.querySelectorAll(this.optionTag); } /** @@ -282,12 +311,12 @@ export const Et2WithSearchMixin = >(superclass */ protected get localItems() { - return this.querySelectorAll("sl-menu-item:not(.remote)"); + return this.querySelectorAll(this.optionTag + ":not(.remote)"); } protected get remoteItems() { - return this.querySelectorAll("sl-menu-item.remote"); + return this.querySelectorAll(this.optionTag + ".remote"); } get value() @@ -319,11 +348,6 @@ export const Et2WithSearchMixin = >(superclass } } - getItems() - { - return [...this.querySelectorAll("sl-menu-item:not(.no-match)")]; - } - protected _bindListeners() { this.addEventListener("sl-blur", this._handleSearchAbort); @@ -687,6 +711,7 @@ export const Et2WithSearchMixin = >(superclass } } + /** * Customise how tags are rendered. This overrides what SlSelect * does in syncItemsFromValue(). @@ -697,30 +722,29 @@ export const Et2WithSearchMixin = >(superclass */ protected _tagTemplate(item) { + let image = item.querySelector("et2-image"); + if(image) + { + image = image.clone(); + image.slot = "prefix"; + image.class = "tag_image"; + } return html` - - { - event.stopPropagation(); - if(!this.disabled) - { - item.checked = false; - this.syncValueFromItems(); - } - }} + + { + event.stopPropagation(); + if(!this.disabled) + { + item.checked = false; + this.syncValueFromItems(); + } + }} > + ${image} ${this.getItemLabel(item)} `;