React bootstrap: How to enable tab navigation when using Tab component - reactjs

I'm using react-bootstrap version 2.4.0 and I'm using the Tab component. I want the website to be accessible by tab navigation but when I use the tab component the focus is set only on the active tab item and never gets to the other tabs.
<Tabs
className="mb-3"
defaultActiveKey="A"
mountOnEnter={true}
unmountOnExit={true} >
<Tab eventKey="A" title="A">
<A/>
</Tab>
<Tab eventKey="B" title="B">
<B/>
</Tab>
<Tab eventKey="C" title="C">
<C/>
</Tab>
</Tabs>
I noticed that when the page is rendered, all the other tabs (not the active one) have tabindex="-1" on the button of that tab, which makes them inaccessible to tab navigation.
This is what the DOM looks like after react-bootstrap generated its HTML. You can see that the first tab button (the active one) doesn't have the tabindex="-1" attribute on it. The other buttons have it so when I'm using tab navigation they never get the focus and I can never click on them.
<ul class="mb-3 nav-tabs nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<button type="button" id="react-aria2325882265-4-tab-A" role="tab" data-rr-ui-event-key="A" aria-selected="true" class="nav-link active" aria-controls="react-aria2325882265-4-tabpane-A">A</button>
</li>
<li class="nav-item" role="presentation">
<button type="button" id="react-aria2325882265-4-tab-B" role="tab" data-rr-ui-event-key="B" aria-selected="false" tabindex="-1" class="nav-link">B</button>
</li>
<li class="nav-item" role="presentation">
<button type="button" id="react-aria2325882265-4-tab-C" role="tab" data-rr-ui-event-key="C" aria-selected="false" class="nav-link" tabindex="-1">C</button>
</li>
</ul>
How can I use the Bootstrap Tab component and make it accessible with tab navigation?
I saw that if I use the Nav component it doesn't have this problem because it doesn't put the tabindex="-1" on the a tag that is generated by react-bootstrap. However I can't use the Nav component because I don't have a link to go to, but a component to render, and this is exactly what the tab component is used for.

The expected behaviour of Tabs as per ARIA Practices Guideline (APG) is that the arrow keys on the keyboard change focus within this composite component.
Depending on the visual presentation of the tabs, the left and right arrow keys are used for a horizontal arrangement, up and down for vertical ones.
React-Bootstrap’s Tab component implements the arrow keys, but both up/down and left/right navigate the tabs.

Related

Responsive navigation menu with React and Bootstrap - hamburger isn't working

I created a simple navigation menu with Bootstrap. It's working fine in pure javascript, but when adapting it into react, the hamburger icon doesn't function (nothing happens on click). I installed bootstrap with
npm install --save bootstrap
And then added the bootstrap css to index.html in the public folder:
link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
My jsx is as follows:
<nav className="navbar navbar-expand-sm navbar-dark bg-dark">
<div className="container">
<button className="navbar-toggler" data-toggle="collapse" data-target="#navbarNav"><span className="navbar-toggler-icon"></span></button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link to="/app/portfolio" className="nav-link">PORTFOLIO</Link>
</li>
<li className="nav-item">
<Link to="/app/about" className="nav-link">ABOUT</Link>
</li>
<li className="nav-item">
<Link to="#create-head-section" className="nav-link" style={{fontStyle: 'italic'}}>Personal art</Link>
</li>
<li className="nav-item">
<Link to="#share-head-section" className="nav-link">CONTACT</Link>
</li>
</ul>
</div>
</div>
</nav>
Again, everything looks fine except that the hamburger icon is not functioning.
The bootstrap show class is used to display the collapsible menu items. So, the task is to simply add the show class conditionally on click of the hamburger icon.
Just follow these simple steps to achieve this functionality.
Add a showCollapsedMenu(the name is up to you) property with initial value of false in your state like this:
state={
showCollapsedMenu: false
}
Then declare a function like this which when called will reverse the current state:
toggleMenu = () => {
this.setState({
showCollapsedMenu: !this.state.showCollapsedMenu
})
}
The above function will be called whenever the hamburger icon is clicked. So implement the onCLick method on the hamburger icon like this:
<button
className="navbar-toggler"
type="button"
onClick={this.toggleMenu} // <=
data-toggle="collapse"
data-target="#navbarNav">
<span className="navbar-toggler-icon"></span>
</button>
Now create a const show which will conditionally add the show class depending on the state of showCollapsedMenu:
const show = (this.state.showCollapsedMenu) ? "show" : "" ;
Now finally add this show to the div with collapse navbar class like this:
<div className={"collapse navbar-collapse " + show} id="navbarNav">
Note: Mixing jQuery with React is not recommended as they both manipulate the DOM differently. While it may seem an easy solution, it might result in bigger problems.
Bootstrap events require jQuery, Popper and Bootstrap.js source. That page will also let you know which components require JS. You can include jQuery, Popper and bootstrap.js in the index.html file, where you load your bundle. Either add that, or simply check out Reactstrap, which implements Bootstrap components in React.
According to https://www.npmjs.com/package/bootstrap#whats-included, the npm version of Bootstrap doesn't include jQuery, but the navbar component needs it, so you might need to add https://www.npmjs.com/package/jquery to your dependencies.

angular-sidebarjs - sidebar not closing on button click in angularjs

