mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(map): announce the places filter control as opening a dialog
MapTogglePill always set aria-pressed, so the phone map's Filters control read as a toggle although it opens a sheet. An opensDialog option drops aria-pressed for aria-haspopup="dialog"; the other map toggles are unchanged.
This commit is contained in:
@@ -6,7 +6,7 @@ import { MAP_CONTROL_SHADOW } from './mapControlShadow'
|
|||||||
* One round on/off control in the frosted shell every map control wears, so a new
|
* One round on/off control in the frosted shell every map control wears, so a new
|
||||||
* one lines up with the compass, the layer switcher and the overview toggle.
|
* one lines up with the compass, the layer switcher and the overview toggle.
|
||||||
*/
|
*/
|
||||||
export function MapTogglePill({ active, onToggle, label, icon, testId, tooltipPlacement = 'left', badge = 0 }: {
|
export function MapTogglePill({ active, onToggle, label, icon, testId, tooltipPlacement = 'left', badge = 0, opensDialog = false }: {
|
||||||
active: boolean
|
active: boolean
|
||||||
onToggle: () => void
|
onToggle: () => void
|
||||||
label: string
|
label: string
|
||||||
@@ -16,6 +16,12 @@ export function MapTogglePill({ active, onToggle, label, icon, testId, tooltipPl
|
|||||||
tooltipPlacement?: 'left' | 'right'
|
tooltipPlacement?: 'left' | 'right'
|
||||||
/** A count pinned to the top right corner while above zero (how many filters are on, say). */
|
/** A count pinned to the top right corner while above zero (how many filters are on, say). */
|
||||||
badge?: number
|
badge?: number
|
||||||
|
/**
|
||||||
|
* The control opens a dialog instead of switching something on and off (the phone
|
||||||
|
* map's places filter): it then announces the dialog, not a pressed state it
|
||||||
|
* does not have. `active` still lights it.
|
||||||
|
*/
|
||||||
|
opensDialog?: boolean
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div style={{
|
<div style={{
|
||||||
@@ -33,7 +39,8 @@ export function MapTogglePill({ active, onToggle, label, icon, testId, tooltipPl
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={onToggle}
|
onClick={onToggle}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
aria-pressed={active}
|
aria-pressed={opensDialog ? undefined : active}
|
||||||
|
aria-haspopup={opensDialog ? 'dialog' : undefined}
|
||||||
data-testid={testId}
|
data-testid={testId}
|
||||||
className={active ? 'text-accent' : 'text-content-muted'}
|
className={active ? 'text-accent' : 'text-content-muted'}
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { useTranslation } from '../../../../i18n'
|
|||||||
/**
|
/**
|
||||||
* The phone map's way into the places filter: a round control in the right-hand
|
* The phone map's way into the places filter: a round control in the right-hand
|
||||||
* stack, lit and badged with how many filters are narrowing the markers. The sheet
|
* stack, lit and badged with how many filters are narrowing the markers. The sheet
|
||||||
* it opens is the shell's 'placesFilter' sheet.
|
* it opens is the shell's 'placesFilter' sheet, so the button announces a dialog
|
||||||
|
* rather than a pressed state.
|
||||||
*/
|
*/
|
||||||
export function MPlacesFilterPill({ onOpen }: { onOpen: () => void }) {
|
export function MPlacesFilterPill({ onOpen }: { onOpen: () => void }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@@ -23,6 +24,7 @@ export function MPlacesFilterPill({ onOpen }: { onOpen: () => void }) {
|
|||||||
label={label}
|
label={label}
|
||||||
badge={count}
|
badge={count}
|
||||||
testId="places-filter-pill"
|
testId="places-filter-pill"
|
||||||
|
opensDialog
|
||||||
icon={<SlidersHorizontal size={17} strokeWidth={2} />}
|
icon={<SlidersHorizontal size={17} strokeWidth={2} />}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -958,7 +958,9 @@ describe('MMapArea — places filter', () => {
|
|||||||
const { shell } = renderArea({ trTab: 'plan' })
|
const { shell } = renderArea({ trTab: 'plan' })
|
||||||
const pill = screen.getByTestId('places-filter-pill')
|
const pill = screen.getByTestId('places-filter-pill')
|
||||||
expect(pill).toHaveAccessibleName('Filters')
|
expect(pill).toHaveAccessibleName('Filters')
|
||||||
expect(pill).toHaveAttribute('aria-pressed', 'false')
|
// It opens a sheet: a dialog to announce, not an on/off state.
|
||||||
|
expect(pill).toHaveAttribute('aria-haspopup', 'dialog')
|
||||||
|
expect(pill).not.toHaveAttribute('aria-pressed')
|
||||||
act(() => { pill.click() })
|
act(() => { pill.click() })
|
||||||
expect(shell.openSheet).toHaveBeenCalledWith('placesFilter')
|
expect(shell.openSheet).toHaveBeenCalledWith('placesFilter')
|
||||||
})
|
})
|
||||||
@@ -967,7 +969,9 @@ describe('MMapArea — places filter', () => {
|
|||||||
seedStore(useTripStore, { placesFilter: 'unplanned', placesRatingFilter: 4 })
|
seedStore(useTripStore, { placesFilter: 'unplanned', placesRatingFilter: 4 })
|
||||||
renderArea({ trTab: 'plan' })
|
renderArea({ trTab: 'plan' })
|
||||||
const pill = screen.getByTestId('places-filter-pill')
|
const pill = screen.getByTestId('places-filter-pill')
|
||||||
expect(pill).toHaveAttribute('aria-pressed', 'true')
|
expect(pill).toHaveClass('text-accent')
|
||||||
|
expect(pill).not.toHaveAttribute('aria-pressed')
|
||||||
|
expect(pill).toHaveAttribute('aria-haspopup', 'dialog')
|
||||||
expect(pill).toHaveAccessibleName('Filters (2)')
|
expect(pill).toHaveAccessibleName('Filters (2)')
|
||||||
expect(screen.getByText('2')).toHaveAttribute('aria-hidden', 'true')
|
expect(screen.getByText('2')).toHaveAttribute('aria-hidden', 'true')
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user