Skip to content

Commit ef04e27

Browse files
rlespinasseclaude
andauthored
feat(site): add accessibility foundations (#2)
## Summary - Add skip navigation link, visually-hidden `<h1>`, and ARIA attributes (`role="application"`, `aria-label`) on the map container - Add `.sr-only` utility, `.skip-link` styles, `:focus-visible` outlines, and `prefers-reduced-motion` media query - Improve BRGM link text for screen readers and add new-tab warnings on legal pages ## Changes | File | What | |------|------| | `site/index.html` | Skip link, sr-only `<h1>`, map ARIA attributes | | `site/css/style.css` | `.sr-only`, `.skip-link`, `:focus-visible`, `prefers-reduced-motion` | | `site/js/detail-builders.js` | BRGM link: descriptive text + sr-only new-tab hint + `aria-hidden` on icon | | `site/js/legal.js` | sr-only new-tab notice on each legal page | ## Review notes - `helpers.js` `terrilLinks`: planned `aria-label` on `<span>` was dropped during Karpathy review — `aria-label` on generic elements has no effect for screen readers - `meta description` conflict with upstream resolved: kept upstream's richer OG/Schema.org metadata ## Test plan - [ ] Tab through the page — skip link appears on first Tab, focus rings visible on all interactive elements - [ ] VoiceOver (Cmd+F5) — verify h1, map label, and BRGM link announced correctly - [ ] Enable "Reduce motion" in system settings — no smooth animations - [ ] Inspect with DevTools Accessibility panel — no missing labels/roles 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c2366a6 commit ef04e27

4 files changed

Lines changed: 51 additions & 2 deletions

File tree

site/css/style.css

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,50 @@ body {
1313
color: var(--color-text);
1414
}
1515

16+
/* --- Accessibility --- */
17+
18+
.sr-only {
19+
position: absolute;
20+
width: 1px;
21+
height: 1px;
22+
padding: 0;
23+
margin: -1px;
24+
overflow: hidden;
25+
clip: rect(0, 0, 0, 0);
26+
white-space: nowrap;
27+
border: 0;
28+
}
29+
30+
.skip-link {
31+
position: absolute;
32+
top: -100%;
33+
left: 0;
34+
z-index: 10000;
35+
padding: 0.75em 1.5em;
36+
background: #4a90d9;
37+
color: #fff;
38+
font-weight: bold;
39+
text-decoration: none;
40+
}
41+
42+
.skip-link:focus {
43+
top: 0;
44+
}
45+
46+
:focus-visible {
47+
outline: 3px solid #4a90d9;
48+
outline-offset: 2px;
49+
}
50+
51+
@media (prefers-reduced-motion: reduce) {
52+
*, *::before, *::after {
53+
animation-duration: 0.01ms !important;
54+
animation-iteration-count: 1 !important;
55+
transition-duration: 0.01ms !important;
56+
scroll-behavior: auto !important;
57+
}
58+
}
59+
1660
/* --- Project-specific styles --- */
1761

1862
main {

site/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@
6969
<link rel="stylesheet" href="css/style.css">
7070
</head>
7171
<body>
72+
<a href="#map" class="skip-link">Aller au contenu principal</a>
7273
<main>
73-
<div id="map"></div>
74+
<h1 class="sr-only">Bassin Minier du Nord-Pas de Calais — Patrimoine mondial UNESCO</h1>
75+
<div id="map" role="application" aria-label="Carte interactive du Bassin Minier du Nord-Pas de Calais"></div>
7476
</main>
7577

7678
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"

site/js/detail-builders.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ export function createDetailBuilders(helpers) {
389389
},
390390
{
391391
label: 'Liens', rows: [
392-
p.brgm && /^https?:\/\//.test(p.brgm) && ['Fiche BRGM', rawHtml(`<a href="${encodeURI(p.brgm)}" target="_blank" rel="noopener">Voir<span class="cross-link-icon"> \u2197</span></a>`)],
392+
p.brgm && /^https?:\/\//.test(p.brgm) && ['Fiche BRGM', rawHtml(`<a href="${encodeURI(p.brgm)}" target="_blank" rel="noopener">Voir la fiche BRGM<span class="sr-only"> (s'ouvre dans un nouvel onglet)</span><span class="cross-link-icon" aria-hidden="true"> \u2197</span></a>`)],
393393
sourceRow(dataGouvSources.puits)
394394
]
395395
}

site/js/legal.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export function buildLegalPages(dataGouvSources) {
66
id: 'mentions-legales',
77
label: 'Mentions légales',
88
content: `
9+
<p class="sr-only">Tous les liens de cette page s'ouvrent dans un nouvel onglet.</p>
910
<h3>Éditeur / Directeur de la publication</h3>
1011
<p>Romain Lespinasse</p>
1112
@@ -23,6 +24,7 @@ export function buildLegalPages(dataGouvSources) {
2324
id: 'confidentialite',
2425
label: 'Confidentialité',
2526
content: `
27+
<p class="sr-only">Tous les liens de cette page s'ouvrent dans un nouvel onglet.</p>
2628
<h3>Mesure d'audience</h3>
2729
<p><a href="https://www.goatcounter.com/" target="_blank" rel="noopener">GoatCounter</a> (open source, respectueux de la vie privée).</p>
2830
@@ -51,6 +53,7 @@ export function buildLegalPages(dataGouvSources) {
5153
id: 'credits',
5254
label: 'Crédits',
5355
content: `
56+
<p class="sr-only">Tous les liens de cette page s'ouvrent dans un nouvel onglet.</p>
5457
<h3>Sources de données</h3>
5558
<ul>
5659
${Object.values(dataGouvSources).map(s =>

0 commit comments

Comments
 (0)