@mica/sdk (SDK contract v1)
    Preparing search index...

    Function focusTrap

    Keep Tab inside a modal surface, and put focus back where it came from on close.

    A deliberate widening of the published surface (MICA-172), and a one-way door. Three of the SDK's own primitives already use it — ConfirmDialog, ReportDialog and PhotoPickerModal — and an add-on that needs a modal the kit does not ship had no way to reach it. The alternative was for every add-on author to write their own trap, and a hand-rolled focus trap is the kind of thing that is quietly got wrong: the surface still looks right, Tab still moves, and the only person who finds out is a keyboard or screen-reader user who was told "dialog" and handed the screen behind it. That is an accessibility bug with no route back to its cause, which is exactly the class of failure this repo would rather make impossible than document.

    Exported here rather than from a barrel line of its own because it is the same kind of thing as everything above: DOM behaviour with no micaOS state behind it, implemented in sdk/lib/ and therefore bundle-safe for a sandboxed add-on. Going through utils.ts is also what gives it index/addon parity for free — both barrels export * from this file, so it cannot end up resolvable to the typechecker and missing at vite build, which is the divergence publicSurface.test.ts's parity arm exists to catch.

    FocusTrapOptions travels with it. An add-on wrapping this in a component of its own has to name the options object to pass enabled or returnFocusTo through, and an action whose parameter type is unnameable is an action you can only use in its default shape.

    <div role="dialog" aria-modal="true" use:focusTrap={{ returnFocusTo: () => opener }}>