Steve Sawczyn58 downloadsAdds screen reader and keyboard accessibility to Obsidian's wikilink and other suggestion popups.
An Obsidian plugin that retrofits screen reader and keyboard accessibility onto Obsidian's suggestion popups — starting with the [[ wikilink autocomplete.
Part of the Ariadne project. See issue #1 in the catalog for the background on why this is needed and what's already known about the problem.
I am a blind screen reader user who has been trying, unsuccessfully, to use Obsidian in an efficient way. While much work has been put into adding keyboard navigation, there exist many situations where dynamically changing content is not picked up by screen readers and other assistive technologies. For example:
Obsidian's [[ wikilink suggestion popup doesn't announce itself to screen readers, and doesn't expose keyboard navigation state to assistive tech — even though a sighted user can visually see a highlighted suggestion move as arrow keys are pressed, nothing tells a screen reader which option is selected or that a list of suggestions exists at all.
This appears to be because the popup is Obsidian's own bespoke EditorSuggest-based UI, not built on CodeMirror 6's @codemirror/autocomplete package (which already implements the accessible ARIA combobox pattern). See the catalog entry for more detail.
Obsidian's suggestion popups all appear to share one internal DOM pattern: a .suggestion-container holding a list of .suggestion-item elements, with .is-selected toggled on whichever one is currently highlighted. This plugin watches for that pattern with a MutationObserver and layers standard ARIA combobox/listbox semantics on top of it, without touching Obsidian's own rendering or keyboard handling:
role="listbox" / role="option" on the popup and its itemsaria-expanded, aria-controls, aria-autocomplete="list" on whichever element had focus when the popup opened (the editor's contenteditable for inline suggesters like [[, or a modal <input> for others)aria-activedescendant kept in sync with the .is-selected item as you arrow throughBecause it's generic to the popup pattern rather than wikilink-specific, it should also apply to any other Obsidian UI built on the same suggestion component (see catalog issue #6 re: the command palette).
Important caveat: the class names above (.suggestion-container, .suggestion-item, .is-selected) are Obsidian's internal, undocumented markup, inferred from known/observed behavior, not a published API. They may shift in future Obsidian versions. If they do, the retrofit will silently do nothing rather than error and I'll get the joy of reengineering a solution.
Confirmed working across multiple Obsidian UI patterns, tested live on macOS with VoiceOver:
EditorSuggest popup (.suggestion-container) — [[ wikilink autocomplete and # tag autocomplete, with zero code changes needed between the two..prompt-results) — the command palette and Quick Switcher, added in 47e381a after root-causing the difference by reading Obsidian's own installed app bundle.All confirmed to:
Not yet tested: other suggestion contexts (embeds, frontmatter property values), Windows/NVDA and other screen reader + OS combinations.
npm install
npm run dev
This builds main.js in watch mode. Symlink or copy this directory into a test vault's .obsidian/plugins/ariadne-autocomplete/ folder to load it.
The plugin can log plain-text status lines to the console ([Ariadne] ...) at each step — popup detected, items tagged, popup closed — as a debugging aid that doesn't require navigating DevTools' Elements accessibility tree, which is a poor experience for screen reader users in its own right. This is off by default so real users don't get a console full of noise; there's no settings UI for it yet, but it can be flipped on in the DevTools console with:
app.plugins.plugins["ariadne-autocomplete"].settings.debugLogging = true
(A proper settings toggle is planned — this is a stopgap so testers can opt in without needing a rebuild.) It logs via console.debug, which Chromium DevTools hides by default under its "Verbose" filter level — if you enable debugLogging and see nothing, check the console's log-level filter before assuming it's broken. Reading the console log is optional either way; the actual test is simpler:
[[.What you hear (or don't) at each step is itself the diagnostic — it doesn't need to be paired with a DevTools inspection to be useful for narrowing down what's broken.
While I wish accessibility were prioritized more highly in Obsidian directly, I'm really glad that it's possible to create work-arounds via plugins like this. While I fully intend to continue maintaining this plugin, I live in hope that there will come a day when this plugin is no longer needed. In the meantime, please contact me or file an issue for any enhancement requests or other suggestions. My goal is to release additional plugins to target additional areas where accessibility is problematic in Obsidian.
Thank you for using this plugin, I hope it enhances your productivity as it has enhanced mine.