diff --git a/services/frontend/src/components/shell/constellation-frame.tsx b/services/frontend/src/components/shell/constellation-frame.tsx index 28ef1e73..4e4f5909 100644 --- a/services/frontend/src/components/shell/constellation-frame.tsx +++ b/services/frontend/src/components/shell/constellation-frame.tsx @@ -18,6 +18,7 @@ import { resolveScene, type SceneSeed, } from "@/components/shell/route-scenes"; +import { SceneA11yMirror } from "@/components/shell/scene-a11y-mirror"; import { SceneGraphProvider, useSceneGraph, @@ -62,6 +63,7 @@ export function ConstellationFrame({
+ {/* Overlay content region — scenes place floating panels inside. */}
diff --git a/services/frontend/src/components/shell/scene-a11y-mirror.tsx b/services/frontend/src/components/shell/scene-a11y-mirror.tsx new file mode 100644 index 00000000..05391e7e --- /dev/null +++ b/services/frontend/src/components/shell/scene-a11y-mirror.tsx @@ -0,0 +1,55 @@ +"use client"; + +/** + * SceneA11yMirror — screen-reader/keyboard mirror of the live constellation. + * The canvas itself is decorative (aria-hidden); this list exposes every + * node as a real link/button so keyboard and AT users get the same graph. + */ +import { usePathname } from "next/navigation"; +import { useSceneGraph } from "@/components/shell/scene-graph-context"; + +export function SceneA11yMirror() { + const pathname = usePathname() ?? "/"; + const { state, setFocus } = useSceneGraph(); + const nodes = state?.graph.nodes ?? []; + + return ( + + ); +}