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:
accessibleHiddenalso 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 · Treeview → tree · Text → text |
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
- Widget basics — creating and configuring widgets
- Events & binding —
onClick, focus events - Variables & reactivity — drive
announcefrom value changes