mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
docs: semantic HTML audit admin section — add sections VIII–XVI to TODO.md
Analysed every admin template against semantic HTML: templates/admin/head.php (VIII): - Nav links are bare <a> in flat <nav>, no <ul>/<li> structure - No aria-label on <nav>, active state uses .active class not aria-current=page - Déconnexion link has inline style for positioning add.php / edit.php (IX): - ~20 <div class=admin-form-row> wrappers removable with CSS grid on form directly - Inner anonymous <div> wrapping input+hint → <small> removes the wrapper - <div class=admin-checkbox-list> + <label class=admin-checkbox-label> → <ul>/<li label> - <div class=admin-submit-wrap> → remove, style button directly - <div class=admin-alert> → <p role=alert> / <p role=status> index.php (X): - Stats <div> soup → <dl>/<dt>/<dd> (numbers as defined terms) - Maintenance bar <div> → <aside role=status> - Bulk toolbar → role=toolbar aria-label - <th> cells missing scope=col tags.php (XI): - <th> cells missing scope=col; inline margins on sibling forms → CSS selector thanks.php (XII): - <div class=admin-thesis-info> already uses <dl> inside — wrap in <section> instead account.php (XIII): - Status rows <div> soup → <dl>/<dt>/<dd> - Danger zone description <div> → <p> - Inline margin on section title → CSS login.php (XIV): - No <main> landmark on the page - Inline styles on form rows → modifier class pages-edit.php (XV): - <link> stylesheet injected inside <body> (invalid) — move to <head> via $extraCss Summary table: 15 additional admin classes deletable via semantic replacements
This commit is contained in:
162
TODO.md
162
TODO.md
@@ -757,3 +757,165 @@ Once the above is applied, the following classes become deletable (element name
|
|||||||
| `.apropos-contact-name` | `strong` inside `address` |
|
| `.apropos-contact-name` | `strong` inside `address` |
|
||||||
| `.apropos-contact-email` | `a[href^="mailto:"]` inside `address` |
|
| `.apropos-contact-email` | `a[href^="mailto:"]` inside `address` |
|
||||||
| `.apropos-description apropos-page-content` | `.prose` (single class) |
|
| `.apropos-description apropos-page-content` | `.prose` (single class) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Semantic HTML audit — Admin section (2026-03-26)
|
||||||
|
|
||||||
|
### VIII — `templates/admin/head.php` (admin nav)
|
||||||
|
|
||||||
|
- [ ] **Admin nav links are bare `<a>` tags in a flat `<nav>`** — identical problem as the public
|
||||||
|
nav. All seven nav links (`Liste des TFE`, `Ajouter`, `Importer`, `Pages statiques`,
|
||||||
|
`Mots-clés`, `Système`, `Compte`) plus the conditional `Modifier` and `Déconnexion` links
|
||||||
|
are direct children of `<nav>`. Replace with `<ul>/<li>` children.
|
||||||
|
Active state `.active` class → `aria-current="page"` on the `<a>`. Remove `.admin-nav__link`
|
||||||
|
as a selector; use `nav ul a` scoped to `.admin-nav`. The `Déconnexion` link with
|
||||||
|
`style="margin-left:auto;opacity:.6;"` → becomes `nav ul li:last-child a` or a utility
|
||||||
|
class, removing the inline style.
|
||||||
|
|
||||||
|
- [ ] **`<nav class="admin-nav">` has no `aria-label`** — add `aria-label="Navigation admin"` to
|
||||||
|
distinguish it from any other landmark on the page.
|
||||||
|
|
||||||
|
### IX — `public/admin/add.php` & `public/admin/edit.php` (TFE forms)
|
||||||
|
|
||||||
|
- [ ] **`.admin-form-row` is a `<div>` used to lay out a `<label>` beside an `<input>`** — for
|
||||||
|
every field where the `<label>` has a `for=` attribute (i.e. all single-control rows), the
|
||||||
|
`<div class="admin-form-row">` is a pure layout wrapper. It can be replaced with a CSS
|
||||||
|
grid applied directly to the `<form>` children, or more practically: the `<label>` and its
|
||||||
|
control remain direct children of the `<form>` and CSS grid spans them with
|
||||||
|
`grid-template-columns: 260px 1fr`. This removes one `<div>` per form field — about
|
||||||
|
**20 divs** from `add.php` and **22 divs** from `edit.php`.
|
||||||
|
|
||||||
|
- [ ] **Multi-control rows (checkboxes, file inputs with hint text) wrap their controls in an
|
||||||
|
anonymous `<div>`** — e.g. `<div class="admin-form-row"><label>…</label><div><input><p class="admin-hint">…</p></div></div>`.
|
||||||
|
The inner `<div>` only exists to stack the input above the hint. Replace the hint `<p>` with
|
||||||
|
`<small>` (ancillary text) and remove the wrapper div — `<small>` stacks naturally below its
|
||||||
|
sibling `<input>`.
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-checkbox-list">` wrapping `<label><input type=checkbox></label>` items**
|
||||||
|
— this is a list of options; replace with `<ul>` (no class needed, or a single utility
|
||||||
|
class). Each `<label class="admin-checkbox-label">` is an `<li>` containing the `<label>`.
|
||||||
|
Removes `.admin-checkbox-list` and `.admin-checkbox-label` classes (the `li label` selector
|
||||||
|
is sufficient).
|
||||||
|
|
||||||
|
- [ ] **Jury fieldset is good** — `<fieldset>` + `<legend>` is correct semantic HTML. No change
|
||||||
|
needed. The inner `<div class="admin-jury-row">` and `<div class="admin-jury-entry">` are
|
||||||
|
acceptable layout helpers for the dynamic row pattern; they are harder to replace without
|
||||||
|
JS complications.
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-submit-wrap">` at the bottom of every form** — wraps only a `<button>`
|
||||||
|
(and sometimes a cancel link). Remove the div; apply top margin and padding directly to the
|
||||||
|
`<button>` with a class or as the last-child `form > button` selector.
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-alert admin-alert--error">` and `..--success`** — these are notices.
|
||||||
|
Replace with `<p role="alert">` (errors) and `<p role="status">` (success messages).
|
||||||
|
Both carry live-region semantics natively. Removes two block-level divs per page load.
|
||||||
|
|
||||||
|
- [ ] **`<input type="hidden">` fields for CSRF** — correct, no change. But they sit as bare
|
||||||
|
siblings inside the `<form>` before the grid rows. Fine.
|
||||||
|
|
||||||
|
### X — `public/admin/index.php` (TFE list)
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-stats">` with `<div class="admin-stat">` children** — the stats
|
||||||
|
(total, published, pending) are a set of key-value pairs. Replace with `<dl>`:
|
||||||
|
`<div class="admin-stats">` → `<dl class="admin-stats">`;
|
||||||
|
each `<div class="admin-stat">` → `<div>` kept (valid `<dl>` child for grouping, per spec);
|
||||||
|
`<div class="admin-stat__number">` → `<dd>`;
|
||||||
|
`<div class="admin-stat__label">` → `<dt>`.
|
||||||
|
Removes two classes; makes the numbers machine-readable as defined terms.
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-maintenance-bar">` (status banner)** — this is a status notice + action
|
||||||
|
form. Replace the outer `<div>` with `<aside role="status">` or `<p role="status">` for the
|
||||||
|
text portion. The form inside stays as `<form>`. Removes one class.
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-bulk-actions">` bar** — a toolbar that appears conditionally. Replace
|
||||||
|
with `<div role="toolbar" aria-label="Actions groupées">`. Not a full semantic element
|
||||||
|
replacement, but adds correct ARIA role for the keyboard/AT pattern of a toolbar.
|
||||||
|
|
||||||
|
- [ ] **`<table class="admin-table">` is correct** — tabular data, right element. No change
|
||||||
|
needed. The `<thead>`, `<tbody>`, `<tr>`, `<th>`, `<td>` structure is correct.
|
||||||
|
Minor: `<th>` cells have no `scope="col"` attribute — add it for screen reader column
|
||||||
|
association (`<th scope="col">`).
|
||||||
|
|
||||||
|
- [ ] **Status badges `<span class="status-badge status-published">Publié</span>`** — these are
|
||||||
|
inline state labels. Semantically fine as `<span>` but could benefit from
|
||||||
|
`role="status"` or at minimum a visually-hidden text prefix (e.g. "Statut :") so screen
|
||||||
|
readers don't just announce "Publié" without context.
|
||||||
|
|
||||||
|
### XI — `public/admin/tags.php`
|
||||||
|
|
||||||
|
- [ ] **Three `<form>` elements per table row (rename, merge, delete)** — structurally correct
|
||||||
|
(each action is a separate form submission). No semantic issue. Minor: the inline
|
||||||
|
`style="margin-top:.35rem;"` on two of the three forms → move to CSS (e.g.
|
||||||
|
`.admin-inline-form + .admin-inline-form` selector in `admin.css`).
|
||||||
|
|
||||||
|
- [ ] **`<table>` with `<th>` cells lacking `scope="col"`** — same as `index.php`.
|
||||||
|
|
||||||
|
### XII — `public/admin/thanks.php`
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-thesis-info">` blocks** — each is a labelled section with a `<dl>`
|
||||||
|
inside it (already using `<dl>/<dt>/<dd>` correctly — good!). The outer wrapper `<div>`
|
||||||
|
could be a `<section>` with the `<h2>` as its heading, making the structure
|
||||||
|
`<section><h2>…</h2><dl>…</dl></section>`. Removes `.admin-thesis-info` class; CSS targets
|
||||||
|
`main > section`.
|
||||||
|
|
||||||
|
### XIII — `public/admin/account.php`
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-account-status">` with `<div class="admin-account-status__row">` children**
|
||||||
|
— each row is a key-value pair (label + status badge). Replace with `<dl>`:
|
||||||
|
`.admin-account-status` → `<dl>`;
|
||||||
|
`.admin-account-status__row` → `<div>` (valid `<dl>` child);
|
||||||
|
`.admin-account-status__label` → `<dt>`;
|
||||||
|
the badge/code stays as `<dd>` content.
|
||||||
|
Removes three classes.
|
||||||
|
|
||||||
|
- [ ] **`<h2 class="admin-section-title">` is correct** — scoped subsection headings inside
|
||||||
|
`<main>` at level 2 are right. The `style="margin-top:3rem;"` on the danger zone heading
|
||||||
|
→ move to CSS (`.admin-section-title + .admin-danger-zone` or a modifier class).
|
||||||
|
|
||||||
|
- [ ] **`<div class="admin-danger-zone">` containing a `<div class="admin-danger-zone__description">`
|
||||||
|
and a `<form>`** — the description div wrapping a `<strong>` and a `<span>` is over-wrapped.
|
||||||
|
The `<strong>` and following text are already inline; they don't need a block wrapper.
|
||||||
|
Replace `<div class="admin-danger-zone__description">` with `<p>` (it is a paragraph of
|
||||||
|
warning text). Removes one class and one div.
|
||||||
|
|
||||||
|
### XIV — `public/admin/login.php`
|
||||||
|
|
||||||
|
- [ ] **Login page has the correct structure overall** — `<form>`, `<label for>`, `<input>` are
|
||||||
|
properly associated. The `<div class="admin-login-wrap">` and `<div class="admin-login-box">`
|
||||||
|
are layout wrappers with no semantic equivalent — they can stay (centering a login box has
|
||||||
|
no semantic HTML counterpart). Minor improvement: wrap the whole login box in `<main>` so
|
||||||
|
it is the page's main landmark (currently there is none on the login page).
|
||||||
|
|
||||||
|
- [ ] **Inline styles on the login form rows** — `style="grid-template-columns:1fr;border:none;padding:.4rem 0;"`
|
||||||
|
on `.admin-form-row` and `style="margin-top:1rem;padding-top:.5rem;"` on `.admin-submit-wrap`
|
||||||
|
→ extract as a `.admin-form-row--compact` modifier and use in `admin.css`.
|
||||||
|
|
||||||
|
### XV — `public/admin/pages-edit.php`
|
||||||
|
|
||||||
|
- [ ] **`<link rel="stylesheet">` injected after `<main>` opens** — the EasyMDE stylesheet CDN
|
||||||
|
link is placed after the `</head>` has already closed (after `head.php` is included). It
|
||||||
|
sits directly inside `<body>` before `<main>`. This is invalid HTML — `<link>` is a head
|
||||||
|
element. Move it into the `<head>` by passing it to the head template via a `$extraCss`
|
||||||
|
variable (the mechanism already exists in the dead `templates/head.php`). Same for the
|
||||||
|
EasyMDE `<script>` tag which currently floats after `</main>`.
|
||||||
|
|
||||||
|
### XVI — Summary of admin class deletions enabled by semantic changes
|
||||||
|
|
||||||
|
| Class removed | Replaced by |
|
||||||
|
|---|---|
|
||||||
|
| `.admin-nav__link` | `nav ul a` |
|
||||||
|
| `.admin-nav__link.active` | `[aria-current="page"]` |
|
||||||
|
| `.admin-form-row` | direct `form > label + input` grid (or keep as minimal layout class) |
|
||||||
|
| `.admin-label` | `label` (scoped to `.admin-form`) |
|
||||||
|
| `.admin-checkbox-list` | `ul` inside form row |
|
||||||
|
| `.admin-checkbox-label` | `li label` |
|
||||||
|
| `.admin-submit-wrap` | `form > button:last-child` or slim `.submit` class |
|
||||||
|
| `.admin-alert--error` / `--success` | `p[role="alert"]` / `p[role="status"]` |
|
||||||
|
| `.admin-stat` | `div` inside `<dl>` |
|
||||||
|
| `.admin-stat__number` | `dd` |
|
||||||
|
| `.admin-stat__label` | `dt` |
|
||||||
|
| `.admin-thesis-info` | `section` |
|
||||||
|
| `.admin-account-status__row` | `div` inside `<dl>` |
|
||||||
|
| `.admin-account-status__label` | `dt` |
|
||||||
|
| `.admin-danger-zone__description` | `p` |
|
||||||
|
|||||||
Reference in New Issue
Block a user