@fluid-topics/ft-search-bar 1.2.60 → 1.2.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,6 +14,8 @@ export interface FtSearchBarLabels extends ParametrizedLabels {
14
14
  presetsSelector?: string;
15
15
  removeRecentSearch?: string;
16
16
  back?: string;
17
+ ariaLiveSuggestions?: string;
18
+ suggestionsAriaLabel?: string;
17
19
  }
18
20
  export type DisplayMode = "auto" | "mobile" | "desktop";
19
21
  export interface FtSearchBarProperties {
@@ -16,6 +16,7 @@ export declare const FtSearchBarCssVariables: {
16
16
  elevation02: import("@fluid-topics/ft-wc-utils").FtCssVariable;
17
17
  buttonColor: import("@fluid-topics/ft-wc-utils").FtCssVariable;
18
18
  buttonRippleColor: import("@fluid-topics/ft-wc-utils").FtCssVariable;
19
+ activeItemBorderColor: import("@fluid-topics/ft-wc-utils").FtCssVariable;
19
20
  };
20
21
  export declare const searchBarCss: import("lit").CSSResult;
21
22
  export declare const facetsCss: import("lit").CSSResult;
@@ -26,6 +26,7 @@ export const FtSearchBarCssVariables = {
26
26
  elevation02: FtCssVariableFactory.external(designSystemVariables.elevation02, "Design system"),
27
27
  buttonColor: FtCssVariableFactory.external(FtButtonCssVariables.color, "Button"),
28
28
  buttonRippleColor: FtCssVariableFactory.external(FtButtonCssVariables.rippleColor, "Button"),
29
+ activeItemBorderColor: FtCssVariableFactory.extend("--ft-search-bar-active-border-color", "", designSystemVariables.colorPrimary),
29
30
  };
30
31
  //language=css
31
32
  export const searchBarCss = css `
@@ -386,4 +387,11 @@ export const facetsCss = css `
386
387
  .ft-search-bar--desktop-menu .ft-search-bar--launch-search {
387
388
  margin: 0;
388
389
  }
390
+
391
+ .ft-search-bar--aria-live {
392
+ position: absolute;
393
+ width: 0;
394
+ height: 0;
395
+ opacity: 0;
396
+ }
389
397
  `;
@@ -12,4 +12,6 @@ export declare class DesktopSearchBarManager {
12
12
  private renderDesktopSearchBarButtons;
13
13
  private onSearchBarKeyDown;
14
14
  private onInput;
15
+ private onClick;
16
+ private onFocus;
15
17
  }
@@ -10,13 +10,13 @@ class DesktopSearchBarManager {
10
10
  this.suggestManager = suggestManager !== null && suggestManager !== void 0 ? suggestManager : new SuggestManager(searchBar);
11
11
  }
12
12
  render() {
13
+ var _a;
13
14
  const rootClasses = {
14
15
  "ft-search-bar--container": true,
15
16
  "ft-search-bar--dense": this.searchBar.dense,
16
17
  "ft-search-bar--desktop": true,
17
18
  "ft-search-bar--floating-panel-open": this.searchBar.displayFacets && !this.searchBar.forceMenuOpen,
18
19
  "ft-search-bar--forced-open": this.searchBar.forceMenuOpen,
19
- "ft-search-bar--react-to-focus": this.searchBar.reactToFocus
20
20
  };
21
21
  return html `
22
22
  <div class="${classMap(rootClasses)}" part="container" tabindex="-1">
@@ -26,10 +26,17 @@ class DesktopSearchBarManager {
26
26
  <div class="ft-search-bar--input-outline" part="input-outline">
27
27
  ${this.searchBar.dense ? this.selectedFacetsManager.render() : nothing}
28
28
  <input class="ft-search-bar--input ft-typography--body2"
29
+ role="combobox"
30
+ aria-autocomplete="list"
31
+ aria-controls="${this.suggestManager.listboxId}"
32
+ aria-expanded="${this.searchBar.displaySuggestListbox}"
33
+ aria-activedescendant="${(_a = this.searchBar.ariaActiveDescendent) !== null && _a !== void 0 ? _a : nothing}"
29
34
  part="input"
30
35
  type="search"
31
36
  placeholder="${this.searchBar.labelResolver.resolve("inputPlaceHolder")}"
32
37
  value="${this.searchBar.query}"
38
+ @click="${() => this.onClick()}"
39
+ @focus="${() => this.onFocus()}"
33
40
  @input=${(e) => this.onInput(e)}
34
41
  @keydown=${(e) => this.onSearchBarKeyDown(e)}>
35
42
  </div>
@@ -116,19 +123,56 @@ class DesktopSearchBarManager {
116
123
  `;
117
124
  }
118
125
  onSearchBarKeyDown(e) {
119
- var _a, _b;
126
+ var _a;
127
+ if (!["Escape", "Tab", "Shift"].includes(e.key)) {
128
+ this.searchBar.displaySuggestListbox = true;
129
+ }
120
130
  switch (e.key) {
131
+ case "Tab":
132
+ this.searchBar.displaySuggestListbox = false;
133
+ this.searchBar.selectedSuggestOptionId = undefined;
134
+ break;
121
135
  case "Escape":
136
+ if (this.suggestManager.shouldDisplaySuggestions) {
137
+ e.stopPropagation();
138
+ e.preventDefault();
139
+ this.searchBar.displaySuggestListbox = false;
140
+ this.searchBar.selectedSuggestOptionId = undefined;
141
+ }
122
142
  this.searchBar.mobileMenuOpen = false;
123
- (_a = this.searchBar.input) === null || _a === void 0 ? void 0 : _a.blur();
124
143
  break;
125
144
  case "ArrowDown":
126
145
  e.stopPropagation();
127
146
  e.preventDefault();
128
- this.suggestManager.focusFirstSuggestion();
147
+ this.suggestManager.focusNextSuggestion();
148
+ break;
149
+ case "ArrowUp":
150
+ e.stopPropagation();
151
+ e.preventDefault();
152
+ this.suggestManager.focusPreviousSuggestion();
153
+ break;
154
+ case "ArrowLeft":
155
+ if (this.searchBar.selectedSuggestOptionId) {
156
+ e.stopPropagation();
157
+ e.preventDefault();
158
+ this.suggestManager.focusArrowLeft();
159
+ }
160
+ break;
161
+ case "ArrowRight":
162
+ if (this.searchBar.selectedSuggestOptionId) {
163
+ e.stopPropagation();
164
+ e.preventDefault();
165
+ this.suggestManager.focusArrowRight();
166
+ }
129
167
  break;
130
168
  case "Enter":
131
- (_b = this.searchBar.launchSearchButton) === null || _b === void 0 ? void 0 : _b.click();
169
+ if (this.searchBar.selectedSuggestRemoveRecent) {
170
+ (_a = this.suggestManager.selectedSuggestRemoveRecentButton) === null || _a === void 0 ? void 0 : _a.click();
171
+ }
172
+ else {
173
+ const elementToClick = this.suggestManager.selectedSuggestOptionLink || this.searchBar.launchSearchButton;
174
+ elementToClick === null || elementToClick === void 0 ? void 0 : elementToClick.click();
175
+ }
132
176
  break;
133
177
  }
134
178
  }
@@ -136,6 +180,14 @@ class DesktopSearchBarManager {
136
180
  const input = e.composedPath()[0];
137
181
  this.searchBar.query = input.value;
138
182
  }
183
+ onClick() {
184
+ this.onFocus();
185
+ }
186
+ onFocus() {
187
+ if (this.searchBar.reactToFocus) {
188
+ this.searchBar.displaySuggestListbox = true;
189
+ }
190
+ }
139
191
  }
140
192
  //language=css
141
193
  DesktopSearchBarManager.styles = css `
@@ -9,6 +9,7 @@ class MobileSearchBarManager {
9
9
  this.suggestManager = suggestManager !== null && suggestManager !== void 0 ? suggestManager : new SuggestManager(searchBar);
10
10
  }
11
11
  render() {
12
+ var _a;
12
13
  const rootClasses = {
13
14
  "ft-search-bar--container": true,
14
15
  "ft-search-bar--mobile": true,
@@ -21,6 +22,11 @@ class MobileSearchBarManager {
21
22
  <div class="ft-search-bar--input-container" part="input-container">
22
23
  <div class="ft-search-bar--input-outline" part="input-outline">
23
24
  <input class="ft-search-bar--input ft-typography--body2"
25
+ role="combobox"
26
+ aria-autocomplete="list"
27
+ aria-controls="${this.suggestManager.listboxId}"
28
+ aria-expanded="${this.searchBar.displaySuggestListbox}"
29
+ aria-activedescendant="${(_a = this.searchBar.ariaActiveDescendent) !== null && _a !== void 0 ? _a : nothing}"
24
30
  part="input"
25
31
  type="search"
26
32
  placeholder="${this.searchBar.labelResolver.resolve("inputPlaceHolder")}"
@@ -91,8 +97,40 @@ class MobileSearchBarManager {
91
97
  }
92
98
  onSearchBarKeyDown(e) {
93
99
  var _a;
94
- if (e.key === "Enter") {
95
- (_a = this.searchBar.launchSearchButton) === null || _a === void 0 ? void 0 : _a.click();
100
+ switch (e.key) {
101
+ case "ArrowDown":
102
+ e.stopPropagation();
103
+ e.preventDefault();
104
+ this.suggestManager.focusNextSuggestion();
105
+ break;
106
+ case "ArrowUp":
107
+ e.stopPropagation();
108
+ e.preventDefault();
109
+ this.suggestManager.focusPreviousSuggestion();
110
+ break;
111
+ case "ArrowLeft":
112
+ if (this.searchBar.selectedSuggestOptionId) {
113
+ e.stopPropagation();
114
+ e.preventDefault();
115
+ this.suggestManager.focusArrowLeft();
116
+ }
117
+ break;
118
+ case "ArrowRight":
119
+ if (this.searchBar.selectedSuggestOptionId) {
120
+ e.stopPropagation();
121
+ e.preventDefault();
122
+ this.suggestManager.focusArrowRight();
123
+ }
124
+ break;
125
+ case "Enter":
126
+ if (this.searchBar.selectedSuggestRemoveRecent) {
127
+ (_a = this.suggestManager.selectedSuggestRemoveRecentButton) === null || _a === void 0 ? void 0 : _a.click();
128
+ }
129
+ else {
130
+ const elementToClick = this.suggestManager.selectedSuggestOptionLink || this.searchBar.launchSearchButton;
131
+ elementToClick === null || elementToClick === void 0 ? void 0 : elementToClick.click();
132
+ }
133
+ break;
96
134
  }
97
135
  }
98
136
  onInput(e) {
@@ -1,20 +1,30 @@
1
1
  import type { FtSearchBar } from "../ft-search-bar";
2
2
  export declare class SuggestManager {
3
+ listboxId: string;
3
4
  private searchBar;
4
5
  private updateDebouncer;
5
6
  constructor(searchBar: FtSearchBar, debounceTime?: number);
6
7
  static styles: import("lit").CSSResult[];
7
8
  render(): import("lit-html").TemplateResult<1>;
9
+ private recentSearchId;
10
+ private suggestionId;
8
11
  private getRequestWithQuery;
9
12
  update(): Promise<void>;
10
- private onSuggestKeyDown;
11
- private nextSuggestionElement;
12
- private previousSuggestionElement;
13
13
  private onSuggestClick;
14
14
  private removeRecentSearch;
15
15
  private getIcon;
16
- private getFocusedSuggestionElement;
17
- private getLastSuggestionElement;
16
+ focusNextSuggestion(): void;
17
+ focusPreviousSuggestion(): void;
18
+ private nextSuggestionElement;
18
19
  private getFirstSuggestionElement;
19
- focusFirstSuggestion(): void;
20
+ private previousSuggestionElement;
21
+ private get selectedSuggestOption();
22
+ get selectedSuggestOptionLink(): HTMLElement | null;
23
+ get selectedSuggestRemoveRecentButton(): HTMLElement | null;
24
+ private getLastSuggestionElement;
25
+ private selectSuggestion;
26
+ focusArrowLeft(): void;
27
+ focusArrowRight(): void;
28
+ get shouldDisplaySuggestions(): boolean;
29
+ get recentSearchesMatchingQuery(): string[];
20
30
  }
@@ -1,27 +1,37 @@
1
- import { css, html } from "lit";
1
+ import { css, html, nothing } from "lit";
2
2
  import { repeat } from "lit/directives/repeat.js";
3
3
  import { FtIcons, FtIconVariants, resolveFileFormatIcon } from "@fluid-topics/ft-icon";
4
- import { Debouncer, wordWrap } from "@fluid-topics/ft-wc-utils";
4
+ import { Debouncer, setVariable, wordWrap } from "@fluid-topics/ft-wc-utils";
5
5
  import { FtSearchBarCssVariables } from "../ft-search-bar.styles";
6
+ import { FtRippleCssVariables } from "@fluid-topics/ft-ripple";
6
7
  class SuggestManager {
7
8
  constructor(searchBar, debounceTime = 300) {
9
+ this.listboxId = "suggestManager";
8
10
  this.searchBar = searchBar;
9
11
  this.updateDebouncer = new Debouncer(debounceTime);
10
12
  }
11
13
  render() {
12
- const filteredRecentSearches = this.searchBar.recentSearches.filter(q => q.toLowerCase().includes(this.searchBar.query.toLowerCase()));
13
- const shouldDisplaySuggestions = this.searchBar.suggestions.length > 0 || filteredRecentSearches.length > 0;
14
+ const filteredRecentSearches = this.recentSearchesMatchingQuery;
14
15
  return html `
15
- <div class="ft-search-bar--suggestions ft-word-wrap ${shouldDisplaySuggestions ? "ft-search-bar--suggestions-not-empty" : ""}"
16
- part="suggestions-container"
17
- @keydown=${(e) => this.onSuggestKeyDown(e)}>
18
- ${repeat(filteredRecentSearches.slice(0, 5), query => query, query => html `
19
- <div part="suggestion-container">
16
+ <div class="ft-search-bar--suggestions ft-word-wrap ${this.shouldDisplaySuggestions ? "ft-search-bar--suggestions-not-empty" : ""}"
17
+ id="${this.listboxId}"
18
+ role="listbox"
19
+ aria-label="${this.searchBar.labelResolver.resolve("suggestionsAriaLabel")}"
20
+ part="suggestions-container">
21
+ ${repeat(filteredRecentSearches.slice(0, 5), query => query, (query, index) => html `
22
+ <div part="suggestion-container"
23
+ class=${this.searchBar.selectedSuggestOptionId === this.recentSearchId(index) ? "ft-search-bar--suggestions-selected" : nothing}>
20
24
  <a href="${this.getRequestWithQuery(query)}"
21
25
  part="suggestions"
22
26
  class="ft-search-bar--suggestion ft-search-bar--recent-search"
27
+ role="option"
28
+ id="${this.recentSearchId(index)}"
29
+ aria-selected="${this.searchBar.selectedSuggestOptionId === this.recentSearchId(index)}"
30
+ tabindex="-1"
31
+ aria-label="${query}"
23
32
  @click=${(e) => this.onSuggestClick(e, query)}>
24
- <ft-ripple></ft-ripple>
33
+ <ft-ripple ?activated=${this.searchBar.selectedSuggestOptionId === this.recentSearchId(index)
34
+ && !this.searchBar.selectedSuggestRemoveRecent}></ft-ripple>
25
35
  <ft-icon variant="material" value="history" part="suggestion-icon"></ft-icon>
26
36
  <ft-typography variant="body1">${query}</ft-typography>
27
37
  </a>
@@ -29,19 +39,28 @@ class SuggestManager {
29
39
  round
30
40
  part="remove-suggestion"
31
41
  ?dense=${!this.searchBar.isMobile}
42
+ id="remove-${this.recentSearchId(index)}"
32
43
  label="${this.searchBar.labelResolver.resolve("removeRecentSearch", query)}"
33
44
  tooltipPosition="left"
45
+ tabindex="-1"
46
+ ?activated=${this.searchBar.selectedSuggestOptionId === this.recentSearchId(index)
47
+ && this.searchBar.selectedSuggestRemoveRecent}
34
48
  @click=${(e) => this.removeRecentSearch(e, query)}>
35
49
  </ft-button>
36
50
  </div>
37
51
  `)}
38
- ${repeat(this.searchBar.suggestions, suggest => suggest.value, suggest => html `
39
- <div part="suggestion-container">
52
+ ${repeat(this.searchBar.suggestions, suggest => suggest.value, (suggest, index) => html `
53
+ <div part="suggestion-container"
54
+ class=${this.searchBar.selectedSuggestOptionId === this.suggestionId(index) ? "ft-search-bar--suggestions-selected" : nothing}>
40
55
  <a href="${(this.getRequestWithQuery(suggest.value))}"
41
56
  part="suggestions"
42
57
  class="ft-search-bar--suggestion"
58
+ id="${this.suggestionId(index)}"
59
+ aria-selected="${this.searchBar.selectedSuggestOptionId === this.suggestionId(index)}"
60
+ role="option"
61
+ tabindex="-1"
43
62
  @click=${(e) => this.onSuggestClick(e, suggest.value)}>
44
- <ft-ripple></ft-ripple>
63
+ <ft-ripple ?activated=${this.searchBar.selectedSuggestOptionId === this.suggestionId(index)}></ft-ripple>
45
64
  ${this.getIcon(suggest)}
46
65
  <ft-typography variant="body1">${suggest.value}</ft-typography>
47
66
  </a>
@@ -50,6 +69,12 @@ class SuggestManager {
50
69
  </div>
51
70
  `;
52
71
  }
72
+ recentSearchId(index) {
73
+ return this.listboxId + "-recent-" + index;
74
+ }
75
+ suggestionId(index) {
76
+ return this.listboxId + "-suggest-" + index;
77
+ }
53
78
  getRequestWithQuery(query) {
54
79
  return this.searchBar.searchRequestSerializer({
55
80
  ...this.searchBar.request,
@@ -67,44 +92,14 @@ class SuggestManager {
67
92
  });
68
93
  });
69
94
  }
70
- onSuggestKeyDown(e) {
71
- var _a, _b;
72
- switch (e.key) {
73
- case "ArrowUp":
74
- (_a = this.previousSuggestionElement()) === null || _a === void 0 ? void 0 : _a.focus();
75
- e.preventDefault();
76
- e.stopPropagation();
77
- break;
78
- case "ArrowDown":
79
- (_b = this.nextSuggestionElement()) === null || _b === void 0 ? void 0 : _b.focus();
80
- e.preventDefault();
81
- e.stopPropagation();
82
- break;
83
- }
84
- }
85
- nextSuggestionElement() {
86
- var _a, _b;
87
- const divElement = (_a = this.getFocusedSuggestionElement()) === null || _a === void 0 ? void 0 : _a.parentElement;
88
- const nextDivElement = (_b = divElement === null || divElement === void 0 ? void 0 : divElement.nextElementSibling) === null || _b === void 0 ? void 0 : _b.querySelector("[part=suggestions]");
89
- return nextDivElement !== null && nextDivElement !== void 0 ? nextDivElement : this.getFirstSuggestionElement();
90
- }
91
- previousSuggestionElement() {
92
- var _a, _b;
93
- const divElement = (_a = this.getFocusedSuggestionElement()) === null || _a === void 0 ? void 0 : _a.parentElement;
94
- const nextDivElement = (_b = divElement === null || divElement === void 0 ? void 0 : divElement.previousElementSibling) === null || _b === void 0 ? void 0 : _b.querySelector("[part=suggestions]");
95
- return nextDivElement !== null && nextDivElement !== void 0 ? nextDivElement : this.getLastSuggestionElement();
96
- }
97
95
  onSuggestClick(e, suggest) {
98
96
  this.searchBar.setQuery(suggest);
99
97
  this.searchBar.onLaunchSearch();
100
98
  }
101
99
  removeRecentSearch(e, query) {
102
- var _a, _b, _c, _d;
103
100
  e.preventDefault();
104
101
  e.stopPropagation();
105
- let currentFocusElement = e.target.closest("[part='suggestion-container']");
106
- const thingToFocus = (_d = (_b = (_a = currentFocusElement === null || currentFocusElement === void 0 ? void 0 : currentFocusElement.previousElementSibling) === null || _a === void 0 ? void 0 : _a.querySelector("[part='remove-suggestion']")) !== null && _b !== void 0 ? _b : (_c = currentFocusElement === null || currentFocusElement === void 0 ? void 0 : currentFocusElement.nextElementSibling) === null || _c === void 0 ? void 0 : _c.querySelector("[part='remove-suggestion']")) !== null && _d !== void 0 ? _d : this.searchBar.input;
107
- thingToFocus === null || thingToFocus === void 0 ? void 0 : thingToFocus.focus();
102
+ this.selectSuggestion(null);
108
103
  this.searchBar.recentSearches = this.searchBar.recentSearches.filter(q => q.toLowerCase() !== query.toLowerCase());
109
104
  this.searchBar.saveRecentSearches();
110
105
  }
@@ -126,19 +121,75 @@ class SuggestManager {
126
121
  <ft-icon .variant="${iconVariant}" .value="${icon}" part="suggestion-icon"></ft-icon>
127
122
  `;
128
123
  }
129
- getFocusedSuggestionElement() {
130
- return this.searchBar.querySelector(".ft-search-bar--suggestion:focus-within");
124
+ focusNextSuggestion() {
125
+ this.selectSuggestion(this.nextSuggestionElement());
131
126
  }
132
- getLastSuggestionElement() {
133
- let suggestions = this.searchBar.querySelectorAll(".ft-search-bar--suggestion");
134
- return suggestions.length > 0 ? suggestions[suggestions.length - 1] : null;
127
+ focusPreviousSuggestion() {
128
+ this.selectSuggestion(this.previousSuggestionElement());
129
+ }
130
+ nextSuggestionElement() {
131
+ const divElement = this.selectedSuggestOption;
132
+ if (!divElement) {
133
+ return this.getFirstSuggestionElement();
134
+ }
135
+ return divElement === null || divElement === void 0 ? void 0 : divElement.nextElementSibling;
135
136
  }
136
137
  getFirstSuggestionElement() {
137
- return this.searchBar.querySelector(".ft-search-bar--suggestion");
138
+ return this.searchBar.querySelector("[part=suggestion-container]");
139
+ }
140
+ previousSuggestionElement() {
141
+ const divElement = this.selectedSuggestOption;
142
+ if (!divElement) {
143
+ return this.getLastSuggestionElement();
144
+ }
145
+ return divElement === null || divElement === void 0 ? void 0 : divElement.previousElementSibling;
138
146
  }
139
- focusFirstSuggestion() {
147
+ get selectedSuggestOption() {
140
148
  var _a;
141
- (_a = this.getFirstSuggestionElement()) === null || _a === void 0 ? void 0 : _a.focus();
149
+ return (_a = this.searchBar.querySelector("[id='" + this.searchBar.selectedSuggestOptionId + "']")) === null || _a === void 0 ? void 0 : _a.parentElement;
150
+ }
151
+ get selectedSuggestOptionLink() {
152
+ return this.searchBar.querySelector("[id='" + this.searchBar.selectedSuggestOptionId + "']");
153
+ }
154
+ get selectedSuggestRemoveRecentButton() {
155
+ var _a;
156
+ return (_a = this.selectedSuggestOption) === null || _a === void 0 ? void 0 : _a.querySelector("[part=remove-suggestion]");
157
+ }
158
+ getLastSuggestionElement() {
159
+ let suggestions = this.searchBar.querySelectorAll("[part=suggestion-container]");
160
+ return suggestions.length > 0 ? suggestions[suggestions.length - 1] : null;
161
+ }
162
+ selectSuggestion(element) {
163
+ var _a;
164
+ this.searchBar.selectedSuggestRemoveRecent = false;
165
+ if (element) {
166
+ this.searchBar.selectedSuggestOptionId = (_a = element.querySelector("[part=suggestions]")) === null || _a === void 0 ? void 0 : _a.id;
167
+ }
168
+ else {
169
+ this.searchBar.selectedSuggestOptionId = undefined;
170
+ }
171
+ }
172
+ focusArrowLeft() {
173
+ if (this.searchBar.selectedSuggestRemoveRecent) {
174
+ this.searchBar.selectedSuggestRemoveRecent = false;
175
+ }
176
+ else {
177
+ this.selectSuggestion(null);
178
+ }
179
+ }
180
+ focusArrowRight() {
181
+ if (!this.searchBar.selectedSuggestRemoveRecent && this.selectedSuggestRemoveRecentButton) {
182
+ this.searchBar.selectedSuggestRemoveRecent = true;
183
+ }
184
+ else {
185
+ this.selectSuggestion(null);
186
+ }
187
+ }
188
+ get shouldDisplaySuggestions() {
189
+ return this.searchBar.displaySuggestListbox && (this.searchBar.suggestions.length > 0 || this.recentSearchesMatchingQuery.length > 0);
190
+ }
191
+ get recentSearchesMatchingQuery() {
192
+ return this.searchBar.recentSearches.filter(q => q.toLowerCase().includes(this.searchBar.query.toLowerCase()));
142
193
  }
143
194
  }
144
195
  //language=css
@@ -179,7 +230,7 @@ SuggestManager.styles = [
179
230
  top: calc(100% + 2px);
180
231
  }
181
232
 
182
- .ft-search-bar--react-to-focus .ft-search-bar--input-container:focus-within .ft-search-bar--suggestions-not-empty {
233
+ .ft-search-bar--input-container .ft-search-bar--suggestions-not-empty {
183
234
  display: block;
184
235
  }
185
236
 
@@ -188,6 +239,14 @@ SuggestManager.styles = [
188
239
  align-items: center;
189
240
  }
190
241
 
242
+ [part~="suggestion-container"].ft-search-bar--suggestions-selected {
243
+ outline: none;
244
+ box-shadow: inset 3px 0 0 ${FtSearchBarCssVariables.activeItemBorderColor};
245
+ }
246
+ [part~="suggestion-container"]:hover {
247
+ box-shadow: inset 3px 0 0 ${FtSearchBarCssVariables.activeItemBorderColor};
248
+ }
249
+
191
250
  [part~="remove-suggestion"] {
192
251
  margin-left: auto;
193
252
  }
@@ -213,10 +272,6 @@ SuggestManager.styles = [
213
272
  min-height: 44px;
214
273
  }
215
274
 
216
- .ft-search-bar--suggestion:focus {
217
- outline: none;
218
- }
219
-
220
275
  .ft-search-bar--recent-search + .ft-search-bar--suggestion:not(.ft-search-bar--recent-search) {
221
276
  border-top: 1px solid ${FtSearchBarCssVariables.colorOutline};
222
277
  }
@@ -226,6 +281,10 @@ SuggestManager.styles = [
226
281
  flex-grow: 1;
227
282
  flex-shrink: 1;
228
283
  }
284
+
285
+ ft-ripple {
286
+ ${setVariable(FtRippleCssVariables.opacityContentOnSurfaceHover, FtRippleCssVariables.opacityContentOnSurfaceSelected)}
287
+ }
229
288
  `,
230
289
  ];
231
290
  export { SuggestManager };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-topics/ft-search-bar",
3
- "version": "1.2.60",
3
+ "version": "1.2.62",
4
4
  "description": "Search bar component using Fluid Topics public API",
5
5
  "keywords": [
6
6
  "Lit"
@@ -19,23 +19,23 @@
19
19
  "url": "ssh://git@scm.mrs.antidot.net:2222/fluidtopics/ft-web-components.git"
20
20
  },
21
21
  "dependencies": {
22
- "@fluid-topics/ft-accordion": "1.2.60",
23
- "@fluid-topics/ft-app-context": "1.2.60",
24
- "@fluid-topics/ft-button": "1.2.60",
25
- "@fluid-topics/ft-chip": "1.2.60",
26
- "@fluid-topics/ft-filter": "1.2.60",
27
- "@fluid-topics/ft-icon": "1.2.60",
28
- "@fluid-topics/ft-select": "1.2.60",
29
- "@fluid-topics/ft-size-watcher": "1.2.60",
30
- "@fluid-topics/ft-skeleton": "1.2.60",
31
- "@fluid-topics/ft-snap-scroll": "1.2.60",
32
- "@fluid-topics/ft-tooltip": "1.2.60",
33
- "@fluid-topics/ft-typography": "1.2.60",
34
- "@fluid-topics/ft-wc-utils": "1.2.60",
22
+ "@fluid-topics/ft-accordion": "1.2.62",
23
+ "@fluid-topics/ft-app-context": "1.2.62",
24
+ "@fluid-topics/ft-button": "1.2.62",
25
+ "@fluid-topics/ft-chip": "1.2.62",
26
+ "@fluid-topics/ft-filter": "1.2.62",
27
+ "@fluid-topics/ft-icon": "1.2.62",
28
+ "@fluid-topics/ft-select": "1.2.62",
29
+ "@fluid-topics/ft-size-watcher": "1.2.62",
30
+ "@fluid-topics/ft-skeleton": "1.2.62",
31
+ "@fluid-topics/ft-snap-scroll": "1.2.62",
32
+ "@fluid-topics/ft-tooltip": "1.2.62",
33
+ "@fluid-topics/ft-typography": "1.2.62",
34
+ "@fluid-topics/ft-wc-utils": "1.2.62",
35
35
  "lit": "3.1.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@fluid-topics/public-api": "1.0.94"
38
+ "@fluid-topics/public-api": "1.0.95"
39
39
  },
40
- "gitHead": "5acbf0235057ab34c306052ddba1e8f500f710bc"
40
+ "gitHead": "6d62bc761fc79063b748e91a4580734fd1329077"
41
41
  }