Accessibility

Accessibility is ScriptWeaver's headline feature. Because the Player draws real native widgets, every app can plug into the host platform's own accessibility stack — ATK / AT-SPI on Linux, IAccessible2 on Windows, NSAccessibility on macOS — rather than reimplementing a screen-reader bridge in a web view. That makes the Player a credible choice where it matters most: public-sector and regulated apps, kiosks, and EU Accessibility Act compliance.

Status. The full a11y bridge ships with Tcl/Tk 9.1. The JS API below is stable and available today — on Tk 9.0 the properties are simply accepted and ignored (no errors), and they go live with no code changes when 9.1 lands. So you can — and should — annotate your app now. (One part already works on 9.0: accessibleHidden also drops the widget from keyboard tab-order.)

Labels

Give every meaningful control an accessible name. It's essential for icon-only or otherwise unlabelled controls, where assistive tech has no visible text to fall back on:

const search = app.Button({
  text: '🔍',
  accessibleLabel: 'Search',
});
Property Description
accessibleLabel The control's accessible name (what a screen reader announces).
accessibleDescription A longer description / hint, beyond the short label.
ariaLabel Alias for accessibleLabel, for those who think in ARIA terms.

Set them at creation (as options, above) or assign later:

icon.accessibleLabel = 'Toggle sidebar';

Roles

A widget's role tells assistive tech what kind of control it is. ScriptWeaver assigns a sensible default from the widget type, so most apps never set one explicitly:

Widget(s) Default role
Button button
CheckButton checkbox
RadioButton radio
Entry textbox
Spinbox spinbutton
Combobox combobox
Scale slider
Meter / Floodgauge progressbar (slider when interactive)
Label label
LabelFrame group
Listbox listbox · Treeviewtree · Texttext

Override only when you're repurposing a widget into a different kind of control:

const tab = frame.Button({ text: 'Files', accessibleRole: 'tab' });

Hiding decorative widgets

Purely decorative elements (spacers, ornamental icons) just add noise for screen readers. Mark them hidden:

divider.accessibleHidden = true;

accessibleHidden removes the widget from the accessibility tree and from keyboard tab traversal. The tab-order part already works on Tk 9.0; the tree-hiding activates with 9.1.

Announcements

Some changes need to be spoken even though focus didn't move — a form saved, an async load finished, an error appeared, or a value cycled in place. app.announce fires a live-region message for assistive tech:

app.announce('Settings saved'); // polite: queued, non-interrupting
app.announce('Upload failed', { priority: 'assertive' }); // interrupts current speech

priority is 'polite' (default) or 'assertive'. Like the properties above, this is a no-op on Tk 9.0 and becomes functional on 9.1 — so it's safe to wire up now (e.g. from a variable trace or an onClick).

See also