Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

(WIP) feat(tabs): make accessible #1714

Closed
wants to merge 1 commit into from
Closed

Conversation

bekos
Copy link
Contributor

@bekos bekos commented Jan 31, 2014

TODO: add keyboard navigation

@Foxandxss
Copy link
Contributor

With little changes like this one we can do good things 👍

@ndarilek
Copy link

ndarilek commented Feb 2, 2014

Would love to see this merged. I'm a blind web developer refactoring to Angular directives, and was disappointed to discover that tabs weren't keyboard accessible. Tabbing between them didn't work, nor did selecting them with enter.

That said, I wasn't sure what the best keyboard access model might be. Typical tab-and-enter is the most obvious choice, but there are sometimes instances where I'd want a more traditional menu/tab flow (I.e. tab to a horizontal menu that gets treated as a single tab stop, then left/right arrow through horizontal items, selecting with enter.) I'm not familiar enough with directives to know if, say, I could override key handling on an individual instance, but there's definitely not a one-size-fits-all for keyboard access. My hope is that directives are flexible enough to account for that.

@pkozlowski-opensource
Copy link
Member

@ndarilek thnx for looking into this. We are determined to make those directives accessible so an remarks from a person using a screen reader on a daily basis would be highly appreciated. If you've got any suggestions regarding tabs or any other directive, please share.

@ndarilek
Copy link

ndarilek commented Feb 2, 2014

Cool. I'm new to Angular and directives, so realize this question is
somewhat off-topic to this issue, but it does impact how I think about
this. How are standard HTML attributes merged into directives?

For instance, my current Angular app just uses standard Bootstrap tabs
in a

element. Given that I'm using plain HTML, I get the ability
to tab through tab links for free. However, if I wanted to implement a
navigation style where the tab key only landed on the menu, and the user
needed to use right and left arrows to cycle through menu items (I.e.
similar to standard system menus or tab bars), I need only set
tabindex=0 on the root nav, -1 on each link, and a custom key handler.
I'd also set ARIA roles on the nav and each link to mark them as a menu
and menu items, respectively.

These wouldn't necessarily be good changes to roll into the default
directive though, since they're highly opinionated and complicate
things. But if I were to set a tabindex/aria-role on the root ,
then aria-roles/tabindexes on each or , would those
attributes get merged into sensible locations on the generated HTML?

@bekos
Copy link
Contributor Author

bekos commented Feb 2, 2014

@ndarilek We try to encapsulate the Bootstrap's HTML complexity, into one custom element. So, by just adding these attributes on the tabset or tab element is not going to work.

The good news though, is that every template is very easy to override and apply any custom behavior and attributes you want without any special effort.
For the tabs we are going to implement the standard behavior of landing on the menu once and then using the arrow keys to navigate.

If you want to build the project locally, you can try and feedback for the rating and the progressbar directives that have already been made accessible.

Anyway, it would be awesome if you could help with this effort in this and the other directives :-)

@ndarilek
Copy link

ndarilek commented Feb 2, 2014

Hmm, I'd have to think through this a bit more. As I see it, there are
three navigation paradigms:

  1. A simple list of links used for navigating between site areas. My
    expectation as a keyboard user is that I can tab between these.
  2. A menubar with drop-down menus, as found in native apps. In this
    case, my expectation would be to tab onto the menu item, using
    right/left or up/down arrows to navigate (depending on whether the menu
    is horizontal or vertical.) I'd also expect ARIA roles to be set
    correctly to identify the container as a menu and each as
    a menu item, with activation states represented accordingly. In these
    instances, they shouldn't appear as links.
  3. A series of horizontal tabs, as seen in tabbed native interfaces.
    Here my expectation would be the same re: tab and arrow key navigation,
    but with ARIA states set to those representing tabs rather than
    menus/menu items.

I'm not sure which should be used in this instance. It's tough being
more specific because I don't know how Bootstrap tabs look compared to
native-ish menus/tabs and lists of links. It's also possible that the
behavior should differ based on whether the tabset's type is 'tabs' or
'pills' (I.e. if one looks like a menubar while the other resembles a
series of tabs in a preference pane.)

@bekos
Copy link
Contributor Author

bekos commented Feb 3, 2014

While trying to implement the keyboard navigation I faced a problem with the tabs array in the controller. The ctrl.tabs does not have the order of the tabs as they appear in the HTML, but apparently, as the linking function fires for each of them.

But, because linking function for the static tabs fire before the dynamic (ie ng-repeat) ones, the order we have is sometimes falsy. For example, for the tab's demo:

<tabset>
    <tab heading="Static title">Static content</tab>
    <tab ng-repeat="tab in tabs" heading="{{tab.title}}" ></tab>
    <tab heading="Alert title"></tab>
  </tabset>

the actual order for the tabs in controller is: [Static title, Alert title, Dynamic 1, Dynamic 2].

There is a workaround, like having a "global" variable inside the tab's directive code, that you use in the compile function, to keep reference of the order when you add the tab on the controller, but as you understand this gets very messy :-(

@angular-ui/bootstrap I wonder, if I miss something obvious or this is an issue I should raise in the AngularJS.

@chrisirhc
Copy link
Contributor

@bekos , there's a similar issue with slides in the carousel. The tabs array also needs to update what the tabs are re-ordered, and ngRepeat re-orders them.

Off the top of my head, the easiest way I can think of is to watch the .childNodes (DOM) of the tabset and matching the order of the child nodes with the order of ctrl.tabs. Not sure if $watchCollection works on NodeLists.

@bekos
Copy link
Contributor Author

bekos commented Feb 4, 2014

@chrisirhc Thx for the info. Do you think it's worth raising this issue at Angular?

@chrisirhc
Copy link
Contributor

@bekos, just thought of another thing, it might be interesting to see if the scope's child scope order reflects the order of the DOM. I think one of the early principles of Angular (I could be wrong, or this might've changed) is that the scope reflects what's in the DOM.

That might be a way to raise the issue at Angular, to see if there are any plans to make the expose child element/directives order perhaps through the scope.

And yes, I think it's worth raising it, just not sure how to put it across. Perhaps directives need to be aware of child element directives' order? Something like the jqLite's find but just for "finding" directives.

@icfantv
Copy link
Contributor

icfantv commented Oct 29, 2015

Closing in favor of #4772.

@icfantv icfantv closed this Oct 29, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants