Workers P3-Endprüfung W3: Fokus kehrt nach dem Anhalten auf den Knopf der Leiste zurück

Der Dialog schloss im selben Takt, in dem pausing den Knopf der Leiste sperrte; useDialogFocus
konnte den Fokus deshalb nicht zurückgeben, und er blieb für Tastatur- und Screenreader-Nutzer
dauerhaft auf <body>. Das Board setzt ihn jetzt selbst, sobald pausing endet (auch nach einem
Fehler), und nur dann, wenn der Fokus verloren ist. Der Prüfstand-Check (Szenario I) ist grün.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-18 10:42:13 +00:00
1 parent f6099938d8
commit 20f51c6584
2 files changed
+40 -2

No files matched your search

+18 -2
View File
@@ -30,6 +30,8 @@ export default function WorkersBoard({ api, isAdmin, stageRef }) {
const ref = stageRef ?? ownRef
const aliveRef = useRef(true)
const sideRef = useRef(null)
const toolbarRef = useRef(null)
const refocusPauseRef = useRef(false) // nach dem Umschalten bekommt der Knopf „Alles anhalten“ / „Fortsetzen“ den Fokus zurück, falls er ihn verlor
const [workers, setWorkers] = useState({})
const [selectedId, setSelectedId] = useState(null)
const [settingsOpen, setSettingsOpen] = useState(false)
@@ -55,6 +57,19 @@ export default function WorkersBoard({ api, isAdmin, stageRef }) {
const { trace, loading: traceLoading, error: traceError } = useWorkerTrace(api, selectedId)
// Fokus nach dem Umschalten: Während pausing gilt, ist der Knopf der Leiste gesperrt. Schließt der Dialog im selben Takt, in dem pausing
// beginnt, kann useDialogFocus den Fokus nicht auf den gesperrten Knopf zurückgeben, und er bliebe für immer auf <body>. Deshalb
// wird er erst hier gesetzt, wenn pausing wieder endet (auch nach einem Fehler) und der Knopf wieder bedienbar ist. Hat der Mensch
// inzwischen woanders hin gewechselt (Fokus nicht auf <body>), bleibt es dabei.
useEffect(() => {
if (pausing || !refocusPauseRef.current) return
refocusPauseRef.current = false
const active = document.activeElement
if (active && active !== document.body) return
const button = toolbarRef.current?.querySelector('[data-wk-pause]')
if (button) button.focus()
}, [pausing])
// Hat inzwischen jemand anderes angehalten, entfällt die Frage; sie darf nach einem späteren Fortsetzen nicht wieder auftauchen
const haltedByState = Boolean(state?.paused)
useEffect(() => {
@@ -95,6 +110,7 @@ export default function WorkersBoard({ api, isAdmin, stageRef }) {
// jemand anderes angehalten hat.
const setPause = async (target) => {
if (pausing) return
refocusPauseRef.current = true
setPausing(true)
setPauseError('')
try {
@@ -118,10 +134,10 @@ export default function WorkersBoard({ api, isAdmin, stageRef }) {
return (
<>
<div className="wk-toolbar">
<div className="wk-toolbar" ref={toolbarRef}>
<span className="wk-status">{paused ? PAUSED_TEXT : RUNNING_TEXT}</span>
<span className="grow" />
<Button type="button" onClick={requestPause} disabled={pausing}>{pauseLabel(paused)}</Button>
<Button type="button" onClick={requestPause} disabled={pausing} data-wk-pause>{pauseLabel(paused)}</Button>
{isAdmin && <Button type="button" onClick={() => setSettingsOpen(true)}>Einstellungen</Button>}
</div>