Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPIKE] Explore progressively enhanced file upload component #5305

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

querkmachine
Copy link
Member

@querkmachine querkmachine commented Sep 10, 2024

As part of post-audit investigations, a spike into layering a new UI onto the File upload component that should be a bit more friendly to assistive technologies. alphagov/govuk-design-system#4031

Note: This hasn't actually been tested across browsers and ATs yet,

Changes

  • Progressively enhances the file input of the File upload component with a custom button and file selection display.
    • This new UI localisable. This adds the potential for buttons to better describe what needs uploading.
    • As much as possible, this new UI behaves similarly to the browser's native controls (e.g. can click on the label or input text to activate the component; supports multiple, accepts and capture attributes; etc.)
  • Adds a visual drop zone if a file is dragged over the input.

Thoughts

  • There are some features that are not supported yet. For example, the button will still appear useable even if the underlying input has been disabled.
  • The native file input is visually hidden but is still exposed to screen readers. I wasn't sure if I could (or should) hide it from them, as it may contain context that the 'enhanced' controls do not. Further testing needed.
  • This has been developed to pretty closely resemble native file inputs as they appear in Chromium browsers. We may be interested in styling them more similarly to other form inputs (e.g. having a black border around it.)
  • The visual drop zone currently only appears when dragging over the input itself. It may be preferable for it to appear if a file is dragged over anywhere on the page.

Copy link

github-actions bot commented Sep 10, 2024

📋 Stats

File sizes

File Size
dist/govuk-frontend-development.min.css 119.03 KiB
dist/govuk-frontend-development.min.js 45.82 KiB
packages/govuk-frontend/dist/govuk/all.bundle.js 97 KiB
packages/govuk-frontend/dist/govuk/all.bundle.mjs 91.1 KiB
packages/govuk-frontend/dist/govuk/all.mjs 1.25 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend-component.mjs 1.74 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend.min.css 119.02 KiB
packages/govuk-frontend/dist/govuk/govuk-frontend.min.js 45.81 KiB
packages/govuk-frontend/dist/govuk/i18n.mjs 5.55 KiB
packages/govuk-frontend/dist/govuk/init.mjs 7.22 KiB

Modules

File Size (bundled) Size (minified)
all.mjs 86.95 KiB 43.11 KiB
accordion.mjs 25.46 KiB 12.93 KiB
button.mjs 7.96 KiB 3.31 KiB
character-count.mjs 24.39 KiB 10.5 KiB
checkboxes.mjs 7.81 KiB 3.42 KiB
error-summary.mjs 9.87 KiB 4.07 KiB
exit-this-page.mjs 19.08 KiB 9.86 KiB
file-upload.mjs 17 KiB 8.19 KiB
header.mjs 6.46 KiB 3.22 KiB
notification-banner.mjs 8.24 KiB 3.23 KiB
password-input.mjs 17.13 KiB 7.86 KiB
radios.mjs 6.81 KiB 2.98 KiB
service-navigation.mjs 6.44 KiB 3.26 KiB
skip-link.mjs 6.4 KiB 2.76 KiB
tabs.mjs 12.04 KiB 6.67 KiB

View stats and visualisations on the review app


Action run for 980b1c6

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

@selfthinker
Copy link

I've started testing this today. But I've only tested with Dragon so far.

Unfortunately it doesn't work. Roughly 9 out of 10 times saying "click choose file" or "click button" only focused on the button but didn't open the file dialog. And weirdly 1 out of 10 times it did. But I didn't do anything differently between when it did and when it didn't.

When we've figured out why this is happening I will test again, including in other assistive technologies.

@owenatgov
Copy link
Contributor

Rebased this whilst I do some local testing

@edwardhorsford
Copy link
Contributor

Just in case it's helpful - we had a styled upload button on the passport service - which has presumably been tested by DAC multiple times.

@querkmachine
Copy link
Member Author

@edwardhorsford Do you know if it was tested in Dragon NaturallySpeaking and, if so, whether it exhibited the same issues described by @selfthinker?

