Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Accesible Map #232

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions content/body/maps.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Accessible Map with List View</title>
<style>
#map {
height: 400px;
width: 100%;
}
#location-list {
list-style-type: none;
padding: 0;
}
#location-list li {
margin: 5px 0;
}
#location-list button {
width: 100%;
padding: 10px;
cursor: pointer;
}
*:focus {
outline: solid 2px #3b99fc;
}
*:focus:not(:focus-visible) {
outline: none;
}
*:focus-visible {
outline: solid 2px #3b99fc;
}
</style>
</head>
<body>
<main>
<h1>Interactive Map and Accessible List View</h1>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you take a look at the other pages in the body directory, you'll see that you only need the stuff inside

.

The CSS above should be linked from content/head/maps.php via the tag. Please make a LESS file to store this. It will be converted to CSS by our build scripts.

JS should be included in the content/bottom/maps.php file.

The aside directory would have notes on the top of the page like the table.php page

Can you please add this information to the README.md for this project? I think if you didn't know this, others wouldn't as well (I missed putting this in the docuementation).

<section>
<p>
An accessible map is a map that is designed to be usable by people with disabilities, ensuring that all users, regardless of their abilities, can interact with and understand the map's content. Accessibility for maps involves making sure that all interactive elements, such as markers, zoom controls, and map regions, are fully navigable via keyboard and screen reader software. It also includes providing alternative ways to view and interact with the map, such as list views of map markers or location descriptions, which help users who cannot rely on visual cues. Additionally, adding proper ARIA roles, landmarks, and text alternatives ensures that the map’s functionality is clear and easily accessible for all users.
</p>
</section>

<!-- Accessibility Instructions Section -->
<section aria-labelledby="accessibility-features" tabindex="0" >
<h2 id="accessibility-features">Accessibility Features</h2>
<p>
This map interface has been designed for accessibility with ARIA roles and a keyboard-friendly layout:
</p>
<ul>
<li><strong>ARIA roles and landmarks:</strong> The map container has <code>role="region"</code> and is <code>aria-labelledby</code> an instruction to help screen readers identify its function and purpose.</li>
<li><strong>Alternative list view:</strong> A list of locations is available below the map. Each location is represented by a button labeled with an <code>aria-label</code> describing the location. This allows users to select locations without navigating through the map itself.</li>
<li><strong>Keyboard navigation:</strong> The map container is focusable with <code>tabindex="0"</code>, and users can use the list to move the map and activate locations directly. Each location in the list opens the corresponding info window on the map when selected.</li>
</ul>
</section>

<section role="region" aria-labelledby="map-instructions" tabindex="0">
<p id="map-instructions">
Use the list below the map to select a location. Each location can be accessed without navigating the map itself.
</p>
<div aria-label="Interactive map showing various locations"></div>
</section>

<div id="map" class="enable-example">
<p>The following is the map container</p>
<section role="region" aria-labelledby="map" tabindex="0"></section>
</div>
<section class="locations" role="region" aria-labelledby="location-list-title" >
<h2 id="location-list-title">List of Locations</h2>
<ul aria-label="List of locations" id="location-list">
<!-- JavaScript will populate this list with items -->
</ul>
</section>

</main>

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zoltan-dulac add API KEY here

<script>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to comment on common practice throughout the project (you may know this already, but I thought I'd better write this down just in case you don't).

  • we should have script tags in the bottom/maps.php file.
  • Scripts should be modules (e.g. <script type="module">). Is it possible to include leaflet.js as an import? Look at js/demos/dialog-example.js to see how we import modules into that file.
  • Instead of using unpkg to include leaflet, we should include it in the project. Please follow our documentation in README.md on including npm modules in the front-end to see what we need to do here.

let map;
let currentFocusIndex = 0;
const locations = [
{ id: 1, name: 'North office', coords: { lat: 25.7617, lng: -80.1918 }, description: 'First location description' },
{ id: 2, name: 'East office', coords: { lat: 25.7637, lng: -80.1910 }, description: 'Second location description' },
{ id: 3, name: 'West office', coords: { lat: 25.7657, lng: -80.1920 }, description: 'Third location description' }
];

function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 25.7617, lng: -80.1918 },
zoom: 13
});

locations.forEach((location, index) => {
const marker = new google.maps.Marker({
position: location.coords,
map: map,
title: location.name
});

const infoWindow = new google.maps.InfoWindow({
content: `<strong>${location.name}</strong><br>${location.description}`
});

marker.addListener('click', () => {
infoWindow.open(map, marker);
});





const listItem = document.createElement('li');
const button = document.createElement('button');
button.innerText = location.name;

button.setAttribute('aria-label', `${location.name}`);
button.setAttribute('aria-describedby', `${location.description}`);
button.onclick = () => {
map.setCenter(location.coords);
map.setZoom(15);
infoWindow.open(map, marker);
};
listItem.appendChild(button);
document.getElementById('location-list').appendChild(listItem);

});



}


</script>

<?php includeShowcode("map", "", "", "", true, 2); ?>
<script type="application/json" id="map-props">
{
"replaceHtmlRules": {},
"steps": [{
"label": "Create accessible map markup",
"highlight": "%OPENCLOSECONTENTTAG%section",
"notes": "Ensure the map container is focusable by adding <code>tabindex='0'</code> and providing a descriptive <code>aria-labelledby</code> for screen readers."
},
{
"label": "Add interactive markers with accessible labels",
"highlight": "%OPENCLOSECONTENTTAG%img",
"notes": "Each marker on the map should be a focusable <code>button</code> element, with an <code>aria-label</code> that describes its purpose to screen readers."
}

]
}
</script>

</body>
</html>
6 changes: 6 additions & 0 deletions templates/data/meta-info.json
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,12 @@
"desc": "Math equations can be made accessible to math students and scholars with MathML.",
"wip": true
},
"maps.php": {
"sectionPages": [ {"controls": "Complex Controls"}],
"title": "Maps",
"desc": "A map which is accessible"

},
"meter.php": {
"sectionPages": [ { "content": "Static Content" }],
"title": "Meter",
Expand Down
Loading