mirror of
https://github.com/open-webui/open-webui.git
synced 2026-02-24 04:00:31 +01:00
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:
@@ -44,8 +44,9 @@
|
||||
</script>
|
||||
|
||||
<button
|
||||
aria-roledescription="model-item"
|
||||
aria-label={item.label}
|
||||
role="option"
|
||||
aria-selected={value === item.value}
|
||||
aria-label={$i18n.t('Select {{modelName}} model', { modelName: item.label })}
|
||||
class="flex group/item w-full text-left font-medium line-clamp-1 select-none items-center rounded-button py-2 pl-3 pr-1.5 text-sm text-gray-700 dark:text-gray-100 outline-hidden transition-all duration-75 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-xl cursor-pointer data-highlighted:bg-muted {index ===
|
||||
selectedModelIdx
|
||||
? 'bg-gray-100 dark:bg-gray-800 group-hover:bg-transparent'
|
||||
@@ -78,7 +79,7 @@
|
||||
<Tooltip content={$user?.role === 'admin' ? (item?.value ?? '') : ''} placement="top-start">
|
||||
<img
|
||||
src={`${WEBUI_API_BASE_URL}/models/model/profile/image?id=${item.model.id}&lang=${$i18n.language}`}
|
||||
alt="Model"
|
||||
alt={$i18n.t('{{modelName}} profile image', { modelName: item.label })}
|
||||
class="rounded-full size-5 flex items-center"
|
||||
loading="lazy"
|
||||
/>
|
||||
@@ -235,6 +236,7 @@
|
||||
>
|
||||
<button
|
||||
class="flex"
|
||||
aria-label={$i18n.t('Eject model')}
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -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);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user