Accessibility
Tynd hands off rendering to the native WebView, so your app inherits the OS’s accessibility tree for free — if your HTML cooperates. This guide is about the app-level concerns Tynd can’t solve for you.
What the WebView gives you
- Screen readers — VoiceOver (macOS), Narrator (Windows), Orca (Linux). They walk the ARIA tree exposed by the WebView. Same semantics as a browser:
<button>is a button,aria-labelis read,role="..."is respected. - Keyboard navigation — Tab order from the DOM. Focus rings rendered by the WebView.
- Reduced motion —
@media (prefers-reduced-motion: reduce)works. - High contrast —
@media (prefers-contrast: more)/ Windows High Contrast Mode both flow through. - Dark mode —
@media (prefers-color-scheme: dark)is respected;os.isDarkMode()gives you a programmatic read.
What doesn’t come for free:
- Global hotkeys for screen-reader shortcuts (the OS owns those).
aria-liveregions still need you to write them.- Focus management across multi-window scenarios.
Checklist
Semantic HTML
- Use
<button>not<div onclick>. - Landmarks:
<main>,<nav>,<header>,<footer>,<aside>. - Headings in order (don’t skip
<h1>→<h3>). <img alt="...">— oralt=""for decorative.- Forms:
<label for="id">tied to<input id="id">.
Focus management
-
Every interactive element must be reachable by Tab.
-
Focus indicator must be visible (don’t
outline: nonewithout a replacement). -
Trap focus inside modal dialogs; restore on close.
-
On multi-window, focus the content area when a window gains focus:
tyndWindow.onFocused(() => { document.getElementById("main-content")?.focus(); });
Live updates
Long-running operations (upload, search, stream) need an aria-live region:
<div aria-live="polite" aria-atomic="true" class="sr-only">
{statusMessage}
</div>Where sr-only visually hides but keeps it in the AT tree:
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}Reduced motion
Respect the user preference:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}Or with JS:
const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (!reduced) runFancyAnimation();Color contrast
- Body text: AA = 4.5:1, AAA = 7:1.
- Large text (18pt+ or 14pt+ bold): AA = 3:1.
- Don’t convey information through color alone (error + icon, not just red).
Keyboard shortcuts
- Document them in an in-app help dialog.
- Don’t hijack OS-reserved combos (⌘Q on macOS, Ctrl+Alt+Del on Windows).
- Let users remap — see Keyboard Shortcuts for a user-configurable pattern.
Tray menu keyboard access
Tray menus open on left-click. Keyboard access to the tray is OS-specific (Windows: Win+B then Tab; macOS: accessibility menu; Linux: varies). You can’t change this — design your app so the tray is an accelerator, not the only way to reach critical features.
Dialog focus
Native dialogs (dialog.openFile, dialog.confirm) are OS-managed — they get focus correctly. In-app modals you build yourself must:
- Move focus into the modal on open.
- Trap Tab inside the modal.
- Close on Esc.
- Restore focus to the trigger on close.
Multi-monitor / DPI changes
Re-measure on DPI change:
tyndWindow.onDpiChanged(({ scale }) => {
applyScaleFactor(scale);
});User-increased font size should reflow your layout. Design for rem, not px, for text.
Testing
- macOS — VoiceOver (⌘F5 to toggle). Navigate with VO+arrows.
- Windows — Narrator (Win+Ctrl+Enter) or NVDA (free). Tab through the app.
- Linux — Orca (
orcacommand). - All OSes — unplug the mouse. Can you still use the app?
Automated checks help but don’t replace manual testing:
axe-coreas a devDependency, run in a dev-mode check.- Lighthouse audit against
tynd://localhost/index.html— paste the URL intoawait tyndWindow.openDevTools()→ Lighthouse tab.
Platform quirks
- macOS VoiceOver — may not announce dynamically inserted content unless in an
aria-liveregion. - Windows Narrator — reads
titleattributes; don’t duplicate witharia-labelunless you want both read. - Linux Orca — coverage varies by app. WebKitGTK’s AT tree is usually complete.
What Tynd will not help with
- No programmatic API for “announce this” — use
aria-liveregions. - No way to query screen-reader activity. Design assuming it’s on; the CSS media queries above are the programmatic signal.
Related
- Keyboard Shortcuts.
- Multi-Window — focus management.
- Security — CSP and trusted-content defaults.