fix: add accessible label to SearchBox input (#2193)
This commit is contained in:
parent
874e16a5d4
commit
df60b8ebe8
6 changed files with 37 additions and 24 deletions
|
|
@ -2,15 +2,15 @@
|
|||
"files": [
|
||||
{
|
||||
"path": "packages/docsearch-css/dist/style.css",
|
||||
"maxSize": "3 kB"
|
||||
"maxSize": "3.25 kB"
|
||||
},
|
||||
{
|
||||
"path": "packages/docsearch-react/dist/umd/index.js",
|
||||
"maxSize": "22.80 kB"
|
||||
"maxSize": "23 kB"
|
||||
},
|
||||
{
|
||||
"path": "packages/docsearch-js/dist/umd/index.js",
|
||||
"maxSize": "30.70 kB"
|
||||
"maxSize": "31 kB"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,6 +551,18 @@ svg.DocSearch-Hit-Select-Icon {
|
|||
width: 20px;
|
||||
}
|
||||
|
||||
/* Hide element accessibly, so that it is still accessible to
|
||||
assistive tech users */
|
||||
.DocSearch-VisuallyHiddenForAccessibility {
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
:root {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export type SearchBoxTranslations = Partial<{
|
|||
resetButtonAriaLabel: string;
|
||||
cancelButtonText: string;
|
||||
cancelButtonAriaLabel: string;
|
||||
searchInputLabel: string;
|
||||
}>;
|
||||
|
||||
interface SearchBoxProps
|
||||
|
|
@ -39,6 +40,7 @@ export function SearchBox({ translations = {}, ...props }: SearchBoxProps) {
|
|||
resetButtonAriaLabel = 'Clear the query',
|
||||
cancelButtonText = 'Cancel',
|
||||
cancelButtonAriaLabel = 'Cancel',
|
||||
searchInputLabel = 'Search',
|
||||
} = translations;
|
||||
const { onReset } = props.getFormProps({
|
||||
inputElement: props.inputRef.current,
|
||||
|
|
@ -67,6 +69,9 @@ export function SearchBox({ translations = {}, ...props }: SearchBoxProps) {
|
|||
>
|
||||
<label className="DocSearch-MagnifierLabel" {...props.getLabelProps()}>
|
||||
<SearchIcon />
|
||||
<span className="DocSearch-VisuallyHiddenForAccessibility">
|
||||
{searchInputLabel}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div className="DocSearch-LoadingIndicator">
|
||||
|
|
|
|||
|
|
@ -34,20 +34,8 @@ function noResultSearch(_queries: any, _requestOptions?: any): Promise<any> {
|
|||
}
|
||||
|
||||
describe('api', () => {
|
||||
let container: HTMLDivElement;
|
||||
|
||||
const docSearchSelector = '.DocSearch';
|
||||
|
||||
beforeEach(() => {
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(container);
|
||||
container = null;
|
||||
});
|
||||
|
||||
it('renders with minimal parameters', () => {
|
||||
render(<DocSearch />);
|
||||
|
||||
|
|
@ -68,10 +56,10 @@ describe('api', () => {
|
|||
);
|
||||
expect(document.querySelector(docSearchSelector)).toBeInTheDocument();
|
||||
expect(
|
||||
document.querySelector('.DocSearch-Button-Placeholder').innerHTML
|
||||
document.querySelector('.DocSearch-Button-Placeholder')?.innerHTML
|
||||
).toBe('Recherche');
|
||||
expect(
|
||||
document.querySelector('.DocSearch-Button').getAttribute('aria-label')
|
||||
document.querySelector('.DocSearch-Button')?.getAttribute('aria-label')
|
||||
).toBe('Recherche');
|
||||
});
|
||||
|
||||
|
|
@ -154,30 +142,36 @@ describe('api', () => {
|
|||
resetButtonAriaLabel: 'Effacer',
|
||||
cancelButtonText: 'Annuler',
|
||||
cancelButtonAriaLabel: 'Annuler',
|
||||
searchInputLabel: 'Recherche',
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(document.querySelector(docSearchSelector)).toBeInTheDocument();
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(await screen.findByText('Search'));
|
||||
});
|
||||
|
||||
expect(document.querySelector('.DocSearch-Cancel').innerHTML).toBe(
|
||||
const searchInputLabel = document.querySelector(
|
||||
'.DocSearch-MagnifierLabel'
|
||||
);
|
||||
|
||||
expect(document.querySelector(docSearchSelector)).toBeInTheDocument();
|
||||
|
||||
expect(document.querySelector('.DocSearch-Cancel')?.innerHTML).toBe(
|
||||
'Annuler'
|
||||
);
|
||||
expect(
|
||||
document.querySelector('.DocSearch-Cancel').getAttribute('aria-label')
|
||||
document.querySelector('.DocSearch-Cancel')?.getAttribute('aria-label')
|
||||
).toBe('Annuler');
|
||||
expect(
|
||||
document.querySelector('.DocSearch-Reset').getAttribute('title')
|
||||
document.querySelector('.DocSearch-Reset')?.getAttribute('title')
|
||||
).toBe('Effacer');
|
||||
expect(
|
||||
document.querySelector('.DocSearch-Reset').getAttribute('aria-label')
|
||||
document.querySelector('.DocSearch-Reset')?.getAttribute('aria-label')
|
||||
).toBe('Effacer');
|
||||
expect(searchInputLabel?.textContent).toBe('Recherche');
|
||||
});
|
||||
|
||||
it('overrides the default DocSearchModal footer text', async () => {
|
||||
|
|
@ -292,7 +286,7 @@ describe('api', () => {
|
|||
expect(screen.getByText(/No results for/)).toBeInTheDocument();
|
||||
const link = document.querySelector('.DocSearch-Help a');
|
||||
expect(link).toBeInTheDocument();
|
||||
expect(link.getAttribute('href')).toBe(
|
||||
expect(link?.getAttribute('href')).toBe(
|
||||
'https://github.com/algolia/docsearch/issues/new?title=q'
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ export function SearchIcon() {
|
|||
height="20"
|
||||
className="DocSearch-Search-Icon"
|
||||
viewBox="0 0 20 20"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ const translations: DocSearchTranslations = {
|
|||
resetButtonAriaLabel: 'Clear the query',
|
||||
cancelButtonText: 'Cancel',
|
||||
cancelButtonAriaLabel: 'Cancel',
|
||||
searchInputLabel: 'Search',
|
||||
},
|
||||
startScreen: {
|
||||
recentSearchesTitle: 'Recent',
|
||||
|
|
|
|||
Loading…
Reference in a new issue