♿️(frontend) add global screen reader announcer
centralize live region rendering with a shared announce hook.
This commit is contained in:
15
src/frontend/src/hooks/useScreenReaderAnnounce.ts
Normal file
15
src/frontend/src/hooks/useScreenReaderAnnounce.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useCallback } from 'react'
|
||||
import {
|
||||
announceToScreenReader,
|
||||
type Politeness,
|
||||
} from '@/stores/screenReaderAnnouncer'
|
||||
|
||||
export const useScreenReaderAnnounce = () => {
|
||||
return useCallback(
|
||||
(message: string, politeness: Politeness = 'polite') => {
|
||||
announceToScreenReader(message, politeness)
|
||||
},
|
||||
[]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Header } from './Header'
|
||||
import { layoutStore } from '@/stores/layout'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { Footer } from '@/layout/Footer'
|
||||
import { ScreenReaderAnnouncer } from '@/primitives'
|
||||
|
||||
export type Layout = 'fullpage' | 'centered'
|
||||
|
||||
@@ -41,6 +42,7 @@ export const Layout = ({ children }: { children: ReactNode }) => {
|
||||
flexDirection: 'column',
|
||||
})}
|
||||
>
|
||||
<ScreenReaderAnnouncer />
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
20
src/frontend/src/primitives/ScreenReaderAnnouncer.tsx
Normal file
20
src/frontend/src/primitives/ScreenReaderAnnouncer.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { screenReaderAnnouncerStore } from '@/stores/screenReaderAnnouncer'
|
||||
|
||||
export const ScreenReaderAnnouncer = () => {
|
||||
const { announcement } = useSnapshot(screenReaderAnnouncerStore)
|
||||
|
||||
return (
|
||||
<div
|
||||
key={announcement.id}
|
||||
role="status"
|
||||
aria-live={announcement.politeness}
|
||||
aria-atomic="true"
|
||||
className="sr-only"
|
||||
data-announce-id={announcement.id}
|
||||
>
|
||||
{announcement.message}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ export { Menu } from './Menu'
|
||||
export { MenuList } from './MenuList'
|
||||
export { P } from './P'
|
||||
export { Popover } from './Popover'
|
||||
export { ScreenReaderAnnouncer } from './ScreenReaderAnnouncer'
|
||||
export { Text } from './Text'
|
||||
export { ToggleButton } from './ToggleButton'
|
||||
export { Ul } from './Ul'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { proxy } from 'valtio'
|
||||
|
||||
type Politeness = 'polite' | 'assertive'
|
||||
export type Politeness = 'polite' | 'assertive'
|
||||
|
||||
type ScreenReaderAnnouncement = {
|
||||
message: string
|
||||
|
||||
Reference in New Issue
Block a user