Started on a live-preview on global search input

This commit is contained in:
Dan Brown 2022-11-14 10:24:14 +00:00
parent a1b1f8138a
commit 19a792bc12
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
8 changed files with 107 additions and 22 deletions

View File

@ -11,7 +11,7 @@ use Illuminate\Http\Request;
class SearchController extends Controller
{
protected $searchRunner;
protected SearchRunner $searchRunner;
public function __construct(SearchRunner $searchRunner)
{

View File

@ -0,0 +1,47 @@
/**
* @extends {Component}
*/
import {htmlToDom} from "../services/dom";
class GlobalSearch {
setup() {
this.input = this.$refs.input;
this.suggestions = this.$refs.suggestions;
this.suggestionResultsWrap = this.$refs.suggestionResults;
this.setupListeners();
}
setupListeners() {
this.input.addEventListener('input', () => {
const value = this.input.value;
if (value.length > 0) {
this.updateSuggestions(value);
} else {
this.hideSuggestions();
}
});
}
async updateSuggestions(search) {
const {data: results} = await window.$http.get('/ajax/search/entities', {term: search, count: 5});
const resultDom = htmlToDom(results);
const childrenToTrim = Array.from(resultDom.children).slice(9);
for (const child of childrenToTrim) {
child.remove();
}
this.suggestions.style.display = 'block';
this.suggestionResultsWrap.innerHTML = '';
this.suggestionResultsWrap.append(resultDom);
}
hideSuggestions() {
this.suggestions.style.display = null;
this.suggestionResultsWrap.innerHTML = '';
}
}
export default GlobalSearch;

View File

@ -57,6 +57,7 @@ import triLayout from "./tri-layout.js"
import userSelect from "./user-select.js"
import webhookEvents from "./webhook-events";
import wysiwygEditor from "./wysiwyg-editor.js"
import globalSearch from "./global-search";
const componentMapping = {
"add-remove-rows": addRemoveRows,
@ -86,6 +87,7 @@ const componentMapping = {
"entity-selector-popup": entitySelectorPopup,
"event-emit-select": eventEmitSelect,
"expand-toggle": expandToggle,
"global-search": globalSearch,
"header-mobile-toggle": headerMobileToggle,
"homepage-control": homepageControl,
"image-manager": imageManager,

View File

@ -86,11 +86,13 @@
.card-title a {
line-height: 1;
}
.card-footer-link {
.card-footer-link, button.card-footer-link {
display: block;
padding: $-s $-m;
line-height: 1;
border-top: 1px solid;
width: 100%;
text-align: left;
@include lightDark(border-color, #DDD, #555);
border-radius: 0 0 3px 3px;
font-size: 0.9em;

View File

@ -1010,4 +1010,31 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
border: 1px solid #b4b4b4;
box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
color: #333;
}
.global-search-suggestions {
display: none;
position: absolute;
top: -$-s;
left: 0;
right: 0;
z-index: -1;
margin-left: -$-xxl;
margin-right: -$-xxl;
padding-top: 56px;
border-radius: 3px;
box-shadow: $bs-hover;
.entity-item-snippet p {
display: none;
}
.entity-item-snippet {
font-size: .8rem;
}
.entity-list-item-name {
font-size: .9rem;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
}

View File

@ -412,7 +412,7 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] {
.search-box {
max-width: 100%;
position: relative;
button {
button[tabindex="-1"] {
background-color: transparent;
border: none;
@include lightDark(color, #666, #AAA);

View File

@ -108,21 +108,6 @@ header .search-box {
border: 1px solid rgba(255, 255, 255, 0.4);
}
}
button {
z-index: 1;
left: 16px;
top: 10px;
color: #FFF;
opacity: 0.6;
@include lightDark(color, rgba(255, 255, 255, 0.8), #AAA);
@include rtl {
left: auto;
right: 16px;
}
svg {
margin-block-end: 0;
}
}
input::placeholder {
color: #FFF;
opacity: 0.6;
@ -130,10 +115,25 @@ header .search-box {
@include between($l, $xl) {
max-width: 200px;
}
&:focus-within button {
&:focus-within #header-search-box-button {
opacity: 1;
}
}
#header-search-box-button {
z-index: 1;
left: 16px;
top: 10px;
color: #FFF;
opacity: 0.6;
@include lightDark(color, rgba(255, 255, 255, 0.8), #AAA);
@include rtl {
left: auto;
right: 16px;
}
svg {
margin-block-end: 0;
}
}
.logo {
display: inline-flex;

View File

@ -19,12 +19,19 @@
<div class="flex-container-column items-center justify-center hide-under-l">
@if (hasAppAccess())
<form action="{{ url('/search') }}" method="GET" class="search-box" role="search">
<form component="global-search" action="{{ url('/search') }}" method="GET" class="search-box" role="search">
<button id="header-search-box-button" type="submit" aria-label="{{ trans('common.search') }}" tabindex="-1">@icon('search') </button>
<input id="header-search-box-input" type="text" name="term"
<input id="header-search-box-input"
refs="global-search@input"
type="text"
name="term"
data-shortcut="global_search"
aria-label="{{ trans('common.search') }}" placeholder="{{ trans('common.search') }}"
value="{{ isset($searchTerm) ? $searchTerm : '' }}">
value="{{ $searchTerm ?? '' }}">
<div refs="global-search@suggestions" class="global-search-suggestions card">
<div refs="global-search@suggestion-results" class="px-m"></div>
<button class="text-button card-footer-link" type="submit">{{ trans('common.view_all') }}</button>
</div>
</form>
@endif
</div>