Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt predictive search layout to new api #2192

Merged
merged 15 commits into from
Jan 12, 2023
Merged
2 changes: 1 addition & 1 deletion assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -2550,7 +2550,7 @@ details[open] .modal-overlay::after {

@media screen and (min-width: 990px) {
.search-modal__form {
max-width: 47.8rem;
max-width: 74.2rem;
}

.search-modal__close-button {
Expand Down
104 changes: 77 additions & 27 deletions assets/component-predictive-search.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,42 @@
z-index: 3;
border-bottom-right-radius: var(--popup-corner-radius);
border-bottom-left-radius: var(--popup-corner-radius);
box-shadow: var(--popup-shadow-horizontal-offset) var(--popup-shadow-vertical-offset) var(--popup-shadow-blur-radius) rgba(var(--color-shadow), var(--popup-shadow-opacity));
box-shadow: var(--popup-shadow-horizontal-offset)
var(--popup-shadow-vertical-offset) var(--popup-shadow-blur-radius)
rgba(var(--color-shadow), var(--popup-shadow-opacity));
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}

.predictive-search--search-template {
z-index: 2;
width: calc(100% + 0.2rem);
}

.predictive-search__results-groups-wrapper {
display: flex;
border-bottom: 0.1rem solid rgba(var(--color-foreground), 0.08);
padding-bottom: 1rem;
}

@media screen and (max-width: 749px) {
.predictive-search--header {
right: 0;
left: 0;
top: 100%;
}
}

@media screen and (max-width: 989px) {
.predictive-search {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
.predictive-search__results-groups-wrapper {
flex-direction: column;
}

.predictive-search__results-groups-wrapper:not(
.predictive-search__results-groups-wrapper--no-suggestions
) {
/* On mobile, when there are no suggestions the first .predictive-search__results-groups-wrapper
* is virtually empty due to a display: hidden on the predictive-search__pages-wrapper child.
* This causes the gap to render and look like a big top margin */
gap: 2rem;
}
}

Expand All @@ -50,14 +65,42 @@ predictive-search[loading] .predictive-search {
display: block;
}

.predictive-search__result-group {
display: flex;
flex-direction: column;
flex: 1 1 auto;
gap: 2rem;
}

.predictive-search__result-group:first-child .predictive-search__pages-wrapper {
display: none;
}

@media screen and (min-width: 750px) {
.predictive-search__results-groups-wrapper--no-products
.predictive-search__result-group:nth-child(2),
.predictive-search__result-group:last-child
.predictive-search__pages-wrapper {
display: none;
}
.predictive-search__result-group:first-child
.predictive-search__pages-wrapper {
display: initial;
}
.predictive-search__result-group:first-child {
flex: 0 0 26.4rem;
}
.predictive-search__results-groups-wrapper--no-products
.predictive-search__result-group:first-child,
.predictive-search__result-group:only-child {
flex-grow: 1;
}
}

.predictive-search__heading {
border-bottom: 0.1rem solid rgba(var(--color-foreground), 0.08);
margin: 0 auto;
margin: 0 2rem;
padding: 1.5rem 0 0.75rem;
display: flex;
justify-content: space-between;
align-items: center;
width: calc(100% - 4rem);
color: rgba(var(--color-foreground), 0.7);
}

Expand All @@ -67,11 +110,6 @@ predictive-search .spinner {
line-height: 0;
}

.predictive-search__heading .spinner {
margin: 0 0.2rem 0 2rem;
}

predictive-search:not([loading]) .predictive-search__heading .spinner,
predictive-search:not([loading]) .predictive-search__loading-state,
predictive-search:not([loading]) .predictive-search-status__loading {
display: none;
Expand All @@ -83,22 +121,22 @@ predictive-search[loading] .predictive-search__loading-state {
padding: 1rem;
}

predictive-search[loading] .predictive-search__heading ~ .predictive-search__loading-state,
predictive-search[loading] .predictive-search__results-list:first-child {
predictive-search[loading]
.predictive-search__results-groups-wrapper
~ .predictive-search__loading-state {
display: none;
}

.predictive-search__list-item:nth-last-child(2) {
border-bottom: 0.1rem solid rgba(var(--color-foreground), 0.08);
}

.predictive-search__list-item[aria-selected="true"] > *,
.predictive-search__list-item:hover > * {
.predictive-search__list-item:hover > *,
.predictive-search__item[aria-selected="true"],
.predictive-search__item:hover {
color: rgb(var(--color-foreground));
background-color: rgba(var(--color-foreground), 0.04);
}

.predictive-search__list-item[aria-selected="true"] .predictive-search__item-heading,
.predictive-search__list-item[aria-selected="true"]
.predictive-search__item-heading,
.predictive-search__list-item:hover .predictive-search__item-heading {
text-decoration: underline;
text-underline-offset: 0.3rem;
Expand All @@ -112,11 +150,11 @@ predictive-search[loading] .predictive-search__results-list:first-child {
width: 100%;
}

.predictive-search__item--link {
.predictive-search__item--link-with-thumbnail {
display: grid;
grid-template-columns: 5rem 1fr;
grid-column-gap: 2rem;
grid-template-areas: 'product-image product-content';
grid-template-areas: "product-image product-content";
}

.predictive-search__item-content {
Expand All @@ -137,6 +175,18 @@ predictive-search[loading] .predictive-search__results-list:first-child {
margin: 0;
}

.predictive-search__item-query-result *:not(mark) {
font-weight: bolder;
}

.predictive-search__item-query-result mark {
opacity: 75%;
}

.predictive-search__item-query-result mark {
background-color: transparent;
}

.predictive-search__item .price {
color: rgba(var(--color-foreground), 0.7);
font-size: 1.2rem;
Expand Down Expand Up @@ -173,5 +223,5 @@ predictive-search[loading] .predictive-search__results-list:first-child {
.predictive-search__image {
grid-area: product-image;
object-fit: contain;
font-family: 'object-fit: contain';
font-family: "object-fit: contain";
}
48 changes: 37 additions & 11 deletions assets/predictive-search.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,32 +104,56 @@ class PredictiveSearch extends SearchForm {

const moveUp = direction === 'up';
const selectedElement = this.querySelector('[aria-selected="true"]');
const allElements = this.querySelectorAll('li');
let activeElement = this.querySelector('li');

// Filter out hidden elements (duplicated page and article resources) thanks
// to this https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent
const allVisibleElements = Array.from(
this.querySelectorAll("li, button.predictive-search__item")
).filter((element) => element.offsetParent !== null);
let activeElementIndex = 0;

if (moveUp && !selectedElement) return;

this.statusElement.textContent = '';
let selectedElementIndex = -1;
let i = 0;

while (selectedElementIndex === -1 && i <= allVisibleElements.length) {
if (allVisibleElements[i] === selectedElement) {
selectedElementIndex = i;
}
i++;
}

this.statusElement.textContent = "";

if (!moveUp && selectedElement) {
activeElement = selectedElement.nextElementSibling || allElements[0];
activeElementIndex =
selectedElementIndex === allVisibleElements.length - 1
? 0
: selectedElementIndex + 1;
} else if (moveUp) {
activeElement = selectedElement.previousElementSibling || allElements[allElements.length - 1];
activeElementIndex =
selectedElementIndex === 0
? allVisibleElements.length - 1
: selectedElementIndex - 1;
}

if (activeElement === selectedElement) return;
if (activeElementIndex === selectedElementIndex) return;

const activeElement = allVisibleElements[activeElementIndex];

activeElement.setAttribute('aria-selected', true);
if (selectedElement) selectedElement.setAttribute('aria-selected', false);

this.setLiveRegionText(activeElement.textContent);
this.input.setAttribute('aria-activedescendant', activeElement.id);
}

selectOption() {
const selectedProduct = this.querySelector('[aria-selected="true"] a, [aria-selected="true"] button');
const selectedOption = this.querySelector(
'[aria-selected="true"] a, button[aria-selected="true"]'
);

if (selectedProduct) selectedProduct.click();
if (selectedOption) selectedOption.click();
}

getSearchResults(searchTerm) {
Expand All @@ -142,8 +166,10 @@ class PredictiveSearch extends SearchForm {
}

fetch(
`${routes.predictive_search_url}?q=${encodeURIComponent(searchTerm)}&${encodeURIComponent('resources[type]')}=product&${encodeURIComponent('resources[limit]')}=4&section_id=predictive-search`,
{signal: this.abortController.signal}
`${routes.predictive_search_url}?q=${encodeURIComponent(
searchTerm
)}&section_id=predictive-search`,
{ signal: this.abortController.signal }
)
.then((response) => {
if (!response.ok) {
Expand Down
16 changes: 15 additions & 1 deletion locales/bg-BG.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,21 @@
"results_with_count_and_term": {
"one": "Открит е {{ count }} резултат за „{{ terms }}“",
"other": "Открити са {{ count }} резултата за „{{ terms }}“"
}
},
"results_pages_with_count": {
"one": "{{ count }} страница",
"other": "{{ count }} страници"
},
"results_suggestions_with_count": {
"one": "{{ count }} предложениe",
"other": "{{ count }} предложения"
},
"results_products_with_count": {
"one": "{{ count }} продукт",
"other": "{{ count }} продукта"
},
"suggestions": "Предложения",
"pages": "Страници"
},
"cart": {
"cart": "Количка"
Expand Down
38 changes: 38 additions & 0 deletions locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,44 @@
"other": "Pro dotaz {{ terms }} byl nalezen tento počet výsledků: {{ count }}",
"few": "Pro dotaz {{ terms }} byl nalezen tento počet výsledků: {{ count }}",
"many": "Pro dotaz {{ terms }} byl nalezen tento počet výsledků: {{ count }}"
},
"results_collections_with_count": {
"one": "{{ count }} kolekce",
"other": "{{ count }} kolek.",
"few": "{{ count }} kolek.",
"many": "{{ count }} kolek."
},
"results_articles_with_count": {
"one": "{{ count }} článek",
"other": "{{ count }} čl.",
"few": "{{ count }} čl.",
"many": "{{ count }} čl."
},
"results_pages_with_count": {
"one": "{{ count }} stránka",
"other": "{{ count }} str.",
"few": "{{ count }} str.",
"many": "{{ count }} str."
},
"results_queries_with_count": {
"one": "{{ count }} navrhovaný dotaz",
"other": "{{ count }} navrhov. dot.",
"few": "{{ count }} navrhov. dot.",
"many": "{{ count }} navrhov. dot."
},
"results_products_with_count": {
"one": "{{ count }} produkt",
"other": "{{ count }} prod.",
"few": "{{ count }} prod.",
"many": "{{ count }} prod."
},
"suggestions": "Návrhy",
"pages": "Stránky",
"results_suggestions_with_count": {
"one": "Počet návrhů: {{ count }}",
"other": "Počet návrhů: {{ count }}",
"few": "Počet návrhů: {{ count }}",
"many": "Počet návrhů: {{ count }}"
}
},
"cart": {
Expand Down
12 changes: 6 additions & 6 deletions locales/cs.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,18 @@
"name": "Chování hledání",
"settings": {
"header": {
"content": "Návrhy produktů"
"content": "Návrhy hledaných výrazů"
},
"predictive_search_enabled": {
"label": "Povolit návrhy produktů"
"label": "Povolit návrhy hledaných výrazů"
},
"predictive_search_show_vendor": {
"label": "Zobrazit dodavatele",
"info": "Zobrazuje se v případě, že jsou povoleny návrhy produktů."
"label": "Zobrazit dodavatele produktu",
"info": "Zobrazuje se v případě, že jsou povoleny návrhy hledaných výrazů."
},
"predictive_search_show_price": {
"label": "Zobrazit cenu",
"info": "Zobrazuje se v případě, že jsou povoleny návrhy produktů."
"label": "Zobrazit cenu produktu",
"info": "Zobrazuje se v případě, že jsou povoleny návrhy hledaných výrazů."
}
}
},
Expand Down
26 changes: 26 additions & 0 deletions locales/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,32 @@
"results_with_count_and_term": {
"one": "Der blev fundet {{ count }} resultat for “{{ terms }}”",
"other": "Der blev fundet {{ count }} resultater for “{{ terms }}”"
},
"results_collections_with_count": {
"one": "{{ count }} kollektion",
"other": "{{ count }} kollektioner"
},
"results_articles_with_count": {
"one": "{{ count }} artikel",
"other": "{{ count }} artikler"
},
"results_pages_with_count": {
"one": "{{ count }} side",
"other": "{{ count }} sider"
},
"results_queries_with_count": {
"one": "{{ count }} forslået forespørgsel",
"other": "{{ count }} forslåede forespørgsler"
},
"results_products_with_count": {
"one": "{{ count }} produkt",
"other": "{{ count }} produkter"
},
"suggestions": "Forslag",
"pages": "Sider",
"results_suggestions_with_count": {
"one": "{{ count }} forslag",
"other": "{{ count }} forslag"
}
},
"cart": {
Expand Down
Loading