mirror of https://github.com/Chocobozzz/PeerTube
Fix search typeahead accessibility
parent
9c215124d1
commit
44eedafed4
|
@ -2,7 +2,7 @@
|
|||
<input
|
||||
type="search" id="search-video" name="search-video" #searchVideo i18n-placeholder placeholder="Search videos, playlists, channels…"
|
||||
[(ngModel)]="search" (ngModelChange)="onSearchChange()" (keydown)="handleKey($event)"
|
||||
autocomplete="off"
|
||||
autocomplete="off" aria-describedby="typeahead-input-help"
|
||||
>
|
||||
|
||||
<button class="border-0 search-button" title="Search" i18n-title (click)="doSearch()">
|
||||
|
@ -17,40 +17,38 @@
|
|||
role="option" aria-selected="true" tabindex="0"
|
||||
(mouseenter)="onSuggestionHover(i)" (click)="onSuggestionClicked(result)" (keyup.enter)="onSuggestionClicked(result)"
|
||||
>
|
||||
<my-suggestion [result]="result" [highlight]="search"></my-suggestion>
|
||||
<my-suggestion
|
||||
[result]="result" [highlight]="search"
|
||||
[describedby]="showSearchGlobalHelp() ? 'typeahead-help' : undefined"
|
||||
></my-suggestion>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- suggestion help, not shown until one of the suggestions is selected and specific to that suggestion -->
|
||||
<div *ngIf="showSearchGlobalHelp()" id="typeahead-help" class="overflow-hidden">
|
||||
<div *ngIf="showSearchGlobalHelp()" id="typeahead-suggestion-help" class="overflow-hidden">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="small-title" i18n>GLOBAL SEARCH</div>
|
||||
<div class="advanced-search-status muted">
|
||||
<span *ngIf="serverConfig" class="me-1" i18n>using {{ serverConfig.search.searchIndex.url }}</span>
|
||||
</div>
|
||||
<div class="small-title mb-2" i18n>GLOBAL SEARCH</div>
|
||||
|
||||
<span *ngIf="serverConfig" class="muted" i18n>using {{ serverConfig.search.searchIndex.url }}</span>
|
||||
</div>
|
||||
|
||||
<div class="muted" i18n>Results will be augmented with those of a third-party index. Only data necessary to make the query will be sent.</div>
|
||||
</div>
|
||||
|
||||
<!-- search instructions, when search input is empty -->
|
||||
<div *ngIf="areInstructionsDisplayed()" id="typeahead-instructions" class="overflow-hidden">
|
||||
<div [hidden]="this.search" id="typeahead-input-help" class="overflow-hidden">
|
||||
<span class="muted" i18n>Your query will be matched against video names or descriptions, channel names.</span>
|
||||
<div class="d-flex justify-content-between mt-3">
|
||||
<div class="small-title" i18n>ADVANCED SEARCH</div>
|
||||
<div class="advanced-search-status c-help">
|
||||
<span [ngClass]="canSearchAnyURI ? 'text-success' : 'muted'" i18n-title title="Determines whether you can resolve any distant content, or if this instance only allows doing so for instances it follows.">
|
||||
<span *ngIf="canSearchAnyURI()" class="me-1" i18n>any instance</span>
|
||||
<span *ngIf="!canSearchAnyURI()" class="me-1" i18n>only followed instances</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 mb-2 small-title" i18n>ADVANCED SEARCH</div>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<em>@channel_id@domain</em> <span class="flex-auto muted" i18n>will list the matching channel</span>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<em>URL</em> <span class="muted" i18n>will list the matching channel</span>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<em>UUID</em> <span class="muted" i18n>will list the matching video</span>
|
||||
</li>
|
||||
|
|
|
@ -37,27 +37,25 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
#typeahead-help,
|
||||
#typeahead-instructions,
|
||||
li.suggestion {
|
||||
#typeahead-suggestion-help,
|
||||
#typeahead-input-help,
|
||||
.suggestion {
|
||||
border: 1px solid pvar(--mainBackgroundColor);
|
||||
background: pvar(--mainBackgroundColor);
|
||||
transition: .3s ease;
|
||||
transition-property: box-shadow;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// soft border-radius for the last suggestion and the link inside
|
||||
&:last-of-type {
|
||||
&,
|
||||
::ng-deep a {
|
||||
#typeahead-suggestion-help,
|
||||
#typeahead-input-help,
|
||||
.suggestion:last-of-type {
|
||||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#typeahead-help,
|
||||
#typeahead-instructions {
|
||||
#typeahead-suggestion-help,
|
||||
#typeahead-input-help {
|
||||
margin-top: 9px;
|
||||
width: 100%;
|
||||
padding: .5rem 1rem;
|
||||
|
@ -110,21 +108,20 @@ li.suggestion {
|
|||
display: none;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
::ng-deep &:focus-within {
|
||||
&:focus-within {
|
||||
> div:last-child {
|
||||
@media screen and (min-width: $mobile-view) {
|
||||
display: initial !important;
|
||||
}
|
||||
|
||||
#typeahead-help,
|
||||
#typeahead-instructions,
|
||||
li.suggestion {
|
||||
#typeahead-suggestion-help,
|
||||
#typeahead-input-help,
|
||||
.suggestion {
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 10px 20px -5px;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep input {
|
||||
input {
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 20px 0;
|
||||
border-end-start-radius: 0;
|
||||
border-end-end-radius: 0;
|
||||
|
@ -136,21 +133,10 @@ li.suggestion {
|
|||
}
|
||||
}
|
||||
|
||||
.advanced-search-status {
|
||||
height: max-content;
|
||||
cursor: default;
|
||||
|
||||
&.c-help {
|
||||
cursor: help;
|
||||
}
|
||||
}
|
||||
|
||||
.small-title {
|
||||
@include in-content-small-title;
|
||||
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
::ng-deep my-suggestion {
|
||||
my-suggestion {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -70,10 +70,6 @@ export class SearchTypeaheadComponent implements OnInit, AfterViewChecked, OnDes
|
|||
if (this.keyboardEventsManager) this.keyboardEventsManager.change.unsubscribe()
|
||||
}
|
||||
|
||||
areInstructionsDisplayed () {
|
||||
return !this.search
|
||||
}
|
||||
|
||||
showSearchGlobalHelp () {
|
||||
return this.search && this.areSuggestionsOpened && this.keyboardEventsManager?.activeItem?.result?.type === 'search-index'
|
||||
}
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<a tabindex="-1" class="d-flex flex-auto flex-items-center p-2" [class.focus-visible]="active">
|
||||
<div class="flex-shrink-0 me-2 text-center">
|
||||
<my-global-icon iconName="search"></my-global-icon>
|
||||
</div>
|
||||
|
||||
<img class="avatar me-2 flex-shrink-0 d-none" alt="" aria-label="Team" src="" width="28" height="28">
|
||||
<a
|
||||
tabindex="-1" class="d-flex flex-auto align-center p-2" [class.focus-visible]="active"
|
||||
[title]="getTitle()"
|
||||
[attr.aria-describedby]="describedby"
|
||||
>
|
||||
<my-global-icon class="me-2" iconName="search"></my-global-icon>
|
||||
|
||||
<div
|
||||
class="flex-auto overflow-hidden text-start no-wrap css-truncate css-truncate-target"
|
||||
class="flex-auto overflow-hidden no-wrap d-flex align-center"
|
||||
[attr.aria-label]="result.text"
|
||||
>
|
||||
{{ result.text }}
|
||||
</div>
|
||||
|
||||
<div class="border rounded flex-shrink-0 px-1 bg-gray text-gray-light ms-1 f6">
|
||||
<div class="result-type border rounded flex-shrink-0 px-1 ms-1 f6">
|
||||
<span *ngIf="result.type === 'search-instance'" i18n>In this instance's network</span>
|
||||
<span *ngIf="result.type === 'search-index'" i18n>In the vidiverse</span>
|
||||
</div>
|
||||
|
|
|
@ -17,11 +17,8 @@ a {
|
|||
}
|
||||
}
|
||||
|
||||
.bg-gray {
|
||||
.result-type {
|
||||
background-color: pvar(--mainBackgroundColor);
|
||||
}
|
||||
|
||||
.text-gray-light {
|
||||
color: pvar(--mainForegroundColor);
|
||||
}
|
||||
|
||||
|
@ -30,6 +27,5 @@ my-global-icon {
|
|||
|
||||
width: 17px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
margin: 5px;
|
||||
top: -1px;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,16 @@ export type SuggestionPayloadType = 'search-instance' | 'search-index'
|
|||
export class SuggestionComponent implements OnInit, ListKeyManagerOption {
|
||||
@Input() result: SuggestionPayload
|
||||
@Input() highlight: string
|
||||
@Input() describedby: string
|
||||
|
||||
disabled = false
|
||||
active = false
|
||||
|
||||
getLabel () {
|
||||
return this.result.text
|
||||
getTitle () {
|
||||
if (this.result.type === 'search-instance') return $localize`Search "${this.result.text}" in this instance's network`
|
||||
if (this.result.type === 'search-index') return $localize`Search "${this.result.text}" in the vidiverse`
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
|
|
Loading…
Reference in New Issue