mirror of
https://github.com/StarCitizenTools/mediawiki-skins-Citizen.git
synced 2024-11-14 18:15:49 +00:00
feat(search): ✨ add empty state to typeahead
This is a barebone initial implementation, more work will come to it
This commit is contained in:
parent
501286a15d
commit
9bf737f720
|
@ -15,10 +15,41 @@
|
|||
// Well this won't be loaded before .citizen-animation-ready anyways
|
||||
.citizen-card-transition();
|
||||
|
||||
&__placeholder {
|
||||
.citizen-typeahead {
|
||||
&__content {
|
||||
flex-direction: column;
|
||||
padding: var( --space-xl ) 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__thumbnail {
|
||||
margin-bottom: var( --space-sm );
|
||||
|
||||
img,
|
||||
source {
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__item {
|
||||
&--active {
|
||||
background-color: var( --background-color-primary--hover );
|
||||
}
|
||||
|
||||
.citizen-typeahead {
|
||||
&__thumbnail {
|
||||
margin-right: var( --space-sm );
|
||||
background-color: #eaecf0;
|
||||
|
||||
img,
|
||||
source {
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
|
@ -31,13 +62,15 @@
|
|||
|
||||
&__thumbnail {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
max-width: 70px;
|
||||
height: 60px;
|
||||
border-radius: var( --border-radius--medium );
|
||||
background-color: #eaecf0;
|
||||
|
||||
img,
|
||||
source {
|
||||
object-fit: cover;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,16 +127,9 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
picture {
|
||||
width: 100%;
|
||||
max-width: 70px;
|
||||
margin-right: 0.75rem;
|
||||
|
||||
img,
|
||||
source {
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
}
|
||||
&__actions {
|
||||
position: absolute;
|
||||
right: var( --space-sm );
|
||||
}
|
||||
|
||||
&__keyboard {
|
||||
|
@ -116,9 +142,23 @@
|
|||
&--expanded {
|
||||
.citizen-card-show( false );
|
||||
}
|
||||
|
||||
&--hasQuery {
|
||||
.citizen-typeahead {
|
||||
&__placeholder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#citizen-typeahead-fulltext {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#citizen-typeahead-footer {
|
||||
#citizen-typeahead-fulltext {
|
||||
display: none;
|
||||
|
||||
.citizen-typeahead {
|
||||
&__content {
|
||||
padding: var( --space-md ) 0;
|
||||
|
@ -126,8 +166,9 @@
|
|||
}
|
||||
|
||||
&__thumbnail {
|
||||
width: 70px; // Sync with thumbnail
|
||||
height: var( --size-icon );
|
||||
background: transparent;
|
||||
background-color: transparent;
|
||||
|
||||
img {
|
||||
object-fit: contain;
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
{{!
|
||||
string msg-citizen-search-fulltext The label on the fulltext search in the typeahead.
|
||||
string msg-citizen-search-toggle Search toggle label
|
||||
}}
|
||||
|
||||
<ol id="searchform-suggestions" class="citizen-typeahead" role="listbox">
|
||||
<li role="option" id="citizen-typeahead-footer" class="citizen-typeahead__item">
|
||||
<a href="" class="citizen-typeahead__content">
|
||||
{{! Empty state }}
|
||||
<li class="citizen-typeahead__placeholder">
|
||||
<div class="citizen-typeahead__content">
|
||||
<picture class="citizen-typeahead__thumbnail">
|
||||
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMCAyMCI+DQoJPHBhdGggZmlsbD0iIzM2YyIgZD0iTTcuNSAxM2MzLjA0IDAgNS41LTIuNDYgNS41LTUuNVMxMC41NCAyIDcuNSAyIDIgNC40NiAyIDcuNSA0LjQ2IDEzIDcuNSAxM3ptNC41NS40NkE3LjQzMiA3LjQzMiAwIDAgMSA3LjUgMTVDMy4zNiAxNSAwIDExLjY0IDAgNy41UzMuMzYgMCA3LjUgMEMxMS42NCAwIDE1IDMuMzYgMTUgNy41YzAgMS43MS0uNTcgMy4yOS0xLjU0IDQuNTVsNi40OSA2LjQ5LTEuNDEgMS40MS02LjQ5LTYuNDl6Ii8+DQoJPHBhdGggZmlsbD0iIzM2YyIgZD0iTTQgNWg3djFINHptMCAyaDd2MUg0em0wIDJoNS40NDR2MUg0eiIvPg0KPC9zdmc+DQo="/>
|
||||
</picture>
|
||||
<div class="citizen-typeahead__text">
|
||||
<div class="citizen-typeahead__description">{{{msg-citizen-search-fulltext}}}</div>
|
||||
<div class="citizen-typeahead__title">{{msg-searchsuggest-search}}</div>
|
||||
<div class="citizen-typeahead__description">{{msg-citizen-search-fulltext-empty}}</div>
|
||||
</div>
|
||||
<div class="citizen-typeahead__actions">
|
||||
<div class="citizen-typeahead__keyboard">↵</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
{{! Template }}
|
||||
<template id="citizen-typeahead-template">
|
||||
<li role="option" class="citizen-typeahead__item">
|
||||
<a href="" class="citizen-typeahead__content">
|
||||
|
|
|
@ -124,7 +124,7 @@ function bindMouseHoverEvent( element ) {
|
|||
*/
|
||||
function clearSuggestions() {
|
||||
const typeaheadItems = typeahead.children,
|
||||
nonSuggestionCount = 2;
|
||||
nonSuggestionCount = 3;
|
||||
|
||||
if ( typeaheadItems.length > nonSuggestionCount ) {
|
||||
// Splice would be cleaner but it is slower (?)
|
||||
|
@ -210,7 +210,8 @@ function getSuggestions( searchQuery ) {
|
|||
thumbnail: result.thumbnail ?? '',
|
||||
title: highlightTitle( result.title ),
|
||||
label: getRedirectLabel( result.title, result.matchedTitle ),
|
||||
description: result.description
|
||||
// Just to be safe, not sure if the default API is HTML escaped
|
||||
description: mw.html.escape( result.description )
|
||||
} );
|
||||
|
||||
fragment.append( suggestion );
|
||||
|
@ -270,25 +271,33 @@ function getMenuItem( data ) {
|
|||
}
|
||||
|
||||
const
|
||||
item = template.content.cloneNode( true ),
|
||||
link = item.querySelector( '.' + PREFIX + '__content' ),
|
||||
thumbnail = item.querySelector( '.' + PREFIX + '__thumbnail img' ),
|
||||
title = item.querySelector( '.' + PREFIX + '__title' ),
|
||||
label = item.querySelector( '.' + PREFIX + '__label' ),
|
||||
description = item.querySelector( '.' + PREFIX + '__description' );
|
||||
fragment = template.content.cloneNode( true ),
|
||||
item = fragment.querySelector( '.' + PREFIX + '__item' ),
|
||||
title = fragment.querySelector( '.' + PREFIX + '__title' ),
|
||||
label = fragment.querySelector( '.' + PREFIX + '__label' ),
|
||||
description = fragment.querySelector( '.' + PREFIX + '__description' );
|
||||
|
||||
if ( data.id ) {
|
||||
item.setAttribute( 'id', data.id );
|
||||
}
|
||||
if ( data.link ) {
|
||||
const link = fragment.querySelector( '.' + PREFIX + '__content' );
|
||||
link.setAttribute( 'href', data.link );
|
||||
}
|
||||
if ( data.icon ) {
|
||||
// FIXME: This is temporary, we need to replace picture elements with background-image because of a11y concern
|
||||
const thumbnailContainer = fragment.querySelector( '.' + PREFIX + '__thumbnail' );
|
||||
thumbnailContainer.classList.add( 'citizen-ui-icon', 'mw-ui-icon-wikimedia-' + data.icon );
|
||||
}
|
||||
if ( data.thumbnail ) {
|
||||
const thumbnail = fragment.querySelector( '.' + PREFIX + '__thumbnail img' );
|
||||
thumbnail.setAttribute( 'src', data.thumbnail );
|
||||
}
|
||||
title.innerHTML = data.title ?? '';
|
||||
label.innerHTML = data.label ?? '';
|
||||
// Description only contains text
|
||||
description.textContent = data.description ?? '';
|
||||
description.innerHTML = data.description ?? '';
|
||||
|
||||
return item;
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -298,21 +307,40 @@ function getMenuItem( data ) {
|
|||
* @return {void}
|
||||
*/
|
||||
function updateTypeahead( messages ) {
|
||||
const searchQuery = searchInput.value,
|
||||
footer = document.getElementById( PREFIX + '-footer' ),
|
||||
footerLink = footer.querySelector( '.' + PREFIX + '__content' ),
|
||||
footerText = footer.querySelector( '.' + PREFIX + '__description' ),
|
||||
fullTextUrl = config.wgScriptPath + '/index.php?title=Special:Search&fulltext=1&search=';
|
||||
const
|
||||
searchQuery = searchInput.value,
|
||||
queryClass = PREFIX + '--hasQuery';
|
||||
|
||||
const updateFullTextSearchItem = () => {
|
||||
const
|
||||
// Should this be handled differently since it is escaped a few times?
|
||||
query = mw.html.escape( searchQuery ),
|
||||
fulltextId = PREFIX + '-fulltext',
|
||||
fulltextEl = document.getElementById( fulltextId ),
|
||||
fulltextText = messages.fulltext + ' <strong>' + query + '</strong>';
|
||||
|
||||
const item = getMenuItem( {
|
||||
icon: 'articleSearch',
|
||||
id: fulltextId,
|
||||
link: config.wgScriptPath + '/index.php?title=Special:Search&fulltext=1&search=' + query,
|
||||
description: fulltextText
|
||||
} );
|
||||
|
||||
// Update existing element instead of creating a new one
|
||||
if ( fulltextEl ) {
|
||||
const description = fulltextEl.querySelector( '.' + PREFIX + '__description' );
|
||||
description.innerHTML = fulltextText;
|
||||
} else {
|
||||
typeahead.prepend( item );
|
||||
}
|
||||
};
|
||||
|
||||
if ( searchQuery.length > 0 ) {
|
||||
const footerQuery = mw.html.escape( searchQuery );
|
||||
footerText.innerHTML = messages.fulltext + ' <strong>' + footerQuery + '</strong>';
|
||||
footerQuery.textContent = searchQuery;
|
||||
footerLink.setAttribute( 'href', fullTextUrl + searchQuery );
|
||||
typeahead.classList.add( queryClass );
|
||||
updateFullTextSearchItem();
|
||||
getSuggestions( searchQuery );
|
||||
} else {
|
||||
footerText.textContent = messages.empty;
|
||||
footerLink.setAttribute( 'href', fullTextUrl );
|
||||
typeahead.classList.remove( queryClass );
|
||||
clearSuggestions();
|
||||
}
|
||||
}
|
||||
|
@ -326,7 +354,6 @@ function initTypeahead( searchForm, input ) {
|
|||
const
|
||||
expandedClass = 'citizen-typeahead--expanded',
|
||||
messages = {
|
||||
empty: mw.message( 'citizen-search-fulltext-empty' ).text(),
|
||||
fulltext: mw.message( 'citizen-search-fulltext' ).text()
|
||||
},
|
||||
template = mw.template.get(
|
||||
|
@ -334,7 +361,8 @@ function initTypeahead( searchForm, input ) {
|
|||
'resources/skins.citizen.search/templates/typeahead.mustache'
|
||||
),
|
||||
data = {
|
||||
'msg-citizen-search-fulltext': messages.empty
|
||||
'msg-searchsuggest-search': mw.message( 'searchsuggest-search' ).text(),
|
||||
'msg-citizen-search-fulltext-empty': mw.message( 'citizen-search-fulltext-empty' ).text()
|
||||
};
|
||||
|
||||
const onBlur = ( event ) => {
|
||||
|
|
|
@ -216,7 +216,8 @@
|
|||
"messages": [
|
||||
"citizen-search-fulltext",
|
||||
"citizen-search-fulltext-empty",
|
||||
"search-redirect"
|
||||
"search-redirect",
|
||||
"searchsuggest-search"
|
||||
],
|
||||
"targets": [
|
||||
"desktop",
|
||||
|
@ -279,6 +280,7 @@
|
|||
"icons": [
|
||||
"article",
|
||||
"articleRedirect",
|
||||
"articleSearch",
|
||||
"block",
|
||||
"collapse",
|
||||
"database",
|
||||
|
|
Loading…
Reference in a new issue