fix(security): medium/low — event-lock, atomic config, a11y, diashow, hygiene
- social: likes/comments rejected on a closed event (e2e proven). - admin: patch_config validates-then-writes atomically; char-based length. - hashtag/comment models: atomic tag writes in edit + comment paths. - Modal: inert the background (modal-inert action) for screen readers. - sse.ts: idempotent visibilitychange listener (no duplicate reconnects). - diashow: videos advance on `ended` (transitions + page wiring). - docs/hygiene: README clone-case fix; removed stale committed .env.test and gitignored it; docker-compose.dev.yml tidy. Left documented as accepted-risk per plan: PIN-persist-after-logout, UUID-reachable hidden uploads, DECISION-media-auth.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
29
frontend/src/lib/actions/modal-inert.ts
Normal file
29
frontend/src/lib/actions/modal-inert.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
// Make everything *outside* a modal's subtree inert while it's open, so screen
|
||||
// readers and tab order can't reach the background (focus-trap only covers
|
||||
// keyboard focus; `inert` also hides the content from assistive tech).
|
||||
//
|
||||
// Walks from the node up to <body> and marks every sibling along the path as
|
||||
// inert, then restores exactly those it changed on teardown. Applying it to a
|
||||
// `display: contents` wrapper keeps the modal's own backdrop + dialog interactive.
|
||||
export function modalInert(node: HTMLElement) {
|
||||
const changed: HTMLElement[] = [];
|
||||
|
||||
let el: HTMLElement | null = node;
|
||||
while (el && el !== document.body) {
|
||||
const parent: HTMLElement | null = el.parentElement;
|
||||
if (!parent) break;
|
||||
for (const sib of Array.from(parent.children)) {
|
||||
if (sib !== el && sib instanceof HTMLElement && !sib.hasAttribute('inert')) {
|
||||
sib.setAttribute('inert', '');
|
||||
changed.push(sib);
|
||||
}
|
||||
}
|
||||
el = parent;
|
||||
}
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
for (const sib of changed) sib.removeAttribute('inert');
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user