Azure / react-azure-maps

React Wrapper for azure-maps-control
MIT License
52 stars 32 forks source link

Keyboard focus is moving on the coordinates tooltip present on the map more than one time using the Tab key. #87

Open yangster23 opened 3 years ago

yangster23 commented 3 years ago

Environment: Windows Version: Win10, Chrome Version: 87.0.4280.88 (Official Build) (64-bit)

On React Azure Maps, Keyboard focus is moving on the coordinates tooltip present on the map more than one time using the tab key. This fails WCAG 2.4.3 - https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-focus-order.html

Expected: Keyboard Focus should move on the coordinates tooltip present on the map only one time using the Tab key.

User Impact: Keyboard only users will face difficulty while navigating on the screen.

Note that Azure Maps Web SDK accessibility example meets this accessibility requirement.

image

rbrundritt commented 3 years ago

I believe this is an implementation issue, not a bug in this SDK. The accessible popup example you reference creates a popup for each location. You will need to do the same in your app rather than reusing a single popup instance.

yangster23 commented 3 years ago

Running the react-azure-playground locally, I can confirm the same behavior occurs where there is more than one instance of an popup, but they cannot be keyboard navigated via tab key.

image

Looking at the accessibility example provided in React Azure Maps, I could theoretically replicate the same code using Map Refs; however, is it possible to avoid using Map refs and pass a specific prop to AzureMapPopup to have users keyboard tab through each popup? I'm using the MultiplePointWithPopups.tsx in React-Azure-Maps-Playground and also attempted to pass "tabIndex: 0 to setPopupOptions with no luck

image

ambientlight commented 3 years ago

@yangster23:

To rephrase what @rbrundritt mentioned: The reason why you cannot navigate with tabs in MultiplePointWithPopups.tsx is the fact that at MultiplePointWithPopup.tsx#L128-L134 a single dynamic popup is used that gets re-rendered on every mouse move when there is data under map cursor: MultiplePointWithPopup.tsx#L107

The solution to this would just require rendering a list of popups instead:

<>
      {points.map((point, idx) => 
        <AzureMapPopup
          key={idx}
          isVisible={!idx}
          options={{
            ...popupOptions,
            position: point,
            pixelOffset: [0, -18],
          }}
          popupContent={
            <div style={styles.popupStyles}>{JSON.stringify({lng: point[0], lat: point[1]})}</div>
          }
        />  
      )}
</>

Unfortunately, as of react-azure-maps@0.3.0 / azure-maps-control@2.0.32 there exists an issue where just loading non-visible popups won't add them to the DOM and thus won't allow to use tab-based navigation.

To remedy this issue, I've used a rather hacky approach where all popups are originally loaded as visible, and then they get immediately closed after map ready event fires. You may reference a full working example with accessible popups at AccessiblePopups.tsx

I hope this can unblock you in the meanwhile while we investigate the root of the issue.

Why do hidden popups need to be added to the DOM? azure-maps-controls currently relies on css trick to keep those popups selectable, but not visible. If you inspect the DOM tree, you will find a css class .hidden-accessible-element added to all hidden popups:

.hidden-accessible-element {
    clip: rect(1px,1px,1px,1px);
    height: 1px;
    position: absolute;
    width: 1px;
}
ambientlight commented 3 years ago

@yangster23: I've created a PR that fixes the above mentioned issue: https://github.com/WiredSolutions/react-azure-maps/pull/96

You may reference the full example at AccessiblePopups.fix.tsx.

Until the fix gets merged, you may install react-azure-maps from the PR's branch directly via:

npm i --save git://github.com/ambientlight/react-azure-maps.git#fix/popups-add