How to use isAccessibilityElement && accessibilityElementsHidden in ReactJS class to solve Voiceover issue - reactjs

I have a Vertical menu that is styled as a dropdown.
on iPhone, when Voiceover is on, double tab will open the dropdown, swipe Right will go through menu items, and when gets to the last menu item, Swipe Right will close the dropdown and gives focus to the first link outside of Menu.
Now, dropdown menu is closed. and menu items are not visible. Normally, one single Left swipe should moves the focus from outside link to the dropdown header while Voiceover is ON.
but the problem is, it takes multiple Left Swipe equal to the number of menu items 4+ 1 to get from outside link to dropdown header. Voiceover is not announcing anything, I can only see on iPhone screen Voiceover text reading Manu item which is the same as <a role="menuitem">.
it looks like Voiceover still recognizes the menu items although the dropdown menu is closed.
If I do NOT open dropdown menu, 1 right swipe moves focus from dropdown header to outside link, and then 1 left swipe move focus from outside link to dropdown header. the problem happens when I open dropdown menu and swipe right through menu items.
I tried to resolve this by giving UL, Li , <a> the combination of these attributes but did not work.
When menu is closed:
aria-hidden=true, tabIndex=-1, display=none, visibility=hidden
but did not work.
I am wondering if I can implement isAccessibilityElement && accessibilityElementsHidden for React JS.
I see how the import command and code for React Native but nothing for React JS.
My Question is: when dropdown menu is closed, lets say focus is on outsideLink, how can I bring focus to dropdownHeader with one Left Swipe ?
How to force Voiceover to ignore menu items when dropdown menu is closed.
Note: my module is a Class in React JS.
Really appreciate any help.
import React, { Component } from 'react'
// help needed : how to import UISwipeGestureRecognizer for React JS
class App extends Component {
constructor(props){
super(props)
this.state = {
menuOpen: false,
}
this.closeMenu = this.closeMenu.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
this.handleSwipe = this.handleSwipe.bind(this);
}
componentDidMount () {
window.addEventListener('touchstart', handleSwipe);
}
closeMenu(event){
this.setState({menuOpen: false});
this.handleSwipe(event);
}
toggleMenu(event){
this.setState({menuOpen: !this.state.menuOpen});
}
handleSwipe(event){
const outsideLinkFocused = event.target.classList.contains('outsideLink');
const itemsArray = [...document.getElementsByClassName('item')];
if(outsideLinkFocused){
itemsArray.map(item => {
// need Help here
item.isAccessibilityElement = false;
item.accessibilityElementsHidden = true;
});
}
}
render() {
return (
<div className="Container">
<div className="NavContainer">
<button className="dropdownHeader">
Dropdown Header
</button>
<ul className="menu" role="menu">
<li className="item" role="none">
<a role=="menuitem" href="#"> item 1</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 2</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 3</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 4</a>
</li>
</ul>
</div>
<div className="ArticleContainer">
<a className="outsideLink" href="#"> Outside Link </a>
</div>
</div>
)
}
}
This module is more complex and all the handlers work fine. I just wrote a short version here.

Related

How to use UISwipeGestureRecognizer in ReactJS

