diff --git a/src/tedi/components/form/search/search.spec.tsx b/src/tedi/components/form/search/search.spec.tsx index f1dee1bc9..8d3710e31 100644 --- a/src/tedi/components/form/search/search.spec.tsx +++ b/src/tedi/components/form/search/search.spec.tsx @@ -25,6 +25,23 @@ describe('Search component', () => { expect(input).toBeInTheDocument(); }); + it('does not name the search region with the placeholder (avoids double announcement)', () => { + render(); + const region = screen.getByRole('search'); + expect(region).toHaveAttribute('aria-label', 'search'); + expect(region.getAttribute('aria-label')).not.toBe('Search by name or keyword'); + }); + + it('uses the provided ariaLabel as the search region name', () => { + render(); + expect(screen.getByRole('search')).toHaveAttribute('aria-label', 'Search products'); + }); + + it('falls back to the generic label when ariaLabel is an empty string', () => { + render(); + expect(screen.getByRole('search')).toHaveAttribute('aria-label', 'search'); + }); + it('calls onSearch when the search button is clicked', () => { render(); const button = screen.getByRole('button', { name: /search/i }); diff --git a/src/tedi/components/form/search/search.tsx b/src/tedi/components/form/search/search.tsx index 7de2cfdad..16bee3a08 100644 --- a/src/tedi/components/form/search/search.tsx +++ b/src/tedi/components/form/search/search.tsx @@ -73,8 +73,13 @@ export const Search = forwardRef( ...(button ? {} : { icon: resolvedSearchIcon }), }; - const defaultAriaLabel = placeholder || getLabel('search'); - const searchAriaLabel = ariaLabel ?? defaultAriaLabel; + // Name the search landmark with the generic "search" label rather than the + // placeholder. The input already surfaces the placeholder, so reusing it as + // the region name makes screen readers announce it twice. Consumers should + // set `ariaLabel` to give the region a distinct name (e.g. "Search products"). + // `||` (not `??`) so an empty-string `ariaLabel` also falls back — otherwise + // the landmark would render with an empty accessible name. + const searchAriaLabel = ariaLabel || getLabel('search'); return (