@edwardhorsford
Copy link
Contributor

@edwardhorsford Do you know if it was tested in Dragon NaturallySpeaking and, if so, whether it exhibited the same issues described by @selfthinker?

I assume it was tested with it as DAC did the testing. But I don't recall more than that. You could try on the live service to see how it works now...

querkmachine and others added 3 commits October 16, 2024 17:03
This change is mutated by a lot of mess from me trying to make typescript not upset with me
@querkmachine
Copy link
Member Author

Adding aria-hidden to the input is apparently ignored by Chromium and raises an error in the console.

Blocked aria-hidden on a <input> element because the element that just received focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden.

tabindex="-1" alone probably suffices for stopping tabbing but I'm not sure if it can prevent keyboard navigation entirely, especially of the kind that screenreaders do which is on a level not easily detected by webpages.

@selfthinker
Copy link

DAC's solution was using the disabled attribute.
But they were partly using it to show the uploaded file.

Setting this via the `attributes` parameter raises complaints from the test that lints our HTML output. Should quieten that failing test.
Chromium actively ignores this attribute on file inputs and throws a warning in the console
Adds a mutation observer that looks to see if the `disabled` attribute of the input changes and, if so, updates the button to match
Dragenter is fired only once when the drag first touches the page, whereas dragover fires continuously.

As we’re only toggling the visbility of the dropzone, dragenter will suffice for our needs.
@matteason
Copy link
Contributor

I tested this out today and spotted a few issues - apologies if you're already aware of these.

Firstly with NVDA (it probably also affects other screen readers but I've only tested NVDA):

With a normal <input type="file">, when it gets focus NVDA reads the <label> text, 'No file chosen' (or the filename if one has been chosen), and 'button' (eg 'Upload a file, no file chosen, button').

With the progressively enhanced file upload, it only reads 'Choose file, button'.

I think having the label read out is important, especially if it's more specific than 'Upload a file'. For example it might specify the type of file to upload - 'Upload a photo of your driving licence'.

One way to resolve this could be to remove the tabindex="-1" from the hidden <input> and put it on the <button> instead. That way, focus would land on the input instead and NVDA would read the label and filename as normal. The button could get its focus style by using the next-sibling combinator: .govuk-file-upload:focus + .govuk-file-upload__button { //focus styles here }. The enter and space keys still work to activate the control, because the <input> has focus.

I'm struggling to think of any other way you could preserve the desired behaviour in both NVDA and Dragon. Making the button aria-labelledby the label and aria-describedby the filename/status would work for NVDA but it would break Dragon compatibility because the visual label wouldn't match the accessible label (so Dragon would be listening for 'Click upload a file', not 'Click choose file').

Another issue (less serious IMO) is that the real <input> and the <button> both appear in NVDA's element list:

NVDA element list with elements named Upload a file; no file chosen; button and choose file; button

My proposed solution doesn't solve this and I'm not sure how to get round it. aria-hidden on the button doesn't work - it would likely hide it from Dragon too, but Chrome blocks you from doing it anyway:

Blocked aria-hidden on an element because its descendant retained focus. The focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden

Finally (unrelated to NVDA), this enhancement only works if the user interacts with another element on the page first. Chrome blocks the file dialog unless the user has interacted with the page, and apparently clicking the button via Dragon doesn't count:

Dragon.enhanced.file.upload.mp4

Even then, only certain interactions seem to count. In the video I say 'Click I accept', which successfully checks the checkbox, but when I then try to activate the file upload Chrome blocks it ("File chooser dialog can only be shown with a user activation."). Only when I say the full name of the checkbox ('Click I accept the terms and conditions') does Chrome then allow me to activate the upload. Dragon must be using two different techniques to check the checkbox depending on whether I abbreviate the label or not.

This is likely to be quite a significant issue on one-thing-per-page-style services, where the file input may well be the only interactive thing on the page beyond the navigation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Investigate solution for operating the file upload component with Dragon
6 participants