I have a Vertical menu that is styled as a dropdown.
on iPhone, when Voiceover is on, double tab will open the dropdown, swipe Right will go through menu items, and when gets to the last menu item, Swipe Right will close the dropdown and gives focus to the first link outside of Menu.
Now, dropdown menu is closed. and menu items are not visible. Normally, one single Left swipe should moves the focus from outside link to the dropdown header while Voiceover is ON.
but the problem is, it takes multiple Left Swipe equal to the number of menu items 4+ 1 to get from outside link to dropdown header. Voiceover is not announcing anything, I can only see on iPhone screen Voiceover text reading Manu item which is the same as <a role="menuitem">.
it looks like Voiceover still recognizes the menu items although the dropdown menu is closed.
If I do NOT open dropdown menu, 1 right swipe moves focus from dropdown header to outside link, and then 1 left swipe move focus from outside link to dropdown header. the problem happens when I open dropdown menu and swipe right through menu items.
I tried to resolve this by giving UL, Li , <a> the combination of these attributes but did not work.
When menu is closed:
aria-hidden=true, tabIndex=-1, display=none, visibility=hidden
but did not work.
I am wondering if I can implement UISwipeGestureRecognizer for React JS.
I see how the import command and code for React Native but nothing for React JS.
My Question is: when dropdown menu is closed, lets say focus is on outsideLink, how can I bring focus to dropdownHeader with one Left Swipe ?
How to force Voiceover to ignore menu items when dropdown menu is closed.
Note: my module is a Class in React JS.
Really appreciate any help.
import React, { Component } from 'react'
// help needed : how to import UISwipeGestureRecognizer for React JS
class App extends Component {
constructor(props){
super(props)
this.state = {
menuOpen: false,
}
this.closeMenu = this.closeMenu.bind(this);
this.toggleMenu = this.toggleMenu.bind(this);
this.handleSwipe = this.handleSwipe.bind(this);
}
componentDidMount () {
window.addEventListener('touchstart', handleSwipe);
}
closeMenu(event){
this.setState({menuOpen: false});
this.handleSwipe(event);
}
toggleMenu(event){
this.setState({menuOpen: !this.state.menuOpen});
}
handleSwipe(event){
const outsideLinkFocused = event.target.classList.contains('outsideLink');
const dropdownHeader = document.getElementsByClassName('dropdownHeader')[0];
const leftSwipe = UISwipeGestureRecognizer.direction == 'left'; // I need help with leftSwipe condition
if(outsideLinkFocused && leftSwipe){
dropdownHeader.focus();
}
}
render() {
return (
<div className="Container">
<div className="NavContainer">
<button className="dropdownHeader">
Dropdown Header
</button>
<ul className="menu" role="menu">
<li className="item" role="none">
<a role=="menuitem" href="#"> item 1</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 2</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 3</a>
</li>
<li className="item" role="none">
<a role=="menuitem" href="#"> item 4</a>
</li>
</ul>
</div>
<div className="ArticleContainer">
<a className="outsideLink" href="#"> Outside Link </a>
</div>
</div>
)
}
}
This module is more complex and all the handlers work fine. I just wrote a short version here.

Set focus to an element when another element has focus with ng-focus

I have angularJS application.There are two components left nav bar and right side content pane.When I go to the end of the right side content pane with tab(keyboard) it gives the focus to the browser URL bar.But I need to give the tab(keyboard) focus to the left nav bar or just need to stop focus getting in to url.
..below is the end of the content pane
<div>
<ul>
<li class="seperater">
test navigate
</li>
</ul>
</div>
What I tried is when focus came to the final element on the content page ,call a method 'navigateToTop' and there I set focus to left nav.
below is the method
this.navigateToTop = function () {
console.log("in navigateToTop");
$('#left-nav').focus();
};
But it is not working and still focusing to the URL.Pls help..
After spending some time I found the solution by doing some changes to my html code of the right content pane.
<div>
<ul>
<li class="seperater">
<a href="" ng-focus="isFocused = true" ng-blur="isFocused = false">
test navigate </a>
</li>
</ul>
<div ng-if="navigateToTop(isFocused);"></div>
</div>

React implement active menu item in sidebar

