fix: react-doctor dialog/a11y/labels → 68/100 with 973 warnings

This commit is contained in:
Nora
2026-06-26 03:43:04 -06:00
parent d0bfec9d36
commit e97eb33bf1
34 changed files with 611 additions and 580 deletions
+32 -31
View File
@@ -1,6 +1,6 @@
"use client";
import { useCallback, useEffect, useEffectEvent, useRef, useState, useSyncExternalStore } from "react";
import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
import Image from "next/image";
import { createPortal } from "react-dom";
@@ -135,24 +135,24 @@ export default function ProductFormModal({
);
// Body scroll lock + escape key
// useEffectEvent so the latest onClose is always called even though
// it's no longer in the effect's dependency array.
const onCloseEffect = useEffectEvent(() => {
onClose();
});
// Native <dialog> handles both focus trapping and ESC; we just open
// it with showModal() and forward the cancel event to onClose so the
// parent's React state stays in sync with the native close behavior.
const dialogRef = useRef<HTMLDialogElement>(null);
useEffect(() => {
if (!open) return;
const original = document.body.style.overflow;
document.body.style.overflow = "hidden";
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") onCloseEffect();
const dialog = dialogRef.current;
if (!dialog) return;
if (!dialog.open) dialog.showModal();
const onCancel = (e: Event) => {
e.preventDefault();
onClose();
};
window.addEventListener("keydown", onKey);
dialog.addEventListener("cancel", onCancel);
return () => {
document.body.style.overflow = original;
window.removeEventListener("keydown", onKey);
dialog.removeEventListener("cancel", onCancel);
};
}, [open]);
}, [open, onClose]);
const handleFile = useCallback(
async (file: File) => {
@@ -232,24 +232,24 @@ export default function ProductFormModal({
const lockedBrandName = brands.find((b) => b.id === lockedBrandId)?.name ?? lockedBrandId;
return createPortal(
<div
className="fixed inset-0 z-[80] flex items-center justify-center p-3 sm:p-6 atelier-backdrop"
onClick={(e) => {
if (e.target === e.currentTarget) onClose();
}}
style={{
backgroundColor: "color-mix(in srgb, var(--admin-text-primary) 55%, transparent)",
backdropFilter: "blur(8px)",
WebkitBackdropFilter: "blur(8px)",
}}
<dialog
ref={dialogRef}
aria-label={mode === "add" ? "Add product" : "Edit product"}
className="m-0 p-0 w-full h-full max-w-none max-h-full bg-transparent"
style={{ backgroundColor: "transparent" }}
>
<div
role="dialog"
aria-modal="true"
aria-label={mode === "add" ? "Add product" : "Edit product"}
className="atelier-enter atelier-canvas relative w-full max-w-5xl max-h-[calc(100vh-1.5rem)] sm:max-h-[calc(100vh-3rem)] rounded-2xl flex flex-col overflow-hidden border border-[var(--admin-border)]"
style={{ boxShadow: "0 30px 80px -20px color-mix(in srgb, var(--admin-text-primary) 45%, transparent)" }}
className="fixed inset-0 z-[80] flex items-center justify-center p-3 sm:p-6 atelier-backdrop"
style={{
backgroundColor: "color-mix(in srgb, var(--admin-text-primary) 55%, transparent)",
backdropFilter: "blur(8px)",
WebkitBackdropFilter: "blur(8px)",
}}
>
<div
className="atelier-enter atelier-canvas relative w-full max-w-5xl max-h-[calc(100vh-1.5rem)] sm:max-h-[calc(100vh-3rem)] rounded-2xl flex flex-col overflow-hidden border border-[var(--admin-border)]"
style={{ boxShadow: "0 30px 80px -20px color-mix(in srgb, var(--admin-text-primary) 45%, transparent)" }}
>
{/* grain overlay */}
<div className="atelier-grain" aria-hidden />
@@ -719,7 +719,8 @@ export default function ProductFormModal({
</div>
</div>
</div>
</div>,
</div>
</dialog>,
document.body
);
}