react-tabs icon indicating copy to clipboard operation
react-tabs copied to clipboard

Nested elements with `role='tab'` are triggering tab change

Open raulchedrese opened this issue 7 years ago • 5 comments

If any child element of a TabPanel has role='tab' clicking on that element will cause the selected tab to become the first tab.

Example:

Clicking on <span>hello</hello> will cause the selected tab to change.

import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';

export default () => (
  <Tabs>
    <TabList>
      <Tab>Title 1</Tab>
      <Tab>Title 2</Tab>
    </TabList>

    <TabPanel>
      <h2>Any content 1</h2>
    </TabPanel>
    <TabPanel>
      <h2>Any content 2</h2>


      <div role='tab'>
          <span>hello</span>
      </div>
    </TabPanel>
  </Tabs>
);

Use Case: Seems plausible that someone might want to use the 'tab' role on a nested element. In my particular case I'm using https://github.com/react-component/collapse within a TabPanel.

raulchedrese avatar Mar 26 '18 17:03 raulchedrese

I am managing the selectedIndex state myself and using e.preventDefault(); on the nested role='tab' and a guard on e.defaultPrevented on the onSelect(index, lastIndex, e) event handler seems to be a temp work around if needed.

kharlamov avatar Apr 18 '18 17:04 kharlamov

Alternate solution: If you put role="button" on "AccordionItemTitle" then you don't get this error. Ex:

<AccordionItemTitle role="button" className="primaryAccordianTitle">
    <h5 className="u-position-relative">
          General Property Information
         <div className="accordion__arrow" role="presentation" />
     </h5>
 </AccordionItemTitle>

htthecool avatar Nov 13 '19 17:11 htthecool

These suggestions aren't really 'solutions', just work arounds to a dumb problem that shouldn't exist. Components shouldn't be relying on accessibility tags for functionality.

JonathonAshworth avatar Jan 15 '20 00:01 JonathonAshworth

Hack suggestion: I supplied a data-component-id to my main tabs.

<TabList className="node-tablist">
              <Tab data-component-id="main-tab">Tab 1</Tab>
              <Tab data-component-id="main-tab">Tab 2</Tab>
</TabList>

Then in the main parent tabs i checked this condition

          <Tabs
            className="main-tabs"
            // selectedIndex to be used when using tabs in controlled mode
            selectedIndex={state.currentTab}
            onSelect={(index, _, e) => {
              if (e.target.getAttribute('data-component-id') === 'main-tab') {
                dispatch({ type: 'currentTab', value: index });
              } else {
                return false;
              }
            }}
          >
            <TabList className="node-tablist">
              <Tab data-component-id="main-tab">Tab 1</Tab>
              <Tab data-component-id="main-tab">Tab 2</Tab>
            </TabList>
         </Tabs>

ayuaga0 avatar May 03 '21 12:05 ayuaga0

Clicking on nested elements with role="tab" activates the first tab in the ancestor react-tabs for me. Also hitting arrows on the keyboard changes react-tabs rather than the nested tabs the event is triggered on.

Worked around the issue by calling event.stopPropagation(). The problem must be solved in react-tabs though.

tigrr avatar Jun 23 '21 10:06 tigrr