I'm using React version 16.6.3. I need some help to implement active menu item in sidebar. I need to do this thing: when the user clicks on any <li> in sidebar, the <li> must become active (for example, it gets class "active").
If the <li> is active and have treeview class, then, inside it, set to <ul> class "show" (if any)
Here's the code:
import React , { Component } from "react"
export default class Sidebar extends Component {
constructor(props) {
super(props);
this.state = { 'activeItem': 0 }
}
render() {
return (
<div className="main-sidebar">
<section className="sidebar">
<ul className="sidebar-menu tree">
<li className="nav-divider"></li>
<li className="header">PERSONAL</li>
<li>
<a href="#">
<span>Dashboard</span>
</a>
</li>
<li className="treeview">
<a href="#">
<span>Application</span>
</a>
<ul class="treeview-menu">
<li>Chat app</li>
<li>Project</li>
<li>Contact / Employee</li>
</ul>
</li>
<li className="treeview">
<a href="#">
<span>Application</span>
</a>
</li>
</ul>
</section>
</div>
)
}
}
The first question you should ask yourself is (if not always) how you store the data of the user selection. You might have multiple activeItem because this is a tree, ex. multiple branches can be open or close at the same time. You need to look for a data structure to hold that thinking first.
Here's a simple one, give each item an id/key, <li key="1-0-0"> and then you can track onChange event of this li and then inside onChange you can use a flat array structure to store the current state of this simple tree. For example, {'1-0-0': true }
There're lots of different ways to do data part, the above one is a simple idea to get you started. And after that, based on the captured data, you can then update the children attribute of each node, ex. <li className={ getNodeAttr('1-0-0')> assuming getNodeAttr is a utility function that give you back the class name string given the node name.
You should not bind active state on a navigation sidebar because if a user type a route directly in a browser the menu item won't be highlighted.
Instead, try to bind the active state to the route with NavLink (if you use react-router):
ref: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/NavLink.js

Dynamically built Navigation bar using angulars but not working properly

I have build sidebar navigation menu from API JSON data.
But after bind data to sidebar navigation menu it will showing all menu with collapsed state after click on some option in sidebar navigation menu then it is working properly.
but at initial stage it is collapsed.
also when i click on some option in some menu of sidebar it is not in collapsed state that menu is closed state but if i click on option from same menu then it is collapsed state
<li ng-repeat="link in links" ui-sref-active="active" >
<i class="{{ link.ShortName }}"></i><span class="nav-label">{{ link.Name | translate }}</span><span class="fa arrow"></span>
<ul class="nav nav-second-level">
<li ng-repeat="subItem in link.ProgramList">
<a ui-sref="{{subItem.AccessibleName}}" ui-sref-opts="{reload: true}">{{ subItem.Name | translate }}
</a>
</li>
</ul>
</li>
this is API call
$http.get('http://localhost:53396/api/Module/Get').success(function (data) {
$scope.links = data;
});

How to show tab with carousel avoiding sliding from the current image to the selected image?

In my Angular app I have a simple twitter-bootstrap carousel, in a tab:
<div class="tabbable">
<ul class="nav nav-pills">
<li ng-class="{active: tabSelected === 'main'}">
Main
</li>
<li ng-class="{active: tabSelected === 'photos'}">
Photos
</li>
</ul>
</div>
...
<div class="tab-content" ng-show="tabSelected === 'photos'>
<div class="slides-control">
<carousel disable-animation="false">
<slide ng-repeat="photo in person.photos" active="photo.active">
<img class="slide" ng-src="{{photo.path}}" />
</slide>
</carousel>
</div>
</div>
In the controller I have defined a method, tabSelect(tabName, photoNumber), which allows the tab to be selected in code, and - if the tab is the one named 'photos' - a specific image number can be selected:
<script>
$scope.tabSelect = function (tabName, photoNumber) {
if (tabName === 'photos') {
$scope.person.photos[0].active = false;
$scope.person.photos[photoNumber].active = true;
}
$scope.tabSelected = tabName;
};
</script>
The problem is this:
When calling, for example, $scope.tabSelect('photos', 7);, the photos tab is shown, but initially the previously active image is shown, and then immediately it slides to the selected image (the 7th, in the example). I don't want to avoid using animations, which are quite cool... Though, I want to display immediately the selected image...
I did already try to surround the $scope.tabSelected = tabName; instruction in a $timeout() block, and the selected slide is immediately shown, but not fully rendered (for example, the arrows are not present...).

Resources