fix(a11y): improve model selector accessibility with proper listbox/option pattern (#21706)

- Replace incorrect aria-roledescription='model-item' with role='option' and aria-selected on ModelItem.svelte. The previous attribute was not a valid ARIA role description and provided no useful information to screen readers.

- Add contextual aria-label to each model item button (e.g. 'Select GPT-4 model') instead of just the raw model name, making the action clear to screen reader users.

- Add role='listbox' and aria-label='Available models' to the scrollable model list container in Selector.svelte so screen readers announce the container's purpose and navigate items correctly.

- Make the model selector trigger button's aria-label dynamic: it now announces 'Selected model: GPT-4' when a model is selected, falling back to 'Select a model' when nothing is selected.

- Add aria-label to the eject (unload) button in ModelItem.svelte so screen readers announce its purpose.

- Add aria-label to the cancel download button in Selector.svelte with the specific model name being canceled.

- Improve model profile image alt text from generic 'Model' to contextual '{{modelName}} profile image'.
This commit is contained in:
Classic298 authored and GitHub committed 2026-02-21 16:14:09 -06:00
1 parent b559606387
commit 08f1c823ad
2 files changed
+9 -4

No files matched your search

@@ -402,7 +402,7 @@
class="relative w-full {($settings?.highContrastMode ?? false)
? ''
: 'outline-hidden focus:outline-hidden'}"
aria-label={placeholder}
aria-label={selectedModel ? $i18n.t('Selected model: {{modelName}}', { modelName: selectedModel.label }) : placeholder}
id="model-selector-{id}-button"
>
<div
@@ -600,6 +600,8 @@
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="max-h-64 overflow-y-auto"
role="listbox"
aria-label={$i18n.t('Available models')}
bind:this={listContainer}
on:scroll={() => {
listScrollTop = listContainer.scrollTop;
@@ -681,6 +683,7 @@
<Tooltip content={$i18n.t('Cancel')}>
<button
class="text-gray-800 dark:text-gray-100"
aria-label={$i18n.t('Cancel download of {{model}}', { model: model })}
on:click={() => {
cancelModelPullHandler(model);
}}