fix(aio): remove `...` separator from search results
An ellipsis was used to separate the most relevant search results from the alphabetic list. The separator was confusing because it was not clear what it represented. This has been removed and the most relevant results are now indicated by styling with a more bold font and a bit of whitespace between them and the rest of the results. To keep things consistent, if there are fewer than 5 results all the results are now displayed as priorityPages. Closes #17233
This commit is contained in:
parent
bb46f54ad7
commit
a4a2901294
|
@ -5,7 +5,7 @@
|
|||
<ng-template #searchResults>
|
||||
<h2 class="visually-hidden">Search Results</h2>
|
||||
<div class="search-area" *ngFor="let area of searchAreas">
|
||||
<h3>{{area.name}} ({{area.pages.length}})</h3>
|
||||
<h3>{{area.name}} ({{area.pages.length + area.priorityPages.length}})</h3>
|
||||
<ul class="priority-pages" >
|
||||
<li class="search-page" *ngFor="let page of area.priorityPages">
|
||||
<a class="search-result-item" href="{{ page.path }}" (click)="onResultSelected(page)">
|
||||
|
@ -13,7 +13,6 @@
|
|||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="more-items material-icons" *ngIf="area.priorityPages.length > 0">more_horiz</div>
|
||||
<ul>
|
||||
<li class="search-page" *ngFor="let page of area.pages">
|
||||
<a class="search-result-item" href="{{ page.path }}" (click)="onResultSelected(page)">
|
||||
|
|
|
@ -33,6 +33,11 @@ describe('SearchResultsComponent', () => {
|
|||
return take === undefined ? results : results.slice(0, take);
|
||||
}
|
||||
|
||||
function compareTitle(l: {title: string}, r: {title: string}) {
|
||||
return l.title.toUpperCase() > r.title.toUpperCase() ? 1 : -1;
|
||||
}
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SearchResultsComponent ],
|
||||
|
@ -54,13 +59,13 @@ describe('SearchResultsComponent', () => {
|
|||
|
||||
searchResults.next({ query: '', results: results});
|
||||
expect(component.searchAreas).toEqual([
|
||||
{ name: 'api', pages: [
|
||||
{ name: 'api', priorityPages: [
|
||||
{ path: 'api/d', title: 'API D', type: '', keywords: '', titleWords: '' }
|
||||
], priorityPages: [] },
|
||||
{ name: 'guide', pages: [
|
||||
], pages: [] },
|
||||
{ name: 'guide', priorityPages: [
|
||||
{ path: 'guide/a', title: 'Guide A', type: '', keywords: '', titleWords: '' },
|
||||
{ path: 'guide/b', title: 'Guide B', type: '', keywords: '', titleWords: '' },
|
||||
], priorityPages: [] }
|
||||
], pages: [] }
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -70,48 +75,35 @@ describe('SearchResultsComponent', () => {
|
|||
{ path: 'tutorial/toh-pt1', title: 'Tutorial - part 1', type: '', keywords: '', titleWords: '' },
|
||||
]});
|
||||
expect(component.searchAreas).toEqual([
|
||||
{ name: 'tutorial', pages: [
|
||||
{ path: 'tutorial/toh-pt1', title: 'Tutorial - part 1', type: '', keywords: '', titleWords: '' },
|
||||
{ name: 'tutorial', priorityPages: [
|
||||
{ path: 'tutorial', title: 'Tutorial index', type: '', keywords: '', titleWords: '' },
|
||||
], priorityPages: [] }
|
||||
{ path: 'tutorial/toh-pt1', title: 'Tutorial - part 1', type: '', keywords: '', titleWords: '' },
|
||||
], pages: [] }
|
||||
]);
|
||||
});
|
||||
|
||||
it('should sort by title within sorted area', () => {
|
||||
const results = getTestResults(5);
|
||||
searchResults.next({ query: '', results: results });
|
||||
|
||||
expect(component.searchAreas).toEqual([
|
||||
{ name: 'api', pages: [
|
||||
{ path: 'api/c', title: 'API C', type: '', keywords: '', titleWords: '' },
|
||||
{ path: 'api/d', title: 'API D', type: '', keywords: '', titleWords: '' },
|
||||
], priorityPages: [] },
|
||||
{ name: 'guide', pages: [
|
||||
{ path: 'guide/a', title: 'Guide A', type: '', keywords: '', titleWords: '' },
|
||||
{ path: 'guide/a/c', title: 'Guide A - C', type: '', keywords: '', titleWords: '' },
|
||||
{ path: 'guide/b', title: 'Guide B', type: '', keywords: '', titleWords: '' },
|
||||
], priorityPages: [] }
|
||||
]);
|
||||
});
|
||||
|
||||
it('should put first 5 area results into priorityPages when more than 10 pages', () => {
|
||||
it('should put first 5 results for each area into priorityPages', () => {
|
||||
const results = getTestResults();
|
||||
const sorted = results.slice().sort((l, r) => l.title > r.title ? 1 : -1);
|
||||
const expected = [
|
||||
{
|
||||
name: 'api',
|
||||
pages: sorted.filter(p => p.path.startsWith('api')),
|
||||
priorityPages: []
|
||||
},
|
||||
{
|
||||
name: 'guide',
|
||||
pages: sorted.filter(p => p.path.startsWith('guide')),
|
||||
priorityPages: results.filter(p => p.path.startsWith('guide')).slice(0, 5)
|
||||
}
|
||||
];
|
||||
|
||||
searchResults.next({ query: '', results: results });
|
||||
expect(component.searchAreas).toEqual(expected);
|
||||
expect(component.searchAreas[0].priorityPages).toEqual(results.filter(p => p.path.startsWith('api')).slice(0, 5));
|
||||
expect(component.searchAreas[1].priorityPages).toEqual(results.filter(p => p.path.startsWith('guide')).slice(0, 5));
|
||||
});
|
||||
|
||||
it('should put the nonPriorityPages into the pages array, sorted by title', () => {
|
||||
const results = getTestResults();
|
||||
searchResults.next({ query: '', results: results });
|
||||
expect(component.searchAreas[0].pages).toEqual([]);
|
||||
expect(component.searchAreas[1].pages).toEqual(results.filter(p => p.path.startsWith('guide')).slice(5).sort(compareTitle));
|
||||
});
|
||||
|
||||
it('should put a total count in the header of each area of search results', () => {
|
||||
const results = getTestResults();
|
||||
searchResults.next({ query: '', results: results });
|
||||
fixture.detectChanges();
|
||||
const headers = fixture.debugElement.queryAll(By.css('h3'));
|
||||
expect(headers.length).toEqual(2);
|
||||
expect(headers[0].nativeElement.textContent).toContain('(2)');
|
||||
expect(headers[1].nativeElement.textContent).toContain('(13)');
|
||||
});
|
||||
|
||||
it('should put search results with no containing folder into the default area (other)', () => {
|
||||
|
@ -121,9 +113,9 @@ describe('SearchResultsComponent', () => {
|
|||
|
||||
searchResults.next({ query: '', results: results });
|
||||
expect(component.searchAreas).toEqual([
|
||||
{ name: 'other', pages: [
|
||||
{ name: 'other', priorityPages: [
|
||||
{ path: 'news', title: 'News', type: 'marketing', keywords: '', titleWords: '' }
|
||||
], priorityPages: [] }
|
||||
], pages: [] }
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -60,8 +60,10 @@ export class SearchResultsComponent implements OnInit, OnDestroy {
|
|||
});
|
||||
const keys = Object.keys(searchAreaMap).sort((l, r) => l > r ? 1 : -1);
|
||||
return keys.map(name => {
|
||||
let pages = searchAreaMap[name];
|
||||
const priorityPages = pages.length > 10 ? searchAreaMap[name].slice(0, 5) : [];
|
||||
let pages: SearchResult[] = searchAreaMap[name];
|
||||
|
||||
// Extract the top 5 most relevant results as priorityPages
|
||||
const priorityPages = pages.splice(0, 5);
|
||||
pages = pages.sort(compareResults);
|
||||
return { name, pages, priorityPages };
|
||||
});
|
||||
|
|
|
@ -55,7 +55,7 @@ aio-search-results {
|
|||
font-size: 14px;
|
||||
color: $lightgray;
|
||||
text-decoration: none;
|
||||
font-weight: 300;
|
||||
font-weight: normal;
|
||||
&:hover {
|
||||
color: $white;
|
||||
}
|
||||
|
@ -68,11 +68,11 @@ aio-search-results {
|
|||
}
|
||||
}
|
||||
|
||||
.more-items {
|
||||
content: 'more_horiz';
|
||||
font-size: 20px;
|
||||
color: $mediumgray;
|
||||
padding: 0;
|
||||
.priority-pages {
|
||||
padding: 0.5rem 0;
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
@include bp(tiny) {
|
||||
|
|
Loading…
Reference in New Issue