A11Y: make the uppy image uploader keyboard navigable (#29807)

This commit is contained in:
Kris 2024-11-19 15:38:13 -05:00 committed by GitHub
parent 84fecd370c
commit acc7caa816
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 56 additions and 1 deletions

View File

@ -9,13 +9,16 @@
<label
class="btn btn-default pad-left no-text {{if this.disabled 'disabled'}}"
title={{this.disabledReason}}
for={{this.computedId}}
tabindex="0"
{{on "keydown" this.handleKeyboardActivation}}
>
{{d-icon "far-image"}}
<PickFilesButton
@registerFileInput={{this.uppyUpload.setup}}
@fileInputDisabled={{this.disabled}}
@fileInputClass="hidden-upload-field"
@acceptedFormatsOverride="image/*"
@fileInputId={{this.computedId}}
/>
</label>

View File

@ -1,6 +1,7 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { or } from "@ember/object/computed";
import { guidFor } from "@ember/object/internals";
import { getOwner } from "@ember/owner";
import { next } from "@ember/runloop";
import { htmlSafe } from "@ember/template";
@ -58,6 +59,12 @@ export default class UppyImageUploader extends Component {
});
}
@discourseComputed("id")
computedId(id) {
// without a fallback ID this will not be accessible
return id ? `${id}__input` : `${guidFor(this)}__input`;
}
@discourseComputed("siteSettings.enable_experimental_lightbox")
experimentalLightboxEnabled(experimentalLightboxEnabled) {
return experimentalLightboxEnabled;
@ -155,4 +162,15 @@ export default class UppyImageUploader extends Component {
this.setProperties({ imageUrl: null });
}
}
@action
handleKeyboardActivation(event) {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault(); // avoid space scrolling the page
const input = document.getElementById(this.computedId);
if (input && !this.disabled) {
input.click();
}
}
}
}

View File

@ -116,6 +116,29 @@ describe "Admin About Config Area Page", type: :system do
expect(config_area.general_settings_section).to have_saved_successfully
expect(SiteSetting.about_banner_image).to eq(nil)
end
it "can upload an image using keyboard nav" do
config_area.visit
image_file = file_from_fixtures("logo.png", "images")
config_area.general_settings_section.banner_image_uploader.select_image_with_keyboard(
image_file.path,
)
expect(config_area.general_settings_section.banner_image_uploader).to have_uploaded_image
end
it "can remove the uploaded image using keyboard nav" do
SiteSetting.about_banner_image = image_upload
config_area.visit
config_area.general_settings_section.banner_image_uploader.remove_image_with_keyboard
config_area.general_settings_section.submit
expect(config_area.general_settings_section).to have_saved_successfully
expect(SiteSetting.about_banner_image).to eq(nil)
end
end
end

View File

@ -11,6 +11,12 @@ module PageObjects
attach_file(path) { @element.find("label.btn-default").click }
end
def select_image_with_keyboard(path)
label = @element.find("label.btn-default")
label.send_keys(:enter)
attach_file(path) { label.click }
end
def has_uploaded_image?
# if there's a delete button (.btn-danger), then there must be an
# uploaded image.
@ -22,6 +28,11 @@ module PageObjects
def remove_image
@element.find(".btn-danger").click
end
def remove_image_with_keyboard
delete_button = @element.find(".btn-danger")
delete_button.send_keys(:enter)
end
end
end
end