Accessibility
The canvas is aria-hidden. Beside it, the explorer renders an outline: the current scene as
real links (each item’s href) and buttons (a hollow aggregate), with its badges (marks). It is
visually hidden, but read aloud and reachable by keyboard. The demo shows it, so you can see what is
announced as you move.
accessibility.tsximport { useState } from "react";import { createSceneSource, DataExplorer } from "@data-xplorer/core";
// The canvas is hidden from assistive technology; the outline beside it is not. It lists the// scene as real links (each item's `href`) and is read aloud. Show it to see what is announced.const shelves: Record<string, string[]> = { Fiction: ["Dune", "Emma", "Ulysses", "Beloved"], Science: ["Cosmos", "The Gene"], Poetry: ["Ariel", "Odes", "Leaves of Grass"],};const source = createSceneSource<string>({ load(shelf) { if (shelf === null) { return { id: "library", heading: "Library", nodes: [], edges: [], clusters: Object.keys(shelves).map((name) => ({ id: name, label: name, weight: shelves[name]!.length, href: `#shelf-${name}`, drillsInto: name, shape: "cloud" as const, marks: [`${shelves[name]!.length} books`], // badges, read with the item })), }; } return { id: shelf, heading: shelf, clusters: [], edges: [], nodes: shelves[shelf]!.map((title) => ({ id: title, label: title, weight: 1, href: `#book-${title}`, drillsInto: null, shape: "square" as const, })), }; }, parentOf: (shelf) => ({ kind: "anchored", focus: null, anchorId: shelf }),});
export default function Accessibility() { const [focus, setFocus] = useState<string | null>(null); const [showOutline, setShowOutline] = useState(true); return ( <div className={showOutline ? "show-outline" : undefined}> <div className="demo-toolbar"> <button onClick={() => setShowOutline(!showOutline)}>{showOutline ? "Hide" : "Show"} the outline</button> </div> <DataExplorer source={source} focus={focus} onSettle={setFocus} /> </div> );}- Keyboard. Tab to an entry and press Enter: the explorer enters that item, raising
onNodeActivatefirst exactly as a double-click does, then moves focus to the new scene with a polite announcement. - Every node needs an
href, so every relationship drawn on the canvas is also an ordinary link. If your data has no pages of its own, use stable in-app URLs. - Drawn edges are in the outline too, as links to their far ends.
- Without WebGL, the canvas is skipped and the outline still works.
- Reduced motion is respected: no pulse, no grow-in, no
animatedrenderers.