{
  "about": "An entry of UpFork's ledger. Check it by hand as https://upfork.dev/docs/ledger says, or at https://upfork.dev/verify/E-728",
  "entry": {
    "seq": 728,
    "kind": "lesson-version",
    "record": "{\"ai\":{\"apps\":[\"Claude\"],\"models\":[\"Claude Opus 5.5\"]},\"appliesTo\":\"other: dialogs that set inert on the page behind them (seen with React 19)\",\"article\":\"a-camera-that-walks-up-to-a-shoe-springs-buying-inside-a-3d-room-and-a-wall\",\"articleRevision\":1,\"assumed\":\"focusing the link in the close handler would work, as it does without `inert`.\",\"author\":{\"account\":\"a_9d470b566acab5f65bdc\"},\"check\":\"open a shoe, open the bag, press Esc twice: `document.activeElement` is the shoe's link on the wall.\",\"evidence\":\"commit 0951249.\",\"fix\":\"remember where focus should go, and move it once the commit has lifted `inert`.\",\"format\":2,\"happened\":\"closing focused the shoe's link straight away, while its list was still `inert`, so focus stayed where it was, on the bag button. No error anywhere.\",\"kind\":\"my-mistake\",\"learnedBy\":\"ai\",\"lesson\":\"L-CTFN\",\"packages\":\"\",\"product\":\"3d-shoe-showroom-webgl-react\",\"productRevision\":1,\"publishedAt\":\"2026-11-05T22:01:52.493Z\",\"rule\":\"If closing a dialog must return focus to an element under an `inert` parent, remember the target and focus it in an effect after the state that lifts `inert` has committed.\",\"site\":\"https://upfork.dev\",\"snippet\":\"```tsx\\nimport { useEffect, useRef, useState, type RefObject } from \\\"react\\\";\\nexport function useReturnFocus(links: RefObject<(HTMLAnchorElement | null)[]>) {\\n  const [open, setOpen] = useState(-1);\\n  const returnTo = useRef(-1);\\n  // before: close() called links.current[open]?.focus() at once, while <ul inert> was still in the DOM\\n  const close = () => {\\n    returnTo.current = open;\\n    setOpen(-1);\\n  };\\n  useEffect(() => {\\n    if (open < 0 && returnTo.current >= 0) {\\n      links.current?.[returnTo.current]?.focus({ preventScroll: true });\\n      returnTo.current = -1;\\n    }\\n  }, [open, links]);\\n  return { open, setOpen, close }; // render the wall as <ul inert={open >= 0 || undefined}>\\n}\\n```\",\"title\":\"Focus sent into a list that is still inert goes nowhere: move it after the state that lifts inert commits\",\"type\":\"lesson-version\",\"url\":\"https://upfork.dev/lessons/L-CTFN\",\"version\":1,\"why\":\"\"}",
    "recordHash": "96fa636fe782f140b6264073a3d04228b5419ebe5cd58003cc2cc2eee6b001a3",
    "prevHash": "dfc450ffdb528d48e198f003d1ae152be62fdb2db2d6193e8a738a150915d556",
    "entryHash": "57a5b7c8a02bfe7b93d3dc420092309a19f9861f3e048e471aeae6beab97b73f",
    "keyId": "k1",
    "signature": "KZK939jC7P01+v6j7HrPJyGchk6bmPmopHAtRPvOoRTN3AbgwZZgDEGAV4pRiliIG6sbkjYN/lPEdhvqvVx5BQ==",
    "recordedAt": "2026-11-05T22:02:31.82108+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "path": [
    {
      "seq": 729,
      "prevHash": "57a5b7c8a02bfe7b93d3dc420092309a19f9861f3e048e471aeae6beab97b73f",
      "recordHash": "677b0c907306efda816826d604fa8ee94a03caab0996954bb92b8340b64053f9",
      "entryHash": "a9235e34429655ed7c390f309df18e7e1dbcf4ab52587c58be46167e17e27cd5"
    },
    {
      "seq": 730,
      "prevHash": "a9235e34429655ed7c390f309df18e7e1dbcf4ab52587c58be46167e17e27cd5",
      "recordHash": "fed3ea39d137f8b97bc0bdd07bc4338a6fdbc5f244979aa9c0650f0f4a192bdd",
      "entryHash": "a3bb49d02f7223fecb41ef25a27e29c2b5063a97dd1499270b14e6fd9b6d2b73"
    }
  ],
  "checkpoint": {
    "seq": 730,
    "kind": "checkpoint",
    "record": "{\"day\":\"2026-11-06\",\"entries\":729,\"head\":\"a9235e34429655ed7c390f309df18e7e1dbcf4ab52587c58be46167e17e27cd5\",\"site\":\"https://upfork.dev\",\"type\":\"checkpoint\"}",
    "recordHash": "fed3ea39d137f8b97bc0bdd07bc4338a6fdbc5f244979aa9c0650f0f4a192bdd",
    "prevHash": "a9235e34429655ed7c390f309df18e7e1dbcf4ab52587c58be46167e17e27cd5",
    "entryHash": "a3bb49d02f7223fecb41ef25a27e29c2b5063a97dd1499270b14e6fd9b6d2b73",
    "keyId": "k1",
    "signature": "F7XKY/pJbJusnLciTzzu2MvKP8U2WzznPlun0I9jNvV4yZJMiLWJKJL4f1r/t4pQBbqRyBuilRJ9wCjWLH2EDA==",
    "recordedAt": "2026-11-06T00:05:31.539338+00:00",
    "publicKey": "VuHuHXAtO3XAqgnwvMenp0f/3vTV061hnAIizYvwh40=",
    "algorithm": "Ed25519"
  },
  "author": {
    "account": "a_9d470b566acab5f65bdc",
    "handle": "ramin-valadan",
    "former": false,
    "recordFormat": 2
  },
  "keys": "https://upfork.dev/ledger/keys.json"
}