Documentation: No new user-facing settings or APIs introduced.
Dependencies: No new dependencies.
Testing: Changes are additive ARIA attributes and sr-only elements; no visual regressions. Tested with NVDA + Firefox and keyboard-only navigation.
Agentic AI Code: This PR was authored with AI assistance and has been manually reviewed.
Code review: Self-reviewed.
Design & Architecture: All changes are accessibility-only; no UX or architectural changes.
Git Hygiene: Single atomic commit targeting dev.
Title Prefix:fix:
Changelog Entry
Description
Fixes 11 WCAG 4.1.2 (Name, Role, Value) violations where icon-only buttons, toggle controls, and interactive elements lacked accessible names. Also adds a proper combobox ARIA pattern to the model selector and global aria-live regions so screen readers announce AI response generation status and completed responses.
Fixed
MessageInput.svelte — Scroll-to-bottom button, dismiss @-model button, Web Search toggle, Image Generation toggle, Stop generating button, and Send message button all lacked aria-label. Web Search and Image Generation toggles also lacked aria-pressed to communicate their on/off state.
Navbar.svelte — Mobile sidebar toggle had no aria-label. Controls button had a hard-coded English aria-label that did not translate with the UI language.
ResponseMessage.svelte — Token usage info button had aria-hidden="true" on a focusable element (keyboard users could tab to it but hear nothing). Regenerate menu trigger was a non-interactive <div> with no keyboard activation.
MessageInput.svelte hidden trigger button: add aria-hidden="true" to exclude it from the accessibility tree.
Added
Selector.svelte — Model search input now has role="combobox", aria-expanded, aria-controls, and aria-activedescendant so screen readers correctly describe the dropdown relationship. e.preventDefault() added to ArrowUp/ArrowDown to prevent page scroll during keyboard navigation.
ModelItem.svelte — Model list items changed from <button> to <div role="option" tabindex="-1" id="model-option-{index}"> to correctly participate in the combobox/listbox pattern. aria-label simplified to item.label. Keyboard handler added for Enter/Space.
Message.svelte — Screen-reader-only <h3> headings added before each message block so users can skim the conversation by heading level ("You said:", "[Model name] said:", "Assistants said:").
Messages.svelte + stores/index.ts + +layout.svelte — Global aria-live regions placed outside all content areas (in the document root via +layout.svelte) so NVDA browse-mode navigation never lands on them. Messages.svelte writes generation status ("Generating response…" / "Still generating…" every 6 s) and the completed plain-text response to global Svelte stores. The live region fires on response completion and during streaming.
en-US/translation.json — 8 new i18n keys registered for the new aria-label values.
Breaking Changes
None.
Additional Information
The <ul role="log"> that previously surrounded the message list has been changed to a plain <div> because the live region responsibility moved to the global aria-live regions in +layout.svelte. Keeping role="log" on the list would cause double-announcements.
The hidden #generate-message-pair-button is a programmatic trigger (not user-facing); aria-hidden="true" ensures AT does not enumerate it.
Screenshots or Videos
No visual changes (all modifications are ARIA attributes and sr-only elements).
Contributor License Agreement
By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/open-webui/open-webui/pull/22091
**Author:** [@devinprater](https://github.com/devinprater)
**Created:** 3/1/2026
**Status:** ❌ Closed
**Base:** `dev` ← **Head:** `fix/unlabeled-controls`
---
### 📝 Commits (3)
- [`d3b9b19`](https://github.com/open-webui/open-webui/commit/d3b9b191b7c12b8a2d6cc01891aa23b88cdb8b52) fix: add accessible labels and live regions to chat UI
- [`99d644b`](https://github.com/open-webui/open-webui/commit/99d644b56a5e7084221b55107b773c6f6fd52114) fix: correct JS escape sequences in markdownToPlainText
- [`a54f37b`](https://github.com/open-webui/open-webui/commit/a54f37b16e5720e936321c31e76de5293ad2c41c) fix: label More and Integrations toolbar buttons
### 📊 Changes
**10 files changed** (+2303 additions, -2140 deletions)
<details>
<summary>View changed files</summary>
📝 `src/lib/components/chat/MessageInput.svelte` (+13 -2)
📝 `src/lib/components/chat/Messages.svelte` (+101 -4)
📝 `src/lib/components/chat/Messages/Message.svelte` (+9 -1)
📝 `src/lib/components/chat/Messages/ResponseMessage.svelte` (+7 -4)
📝 `src/lib/components/chat/ModelSelector/ModelItem.svelte` (+11 -3)
📝 `src/lib/components/chat/ModelSelector/Selector.svelte` (+9 -1)
📝 `src/lib/components/chat/Navbar.svelte` (+5 -1)
📝 `src/lib/i18n/locales/en-US/translation.json` (+2131 -2123)
📝 `src/lib/stores/index.ts` (+7 -0)
📝 `src/routes/+layout.svelte` (+10 -1)
</details>
### 📄 Description
# Pull Request Checklist
- [x] **Target branch:** This PR targets the `dev` branch.
- [x] **Description:** See changelog below.
- [x] **Changelog:** Included below.
- [ ] **Documentation:** No new user-facing settings or APIs introduced.
- [x] **Dependencies:** No new dependencies.
- [x] **Testing:** Changes are additive ARIA attributes and sr-only elements; no visual regressions. Tested with NVDA + Firefox and keyboard-only navigation.
- [x] **Agentic AI Code:** This PR was authored with AI assistance and has been manually reviewed.
- [x] **Code review:** Self-reviewed.
- [x] **Design & Architecture:** All changes are accessibility-only; no UX or architectural changes.
- [x] **Git Hygiene:** Single atomic commit targeting `dev`.
- [x] **Title Prefix:** `fix:`
---
# Changelog Entry
### Description
Fixes 11 WCAG 4.1.2 (Name, Role, Value) violations where icon-only buttons, toggle controls, and interactive elements lacked accessible names. Also adds a proper combobox ARIA pattern to the model selector and global `aria-live` regions so screen readers announce AI response generation status and completed responses.
### Fixed
- `MessageInput.svelte` — Scroll-to-bottom button, dismiss @-model button, Web Search toggle, Image Generation toggle, Stop generating button, and Send message button all lacked `aria-label`. Web Search and Image Generation toggles also lacked `aria-pressed` to communicate their on/off state.
- `Navbar.svelte` — Mobile sidebar toggle had no `aria-label`. Controls button had a hard-coded English `aria-label` that did not translate with the UI language.
- `ResponseMessage.svelte` — Token usage info button had `aria-hidden="true"` on a focusable element (keyboard users could tab to it but hear nothing). Regenerate menu trigger was a non-interactive `<div>` with no keyboard activation.
- `MessageInput.svelte` hidden trigger button: add `aria-hidden="true"` to exclude it from the accessibility tree.
### Added
- `Selector.svelte` — Model search input now has `role="combobox"`, `aria-expanded`, `aria-controls`, and `aria-activedescendant` so screen readers correctly describe the dropdown relationship. `e.preventDefault()` added to ArrowUp/ArrowDown to prevent page scroll during keyboard navigation.
- `ModelItem.svelte` — Model list items changed from `<button>` to `<div role="option" tabindex="-1" id="model-option-{index}">` to correctly participate in the combobox/listbox pattern. `aria-label` simplified to `item.label`. Keyboard handler added for Enter/Space.
- `Message.svelte` — Screen-reader-only `<h3>` headings added before each message block so users can skim the conversation by heading level ("You said:", "[Model name] said:", "Assistants said:").
- `Messages.svelte` + `stores/index.ts` + `+layout.svelte` — Global `aria-live` regions placed outside all content areas (in the document root via `+layout.svelte`) so NVDA browse-mode navigation never lands on them. `Messages.svelte` writes generation status ("Generating response…" / "Still generating…" every 6 s) and the completed plain-text response to global Svelte stores. The live region fires on response completion and during streaming.
- `en-US/translation.json` — 8 new i18n keys registered for the new `aria-label` values.
### Breaking Changes
- None.
---
### Additional Information
- The `<ul role="log">` that previously surrounded the message list has been changed to a plain `<div>` because the live region responsibility moved to the global `aria-live` regions in `+layout.svelte`. Keeping `role="log"` on the list would cause double-announcements.
- The hidden `#generate-message-pair-button` is a programmatic trigger (not user-facing); `aria-hidden="true"` ensures AT does not enumerate it.
### Screenshots or Videos
No visual changes (all modifications are ARIA attributes and `sr-only` elements).
### Contributor License Agreement
By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms.
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/open-webui/open-webui/pull/22091
Author: @devinprater
Created: 3/1/2026
Status: ❌ Closed
Base:
dev← Head:fix/unlabeled-controls📝 Commits (3)
d3b9b19fix: add accessible labels and live regions to chat UI99d644bfix: correct JS escape sequences in markdownToPlainTexta54f37bfix: label More and Integrations toolbar buttons📊 Changes
10 files changed (+2303 additions, -2140 deletions)
View changed files
📝
src/lib/components/chat/MessageInput.svelte(+13 -2)📝
src/lib/components/chat/Messages.svelte(+101 -4)📝
src/lib/components/chat/Messages/Message.svelte(+9 -1)📝
src/lib/components/chat/Messages/ResponseMessage.svelte(+7 -4)📝
src/lib/components/chat/ModelSelector/ModelItem.svelte(+11 -3)📝
src/lib/components/chat/ModelSelector/Selector.svelte(+9 -1)📝
src/lib/components/chat/Navbar.svelte(+5 -1)📝
src/lib/i18n/locales/en-US/translation.json(+2131 -2123)📝
src/lib/stores/index.ts(+7 -0)📝
src/routes/+layout.svelte(+10 -1)📄 Description
Pull Request Checklist
devbranch.dev.fix:Changelog Entry
Description
Fixes 11 WCAG 4.1.2 (Name, Role, Value) violations where icon-only buttons, toggle controls, and interactive elements lacked accessible names. Also adds a proper combobox ARIA pattern to the model selector and global
aria-liveregions so screen readers announce AI response generation status and completed responses.Fixed
MessageInput.svelte— Scroll-to-bottom button, dismiss @-model button, Web Search toggle, Image Generation toggle, Stop generating button, and Send message button all lackedaria-label. Web Search and Image Generation toggles also lackedaria-pressedto communicate their on/off state.Navbar.svelte— Mobile sidebar toggle had noaria-label. Controls button had a hard-coded Englisharia-labelthat did not translate with the UI language.ResponseMessage.svelte— Token usage info button hadaria-hidden="true"on a focusable element (keyboard users could tab to it but hear nothing). Regenerate menu trigger was a non-interactive<div>with no keyboard activation.MessageInput.sveltehidden trigger button: addaria-hidden="true"to exclude it from the accessibility tree.Added
Selector.svelte— Model search input now hasrole="combobox",aria-expanded,aria-controls, andaria-activedescendantso screen readers correctly describe the dropdown relationship.e.preventDefault()added to ArrowUp/ArrowDown to prevent page scroll during keyboard navigation.ModelItem.svelte— Model list items changed from<button>to<div role="option" tabindex="-1" id="model-option-{index}">to correctly participate in the combobox/listbox pattern.aria-labelsimplified toitem.label. Keyboard handler added for Enter/Space.Message.svelte— Screen-reader-only<h3>headings added before each message block so users can skim the conversation by heading level ("You said:", "[Model name] said:", "Assistants said:").Messages.svelte+stores/index.ts++layout.svelte— Globalaria-liveregions placed outside all content areas (in the document root via+layout.svelte) so NVDA browse-mode navigation never lands on them.Messages.sveltewrites generation status ("Generating response…" / "Still generating…" every 6 s) and the completed plain-text response to global Svelte stores. The live region fires on response completion and during streaming.en-US/translation.json— 8 new i18n keys registered for the newaria-labelvalues.Breaking Changes
Additional Information
<ul role="log">that previously surrounded the message list has been changed to a plain<div>because the live region responsibility moved to the globalaria-liveregions in+layout.svelte. Keepingrole="log"on the list would cause double-announcements.#generate-message-pair-buttonis a programmatic trigger (not user-facing);aria-hidden="true"ensures AT does not enumerate it.Screenshots or Videos
No visual changes (all modifications are ARIA attributes and
sr-onlyelements).Contributor License Agreement
By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.