@wholisphere.ai/widget
v0.1.0
Published
MIT-licensed accessibility widget — a Shadow-DOM landmark + pure-DOM helpers for read-aloud, focus mode, live captions, and sandboxed voice control. Powers the Wholisphere extension and embed script.
Maintainers
Readme
@wholisphere.ai/widget
The Lit-based, Shadow-DOM accessibility widget powering the Wholisphere browser extension and embed script. MIT-licensed. Use it in your own products, fork it, ship it.
What you get: a floating "Accessibility tools" button + panel that lives in a Shadow DOM landmark, plus pure-DOM helpers for visual focus mode, live captions, voice-command execution, and a "read this page" TTS controller. Coexists with native screen readers — never traps focus, never overrides keyboard events.
Install
npm install @wholisphere.ai/widget lit(lit is a peer dep — most apps already have it.)
Quick start
import { mountWidget } from '@wholisphere.ai/widget';
const handle = mountWidget({
capabilities: [], // hand in your own Capability[] from @wholisphere/core, or none for a passive landmark
position: 'bottom-right',
locale: 'en',
onInvoke: (capabilityId) => {
console.log('user picked', capabilityId);
},
showActivityTab: true,
});
// Programmatic control:
handle.open();
handle.pushActivity({ capability: 'system', label: 'Page loaded' });
handle.setLocale('ar'); // RTL-flips automatically
handle.destroy();The mounted widget appears as a <aside role="complementary" aria-label="Accessibility tools"> so native screen readers find it as a real landmark, even if your visitor never engages the AI features.
Pure-DOM helpers (no Lit required)
If you don't need the panel UI, the per-capability helpers ship from a separate subpath that pulls no Lit code in:
import {
installFocusMode,
installCaptions,
executeVoiceCommand,
ReadPageController,
streamReadPage,
} from '@wholisphere.ai/widget/caps';installFocusMode(doc?) — visual focus mode
Hides nav/aside/footer/ad-shaped clutter, widens line spacing, optionally swaps to Atkinson Hyperlegible. Toggleable, fully reversible.
const fm = installFocusMode();
fm.toggle({ hideClutter: true, largerText: true, dyslexiaFont: false });installCaptions(doc?, opts?) — live captions overlay
Mirrors any native <track kind="captions"> cues onto a single fixed-position high-contrast overlay. MutationObserver picks up dynamic media. STT-stream extension hook ready for v2.
const cap = installCaptions();
cap.enable();
cap.pushCue({ text: 'Hello', startTime: 0, endTime: 1, source: 'manual' });executeVoiceCommand(command, opts?) — sandboxed voice→DOM
Takes the structured response from a voice-action LLM and runs it against the host DOM with hard guardrails: selector sanitation, off-origin nav blocked, 10 KB input cap, confidence threshold.
const outcome = executeVoiceCommand({
action: 'click',
targetSelector: 'button#submit',
targetLabel: 'Submit form',
value: null,
confidence: 0.92,
});
if (outcome.ok) console.log('ran', outcome.ran);ReadPageController — TTS playback over a structured outline
import { ReadPageController, streamReadPage } from '@wholisphere.ai/widget/caps';
const controller = new ReadPageController(outline, ttsEngine, {
rate: 1.1,
onChunk: ({ text }) => highlightLine(text),
});
await controller.start();
controller.nextSection();
controller.pause();streamReadPage() is the SSE consumer for the backend's POST /v1/read-page/stream route — yields summary, section, links, done events as they arrive so the controller can start narration while the rest of the outline is still in flight.
i18n
Out of the box: English, Spanish, French, German, Arabic (with dir="rtl" auto-applied to the landmark). Override or add locales via setStrings(locale, partial).
Accessibility self-claims
- The widget is itself a landmark region (
<aside role="complementary">). It never traps focus, never overrides Tab, and never installs global keyboard listeners that conflict with screen readers. - Panel renders as
role="dialog"witharia-modal="false"so users can Tab out into the host page at any time. - Esc closes; focus returns to the FAB.
- AAA-target color contrast in default tokens; hosts can override via the
--whs-*CSS custom property surface.
We publish a per-release VPAT 2.5 INT for the widget itself at wholisphere.ai/security.
Bundle size
- Root entry (with Lit components): ~28 KB gzipped.
/capssubpath (Lit-free helpers only): ~6 KB gzipped.
Contributing
Issues + PRs welcome. Run pnpm test in this package; happy-dom + Vitest cover the pure helpers, and the Lit components are integration-tested via the extension. Read CONTRIBUTING.md for setup + the PR checklist.
Related packages
@wholisphere/core— capability registry, schemas, types@wholisphere.ai/sdk— typed HTTP client for the Wholisphere API@wholisphere.ai/react— React provider + hooks
License
MIT — see LICENSE.
