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

Upload Form Combo Boxes WCAG Failures #254

Open
amccollo opened this issue Aug 26, 2024 · 1 comment
Open

Upload Form Combo Boxes WCAG Failures #254

amccollo opened this issue Aug 26, 2024 · 1 comment

Comments

@amccollo
Copy link

amccollo commented Aug 26, 2024

  1. Contents and/or State of items from dropdown lists and comboboxes often not available to AT and/or are not completely keyboard accessible. (e.g., Subject Select, Languages, Additional Description/Language, Add Standard Award/Funder)

  2. Required dropdown fields (e.g., Resource Type and Creators) are not properly labeled.

Example of non-compliant "Subject Select" combobox form field, followed by improved code sample:

<div class="eleven wide field invenio-remote-select-field"><label><label for="metadata.subjects" class="mobile-hidden">
        </label></label>
    <div name="metadata.subjects" field="[object Object]" role="combobox" aria-busy="false" aria-expanded="true"
        class="ui active visible fluid multiple search selection dropdown"><input id="metadata.subjects"
            aria-autocomplete="list" autocomplete="off" class="search" tabindex="0" type="text" value="human"
            style="width: 87px;"><span class="sizer" style>human</span>
        <div aria-atomic="true" aria-live="polite" role="alert" class="divider default text filtered">Search for a
            subject by
            name</div><i aria-hidden="true" class="dropdown icon"></i>
        <div aria-multiselectable="true" role="listbox" class="visible menu transition">
            <div data-additional="true" role="option" aria-checked="false" aria-selected="true"
                class="selected item addition" style="pointer-events: all;"><span class="text">Add
                    <b>human</b></span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/0627c833-88fb-4bbd-86b4-1eb20529fb17"
                subject="Digital humanities" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Digital humanities</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/7a2dcf7b-2c20-468a-a81c-76d67c14de31" subject="Humanities"
                role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><span
                    class="text">(EuroSciVoc)
                    Humanities</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/4f546680-d48b-4c0d-9c81-9870b0a16c32"
                subject="Human migrations" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Human migrations</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/a708050b-3b9b-47bb-86cb-2737aa0e0cf4"
                subject="Human rights law" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Human rights law</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/ace9a277-0a73-4d3c-8728-3b0279a4b069"
                subject="Human rights violations" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Human rights violations</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/e2120c91-f57d-4f96-8992-59c109634f1c"
                subject="Other humanities" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Other humanities</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/7f6f9d2d-c94a-4d5e-bfd2-76dbd4df61e0"
                subject="Regional human rights" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Regional human rights</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/ca0b52b4-4d64-4b75-a231-06ea45752be6" subject="Human rights"
                role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><span
                    class="text">(EuroSciVoc)
                    Human rights</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/da44150d-4cff-45ba-8a81-12023a679ac3"
                subject="International protection of human rights" role="option" aria-checked="false"
                aria-selected="false" class="item" style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    International protection of human rights</span></div>
            <div id="http://data.europa.eu/8mn/euroscivoc/e650a829-2773-4e7d-98dc-1a1d0b415df1"
                subject="Human trafficking" role="option" aria-checked="false" aria-selected="false" class="item"
                style="pointer-events: all;"><span class="text">(EuroSciVoc)
                    Human trafficking</span></div>
        </div>
    </div>
</div>

Issues with the above code:

Ensure the Label is Properly Associated:The label currently has a nested label element with no accessible text or description. This can be improved by associating the label directly with the input using the for attribute and providing meaningful text.

Correct the Use of name Attribute:The name attribute is being incorrectly used on a div element. It should either be removed or replaced with a valid attribute that applies to div elements, like data-* attributes.

Role and ARIA Attributes:Ensure that the roles and ARIA attributes are correctly used and clearly convey the purpose of each interactive element. For example, the combobox should clearly indicate its expanded state, and options should convey selection status appropriately.

Keyboard Accessibility:Ensure that all interactive elements are keyboard accessible, with focusable attributes like tabindex and appropriate event handling for keyboard interaction.

Add Accessible Descriptions:Use aria-describedby or similar attributes to provide additional context or descriptions where needed.

Improved version:

<div class="eleven wide field invenio-remote-select-field">

<!-- Properly associate label -->
<label for="metadata-subjects" class="mobile-hidden">Select Subject</label>

<!-- Use a data attribute instead of name, add proper ARIA attributes -->
<div id="metadata-subjects" data-field="subjectField" role="combobox" aria-busy="false" aria-expanded="true" aria-haspopup="listbox" aria-labelledby="metadata-subjects-label" aria-controls="metadata-subjects-listbox" class="ui active visible fluid multiple search selection dropdown">


<!-- Input element with ARIA properties for accessibility -->
<input id="metadata-subjects-input" aria-autocomplete="list" aria-controls="metadata-subjects-listbox" autocomplete="off" class="search" tabindex="0" type="text" value="human" style="width: 87px;">

<span class="sizer">human</span>

<!-- Alert to provide live updates to screen readers -->
<div aria-atomic="true" aria-live="polite" role="alert" class="divider default text filtered">Search for a subject by name</div>

<i aria-hidden="true" class="dropdown icon"></i>