I am new in angular and I have been using angular-sidebarjs in my app. I have given my code of sidebar directive below.
in my template:
<sidebarjs>
<div class="sidebar-head">Find User</div>
<nav>
<ul class="sidebar-menu">
<li ng-repeat="radius in radius">
radius.name
</li>
</ul>
</nav>
</sidebarjs>
in my home.js:
var home = angular.module('wm.home',[uiRouter,'ngSidebarJS'])
When I click on an option among the list, sidebar doesn't close and the required page loads behind. sidebar closes only when I click on the toggle button or outside the sidebar.
How to close the sidebar onclick of any of the options in the list?
You should add the attribute sidebarjs-toggle to your options, like this:
<sidebarjs>
<div class="sidebar-head">Find User</div>
<nav>
<ul class="sidebar-menu">
<li ng-repeat="radius in radius">
<a sidebarjs-toggle href="#" ng-click="listMenus()" ui-sref="users({radius_id: radius_id})" ui-sref-opts="{reload: true}">radius.name</a>
</li>
</ul>
</nav>
</sidebarjs>
Also, I think you should remove that href="#" because you are already doing the routing with the ui-sref.

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 do I set the tabindex (or any other attribute) of an AngularUI Boostrap tab heading link?

I'm using AngularUI Bootstrap like this to create a tabset:
...
<tabset>
<tab heading="First Tab">
<div>First Content Here</div>
</tab>
<tab heading="Second Tab">
<div>Second Content Here</div>
</tab>
</tabset>
...
The code that is output to the page looks like this:
...
<ul class="...">
<li ng-class="..." heading="First Tab" class="...">
<a href ng-click="select()" tab-heading-transclude class="ng-binding">
First Tab
</a>
</li>
<li ng-class="..." heading="Second Tab" class="...">
<a href ng-click="select()" tab-heading-transclude class="ng-binding">
Second Tab
</a>
</li>
</ul>
<div class="tab-content">
<!-- tab contents here -->
</div>
...
The problem I have, is the heading links can't be selected via the keyboard because they're missing a tabindex. Obviously, I can't just add that in because angular is creating the filler HTML for the list, and adding a tabindex to the tab element next to the heading attribute just adds it to the li and not the a tag where it needs to be.
Is there a way to define a tabset and also pass in an attribute like a tabindex to be placed on the navigation (heading) links?

Trouble with active tab default using AngularJS, UI Boostrap, and UI Router

When using a UI Boostrap tabset along with nested sticky states created with ui-router and ui-router-extras, I have an issue where navigating to a tab's state via URL will select the first tab along with the correct tab. It should only activate the tab whose state matches the URL route.
Here's what the tabset looks like:
<div style="position:relative">
<tabset>
<tab heading="Dashboard" ui-sref="LMS.Dashboard" ui-sref-active="active"></tab>
<tab heading="Modules" ui-sref="LMS.Modules" ui-sref-active="active"></tab>
<tab heading="Messages" ui-sref="LMS.Messages" ui-sref-active="active"></tab>
<tab heading="Settings" ui-sref="LMS.Settings" ui-sref-active="active"></tab>
</tabset>
<div ui-view="Dashboard" class="tab-content" ng-show="$state.includes('LMS.Dashboard')">
<h2>Dashboard</h2>
{{test}}
</div>
<div ui-view="Modules" class="tab-content" ng-show="$state.includes('LMS.Modules')">
<h2>Modules</h2>
</div>
<div ui-view="Messages" class="tab-content" ng-show="$state.includes('LMS.Messages')">
<h2>Messages</h2>
</div>
<div ui-view="Settings" class="tab-content" ng-show="$state.includes('LMS.Settings')">
<h2>Settings</h2>
</div>
</div>
I have a plunker here:
http://plnkr.co/edit/sQB58YKntDwNIUpAdLmT?p=preview
To see the issue, select a tab other than 'Dashboard', then reload the "live view" frame.
Another way is to open it in a window, switch the tab, then reload.
I have the same issue. Add active="false" to disable default behavior and use ui-sref-active to add active class.
<tab ui-sref-active="active" active="false">
Edit
While this method seems to works, it produces error because false is not assignable.
Edit 2
Combining ng-init with a local scope variable seems to do the trick.
<tab ui-sref-active="active" active="isActive" ng-init="isActive=false">
In your case, it might be simpler to just add an active variable for each tab. See this plunker:
http://plnkr.co/edit/73lm068buZf851h47FVQ?p=preview
I had exactly the same thing. After searching for while, I decided the "value" ui-bootstrap offers around tabs is not worth the effort. My simple manual implementation:
<ul class="nav nav-tabs">
<li ng-class="{active:$state.current.name == 'properties.edit.basic'}"><a ui-sref="properties.edit.basic">Basic</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.marketing'}"><a ui-sref="properties.edit.marketing">Marketing</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.rooms'}"><a ui-sref="properties.edit.rooms">Rooms</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.images'}"><a ui-sref="properties.edit.images">Images</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.rates'}"><a ui-sref="properties.edit.rates">Rates</a></li>
<li ng-class="{active:$state.current.name == 'properties.edit.availability'}"><a ui-sref="properties.edit.availability">Availability</a></li>
</ul>
<ui-view></ui-view>

Resources