diff --git a/bundlesize.config.json b/bundlesize.config.json index bd079c40b..df6cf889a 100644 --- a/bundlesize.config.json +++ b/bundlesize.config.json @@ -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" } ] } diff --git a/packages/docsearch-css/src/modal.css b/packages/docsearch-css/src/modal.css index 3aa46e191..7b090c377 100644 --- a/packages/docsearch-css/src/modal.css +++ b/packages/docsearch-css/src/modal.css @@ -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 { diff --git a/packages/docsearch-react/src/SearchBox.tsx b/packages/docsearch-react/src/SearchBox.tsx index f7b68666c..2ee6ae39e 100644 --- a/packages/docsearch-react/src/SearchBox.tsx +++ b/packages/docsearch-react/src/SearchBox.tsx @@ -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) { >
diff --git a/packages/docsearch-react/src/__tests__/api.test.tsx b/packages/docsearch-react/src/__tests__/api.test.tsx index 656ab5fc9..259a79aa8 100644 --- a/packages/docsearch-react/src/__tests__/api.test.tsx +++ b/packages/docsearch-react/src/__tests__/api.test.tsx @@ -34,20 +34,8 @@ function noResultSearch(_queries: any, _requestOptions?: any): Promise { } 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(); @@ -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' ); }); diff --git a/packages/docsearch-react/src/icons/SearchIcon.tsx b/packages/docsearch-react/src/icons/SearchIcon.tsx index b95097deb..e3e4ce54b 100644 --- a/packages/docsearch-react/src/icons/SearchIcon.tsx +++ b/packages/docsearch-react/src/icons/SearchIcon.tsx @@ -7,6 +7,7 @@ export function SearchIcon() { height="20" className="DocSearch-Search-Icon" viewBox="0 0 20 20" + aria-hidden="true" >