mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
fix(a11y): move pages-edit EasyMDE scripts to head/footer, add h1 to home, fix stale TODO items
- pages-edit.php: EasyMDE CDN JS URL moved to $extraJs (rendered by footer.php before </body>); inline EasyMDE init block moved to $extraJsInline, emitted by footer.php via new `<?php if (!empty($extraJsInline))` guard - fixes invalid <script> floating in <body> (WCAG 4.1.1) - pages-edit.php: add <small> keyboard-trap hint below the editor textarea: 'Appuyez sur Échap pour quitter l'éditeur au clavier.' (WCAG 2.1.2) - templates/admin/footer.php: extend to support $extraJsInline (raw inline script string) - index.php: add <h1 class="sr-only">Mémoires de l'ERG</h1> inside <main> so the page has a document heading (WCAG 2.4.6; h2 columns in search.php already had a sr-only h1) - TODO.md: mark completed items as [x]: skip links (2.4.1), focus-visible / outline:none removal (2.4.7), search.php h1 + index.php h1 (2.4.6), pages-edit.php invalid HTML (4.1.1), EasyMDE keyboard trap hint (2.1.2)
This commit is contained in:
19
TODO.md
19
TODO.md
@@ -1077,14 +1077,14 @@ Current state: **zero ARIA attributes, zero skip links, zero focus-visible style
|
|||||||
|
|
||||||
#### 2.1.2 No keyboard trap
|
#### 2.1.2 No keyboard trap
|
||||||
|
|
||||||
- [ ] **EasyMDE editor in `pages-edit.php`** - CodeMirror-based editors are known keyboard
|
- [x] **EasyMDE editor in `pages-edit.php`** - CodeMirror-based editors are known keyboard
|
||||||
traps; Tab inside the editor inserts a tab character rather than moving focus out. EasyMDE
|
traps; Tab inside the editor inserts a tab character rather than moving focus out. EasyMDE
|
||||||
provides an escape route (Escape key exits the editor). Verify this works and document
|
provides an escape route (Escape key exits the editor). Verify this works and document
|
||||||
it with a visible hint below the editor (`<small>Appuyez sur Échap pour quitter l'éditeur</small>`).
|
it with a visible hint below the editor (`<small>Appuyez sur Échap pour quitter l'éditeur</small>`).
|
||||||
|
|
||||||
#### 2.4.1 Bypass blocks - skip link
|
#### 2.4.1 Bypass blocks - skip link
|
||||||
|
|
||||||
- [ ] **No skip-to-main-content link exists on any page** - every page loads with focus on
|
- [x] **No skip-to-main-content link exists on any page** - every page loads with focus on
|
||||||
the browser chrome, then Tab cycles through the nav and search bar before reaching `<main>`.
|
the browser chrome, then Tab cycles through the nav and search bar before reaching `<main>`.
|
||||||
On the home page that means tabbing through 4 nav links before reaching 24 thesis cards.
|
On the home page that means tabbing through 4 nav links before reaching 24 thesis cards.
|
||||||
Add `<a href="#main-content" class="skip-link">Aller au contenu principal</a>` as the
|
Add `<a href="#main-content" class="skip-link">Aller au contenu principal</a>` as the
|
||||||
@@ -1133,14 +1133,14 @@ Current state: **zero ARIA attributes, zero skip links, zero focus-visible style
|
|||||||
a label/metadata, not a heading. This is flagged in the semantic audit but it is also
|
a label/metadata, not a heading. This is flagged in the semantic audit but it is also
|
||||||
directly a WCAG 2.4.6 failure (heading does not describe the topic of the page).
|
directly a WCAG 2.4.6 failure (heading does not describe the topic of the page).
|
||||||
|
|
||||||
- [ ] **`search.php` répertoire index: `<h2>` headings inside columns are correct** - "Années",
|
- [x] **`search.php` répertoire index: `<h2>` headings inside columns are correct** - "Années",
|
||||||
"Catégories", "Étudiantes", "Mots-clés" as `<h2>` under a page with no `<h1>` is a skip.
|
"Catégories", "Étudiantes", "Mots-clés" as `<h2>` under a page with no `<h1>` is a skip.
|
||||||
Add an `<h1>` for the page (visually hidden if needed): `<h1 class="sr-only">Répertoire</h1>`.
|
Add an `<h1>` for the page (visually hidden if needed): `<h1 class="sr-only">Répertoire</h1>`.
|
||||||
Same for `index.php` which has no heading at all.
|
`index.php` now has `<h1 class="sr-only">Mémoires de l'ERG</h1>` inside `<main>`.
|
||||||
|
|
||||||
#### 2.4.7 Focus visible
|
#### 2.4.7 Focus visible
|
||||||
|
|
||||||
- [ ] **No `:focus-visible` style defined anywhere in the public CSS** - `common.css`,
|
- [x] **No `:focus-visible` style defined anywhere in the public CSS** - `common.css`,
|
||||||
`main.css`, `search.css`, `tfe.css`, and `apropos.css` contain zero `:focus` or
|
`main.css`, `search.css`, `tfe.css`, and `apropos.css` contain zero `:focus` or
|
||||||
`:focus-visible` rules. `modern-normalize` does not add any either. The browser's default
|
`:focus-visible` rules. `modern-normalize` does not add any either. The browser's default
|
||||||
focus ring is the only indicator, and it is suppressed by `outline: none` on
|
focus ring is the only indicator, and it is suppressed by `outline: none` on
|
||||||
@@ -1155,7 +1155,7 @@ Current state: **zero ARIA attributes, zero skip links, zero focus-visible style
|
|||||||
in `common.css`. This single rule covers every `<a>`, `<button>`, `<input>`, `<select>`,
|
in `common.css`. This single rule covers every `<a>`, `<button>`, `<input>`, `<select>`,
|
||||||
`<textarea>` on public pages. For admin: same using `var(--admin-purple)`.
|
`<textarea>` on public pages. For admin: same using `var(--admin-purple)`.
|
||||||
|
|
||||||
- [ ] **`outline: none` on `.site-search__input`** - this is an explicit suppression of the
|
- [x] **`outline: none` on `.site-search__input`** - this is an explicit suppression of the
|
||||||
browser focus ring with no replacement. Remove `outline: none` once the global
|
browser focus ring with no replacement. Remove `outline: none` once the global
|
||||||
`:focus-visible` rule above is in place. Same for `outline: none` on `.admin-input`,
|
`:focus-visible` rule above is in place. Same for `outline: none` on `.admin-input`,
|
||||||
`.admin-select`, `.admin-textarea`, and `.search-filter-select`.
|
`.admin-select`, `.admin-textarea`, and `.search-filter-select`.
|
||||||
@@ -1225,9 +1225,10 @@ Current state: **zero ARIA attributes, zero skip links, zero focus-visible style
|
|||||||
|
|
||||||
#### 4.1.1 Parsing
|
#### 4.1.1 Parsing
|
||||||
|
|
||||||
- [ ] **`pages-edit.php` has a `<link>` element inside `<body>`** - invalid HTML. Confirmed in
|
- [x] **`pages-edit.php` has a `<link>` element inside `<body>`** - invalid HTML. Confirmed in
|
||||||
the semantic audit (section XV). Browsers tolerate it but validators flag it and some AT
|
the semantic audit (section XV). The EasyMDE CSS was already moved to `$extraCss` (rendered
|
||||||
may misinterpret the document structure.
|
in `<head>`). The inline `<script>` init block is now moved to `$extraJsInline` (rendered
|
||||||
|
by `footer.php` before `</body>`). CDN JS URL uses `$extraJs`. All scripts/styles valid.
|
||||||
|
|
||||||
#### 4.1.2 Name, role, value
|
#### 4.1.2 Name, role, value
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,16 @@ try {
|
|||||||
|
|
||||||
$pageTitle = "Éditer : " . htmlspecialchars($page['title']);
|
$pageTitle = "Éditer : " . htmlspecialchars($page['title']);
|
||||||
$extraCss = ['https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css'];
|
$extraCss = ['https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css'];
|
||||||
|
$extraJs = ['https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js'];
|
||||||
|
$extraJsInline = <<<'JS'
|
||||||
|
var easyMDE = new EasyMDE({
|
||||||
|
element: document.getElementById('content'),
|
||||||
|
spellChecker: false,
|
||||||
|
status: ['lines', 'words'],
|
||||||
|
minHeight: '400px',
|
||||||
|
toolbarTips: true
|
||||||
|
});
|
||||||
|
JS;
|
||||||
?>
|
?>
|
||||||
<?php require_once APP_ROOT . '/templates/admin/head.php'; ?>
|
<?php require_once APP_ROOT . '/templates/admin/head.php'; ?>
|
||||||
|
|
||||||
@@ -41,8 +51,11 @@ $extraCss = ['https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css'];
|
|||||||
|
|
||||||
<div class="admin-form-row" style="align-items:start;">
|
<div class="admin-form-row" style="align-items:start;">
|
||||||
<label class="admin-label" for="content">Contenu (Markdown) :</label>
|
<label class="admin-label" for="content">Contenu (Markdown) :</label>
|
||||||
<textarea class="admin-textarea" id="content" name="content"
|
<div>
|
||||||
rows="20"><?= htmlspecialchars($page['content'] ?? '') ?></textarea>
|
<textarea class="admin-textarea" id="content" name="content"
|
||||||
|
rows="20"><?= htmlspecialchars($page['content'] ?? '') ?></textarea>
|
||||||
|
<small class="admin-hint">Appuyez sur <kbd>Échap</kbd> pour quitter l'éditeur au clavier.</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="admin-submit-wrap">
|
<div class="admin-submit-wrap">
|
||||||
@@ -51,15 +64,4 @@ $extraCss = ['https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.css'];
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js"></script>
|
|
||||||
<script>
|
|
||||||
var easyMDE = new EasyMDE({
|
|
||||||
element: document.getElementById('content'),
|
|
||||||
spellChecker: false,
|
|
||||||
status: ['lines', 'words'],
|
|
||||||
minHeight: '400px',
|
|
||||||
toolbarTips: true
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ $extraCss = ['assets/main.css'];
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<main class="home-main" id="main-content">
|
<main class="home-main" id="main-content">
|
||||||
|
<h1 class="sr-only">Mémoires de l'ERG</h1>
|
||||||
<ul class="cards-container">
|
<ul class="cards-container">
|
||||||
<?php foreach ($itemsToLoad as $item): ?>
|
<?php foreach ($itemsToLoad as $item): ?>
|
||||||
<li class="card">
|
<li class="card">
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
<?php foreach ($extraJs ?? [] as $js): ?>
|
<?php foreach ($extraJs ?? [] as $js): ?>
|
||||||
<script src="<?= htmlspecialchars($js) ?>"></script>
|
<script src="<?= htmlspecialchars($js) ?>"></script>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
<?php if (!empty($extraJsInline)): ?>
|
||||||
|
<script><?= $extraJsInline ?></script>
|
||||||
|
<?php endif; ?>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user