frontend-patterns/research/experiments/boundary-recovery/fixture.jsx
tegwick 3eecd74b0d Probe rendering and modal focus boundaries in pinned browser fixture
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0cffe-206f-7323-89d3-b20ca4cf4bf9
2026-09-26 22:01:35 +02:00

81 lines
3.6 KiB
JavaScript

import React, {useState, useRef} from 'react';
import {createRoot} from 'react-dom/client';
import * as Dialog from '@radix-ui/react-dialog';
window.observed = {caught: [], globalErrors: [], requests: [], dialogTransitions: []};
window.addEventListener('error', e => window.observed.globalErrors.push(e.message));
class Boundary extends React.Component {
state = {failed: false};
static getDerivedStateFromError() { return {failed: true}; }
componentDidCatch(error) { window.observed.caught.push({boundary: this.props.name, message: error.message}); }
render() {
if (this.state.failed) return this.props.brokenFallback
? <BrokenFallback /> : <p role="alert" data-testid={this.props.name}>Region unavailable</p>;
return this.props.children;
}
}
function BrokenFallback() { throw new Error('fallback fault'); }
function Panel() {
const [broken, setBroken] = useState(false);
const [request, setRequest] = useState('idle');
if (broken) throw new Error('render fault');
return <section data-testid="panel">
<button onClick={() => setBroken(true)}>Break render</button>
<button onClick={() => {throw new Error('event fault');}}>Break event</button>
<button onClick={async () => {
setRequest('pending');
try {
const r = await fetch('/failure');
window.observed.requests.push(r.status);
if (!r.ok) throw new Error('request rejected');
setRequest('accepted');
} catch {setRequest('request failed');}
}}>Fail request</button>
<p role="status">{request}</p>
</section>;
}
function FailureFixture() {
const [clicks, setClicks] = useState(0);
const brokenFallback = new URLSearchParams(location.search).has('brokenFallback');
return <main>
<button onClick={() => setClicks(clicks + 1)}>Sibling {clicks}</button>
<Boundary name="outer"><Boundary name="inner" brokenFallback={brokenFallback}>
<Panel />
</Boundary></Boundary>
</main>;
}
function Modal({children, title}) {
return <Dialog.Portal><Dialog.Overlay />
<Dialog.Content aria-describedby={undefined}>
<Dialog.Title>{title}</Dialog.Title>{children}
</Dialog.Content>
</Dialog.Portal>;
}
function FocusFixture() {
const [open, setOpen] = useState(false);
const [present, setPresent] = useState(true);
const next = useRef(null);
const explicit = new URLSearchParams(location.search).has('explicit');
return <main>
<button id="next" ref={next}>Next record</button>
<Dialog.Root open={open} onOpenChange={value => {window.observed.dialogTransitions.push({dialog: "outer", open: value}); setOpen(value);}}>
{present && <Dialog.Trigger id="invoker">Open task</Dialog.Trigger>}
<Dialog.Portal><Dialog.Overlay />
<Dialog.Content aria-describedby={undefined} onCloseAutoFocus={event => {
if (explicit && !present) {event.preventDefault(); next.current?.focus();}
}}>
<Dialog.Title>Record task</Dialog.Title>
<button id="remove" onClick={() => {setPresent(false); setOpen(false);}}>Remove invoking record</button>
<Dialog.Root onOpenChange={value => window.observed.dialogTransitions.push({dialog: "inner", open: value})}>
<Dialog.Trigger id="nested-invoker">Nested task</Dialog.Trigger>
<Modal title="Nested task"><Dialog.Close id="nested-close">Close nested</Dialog.Close></Modal>
</Dialog.Root>
<Dialog.Close id="close">Close task</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
</main>;
}
createRoot(document.getElementById('root')).render(
new URLSearchParams(location.search).get('mode') === 'focus' ? <FocusFixture /> : <FailureFixture />
);