<!-- Listbox with ARIA attributes -->
<div id="metadata-subjects-listbox" aria-multiselectable="true" role="listbox" class="visible menu transition">
  
  <!-- Listbox options with proper ARIA roles and states -->
  <div data-additional="true" role="option" aria-checked="false" aria-selected="true" class="selected item addition" style="pointer-events: all;">
    <span class="text">Add <b>human</b></span>
  </div>
  
  <div id="option-1" subject="Digital humanities" role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;">
    <span class="text">(EuroSciVoc) Digital humanities</span>
  </div>
  
  <!-- Additional options as needed -->
  
</div>
</div>
</div>

Example of non-compliant required dropdown field (Resource Type):

<div name="metadata.resource_type" field="[object Object]" aria-label="Resource type" labelclassname="field-label-class"
    required="" role="listbox" aria-expanded="true" aria-multiselectable="false"
    class="ui active visible fluid selection dropdown" tabindex="0">
    <div aria-atomic="true" aria-live="polite" role="alert" class="divider text">Lesson</div><i aria-hidden="true"
        class="dropdown icon"></i>
    <div class="visible menu transition">
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="table icon"></i><span class="text">Dataset</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="calendar alternate outline icon"></i><span class="text">Event</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image / Diagram</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image / Drawing</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image / Figure</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image / Other</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image / Photo</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Image / Plot</span></div>
        <div role="option" aria-checked="true" aria-selected="true" class="active selected item"
            style="pointer-events: all;"><i aria-hidden="true" class="graduation icon"></i><span
                class="text">Lesson</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="chart bar outline icon"></i><span class="text">Model</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="asterisk icon"></i><span class="text">Other</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="cube icon"></i><span class="text">Physical object</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="columns icon"></i><span class="text">Poster</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="group icon"></i><span class="text">Presentation</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Annotation
                collection</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Book</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Book chapter</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Conference
                paper</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Conference
                proceeding</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Data paper</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Dissertation</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Journal</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Journal
                article</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Other</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Output management
                plan</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Patent</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Peer review</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Preprint</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Project
                deliverable</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Project
                milestone</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Proposal</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Report</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Software
                documentation</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Standard</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Taxonomic
                treatment</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Technical
                note</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Thesis</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="file alternate icon"></i><span class="text">Publication / Working paper</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="code icon"></i><span class="text">Software</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="code icon"></i><span class="text">Software / Computational notebook</span>
        </div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="film icon"></i><span class="text">Video/Audio</span></div>
        <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><i
                aria-hidden="true" class="code fork icon"></i><span class="text">Workflow</span></div>
    </div>
</div>

1. Analysis of the Current Code

Role and Accessibility

The role="listbox" attribute is correctly used, indicating that the element functions as a listbox. The aria-multiselectable="false" attribute specifies that the listbox does not support multiple selections.

The aria-expanded="true" attribute indicates that the dropdown is currently open, which is appropriate.

The aria-label="Resource type" attribute provides a label for screen reader users, which is good for accessibility.

Missing Elements

There is no visible label associated with the dropdown. While aria-label is used, it’s better to have a visible label and link it to the dropdown using the for attribute.

The required attribute is present, but it is set to an empty string (required=""). This does not fully indicate that the field is required to assistive technologies.

The aria-describedby attribute could be used to provide additional context or error messages.

Interactive Elements

The tabindex="0" makes the dropdown keyboard navigable, which is good, but additional focus management for options should be ensured.

2. Enhancements for WCAG Conformance

To make the code more conformant with WCAG 2.1 Success Criterion 4.1.2, especially for a required field, the following enhancements are suggested:


<div class="eleven wide field invenio-remote-select-field">
  <!-- Visible label added and associated with the dropdown -->
  <label for="metadata-resource-type" class="field-label-class">
    Resource Type <span aria-hidden="true" style="color: red;">*</span>
  </label>
  
  <!-- Updated dropdown element -->
  <div id="metadata-resource-type" name="metadata.resource_type" field="[object Object]" aria-label="Resource type" aria-required="true" role="listbox" aria-expanded="true" aria-multiselectable="false" class="ui active visible fluid selection dropdown" tabindex="0" aria-describedby="metadata-resource-type-description">
    
    <!-- Description or error message linked via aria-describedby -->
    <div id="metadata-resource-type-description" aria-atomic="true" aria-live="polite" role="alert" class="divider text">
      Lesson
    </div>
    
    <i aria-hidden="true" class="dropdown icon"></i>
    
    <div class="visible menu transition">
      <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;">
        <i aria-hidden="true" class="table icon"></i><span class="text">Dataset</span>
      </div>
      <div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;">
        <i aria-hidden="true" class="calendar alternate outline icon"></i><span class="text">Event</span>
      </div>
      <!-- Other options continue as before -->
    </div>
  </div>
</div>
@amccollo amccollo converted this from a draft issue Aug 26, 2024
@amccollo
Copy link
Author

NB: @ptamarit observes that the problems in this ticket are traceable first to semantic-ui and has some ideas about how to address problems with semantic-ui not actually being very semantically conformant:

  • Concerning my remark regarding the dropdown/combobox in React Semantic UI, I initially thought that it might be easy to patch this component to “make it work”, but I now have the feeling that making it fully compliant is a lot of effort, and using an existing compliant implementation would be a better choice.

  • One route I’d like to explore is to use a headless component (see this article for an introduction on the concept), and generate HTML reusing the Semantic UI CSS classes, so that the look would be the same, but the underlying implementation would be accessible. The downshift library looks like a good candidate to me, with the downside that it addresses “only” dropdown/combobox components.

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

No branches or pull requests

5 participants
@amccollo and others